Session 19.2 - Implementation Plan

Detailed plan to fix Universe vs Module architecture in vibe-universe-generator

Session 19.2: Implementation Plan

🎯 Goal

Transform the vibe-universe-generator from creating a single "platform module" to properly creating a Universe with separate Modules.


📊 Current vs Target Architecture

Current (WRONG)

// Saves ONE module called "Fitness Management"
ModuleContext {
  moduleId: "fitness-management-1767058598901",
  moduleName: "Fitness Management",
  entities: [Member, Trainer, Class, ...], // ALL entities mixed together
  actions: [...], // ALL actions mixed together
  embeddables: [...] // ALL embeddables mixed together
}

// Saved to: module-context:fitness-management-1767058598901
// Problem: This is NOT a module, it's a platform!

Target (CORRECT)

// 1. Create UNIVERSE
Universe {
  _id: "universe-fitness-management-1767058598901",
  name: "Fitness Management",
  slug: "fitness-management",
  modules: [
    "mod-member-management-xxx",
    "mod-trainer-management-xxx",
    "mod-class-schedule-xxx",
    ...
  ],
  structure: [...], // Module tree
  spaceId: "69250a03857479fe44376823"
}

// 2. Create 7 separate MODULES
SpaceModule {
  _id: "mod-member-management-xxx",
  name: "Member Management",
  slug: "member-management",
  universeId: "universe-fitness-management-1767058598901",
  scope: "universe",
  defaultConfig: {
    entities: [Member],
    actions: [CreateMember, UpdateMember, ...],
    embeddables: [MemberList, MemberCard, ...]
  }
}
// ... repeat for each module

🔧 Implementation Steps

Phase 1: Refactor deployToUniverse() Method

Current Issues:

New Implementation:

async deployToUniverse(): Promise<void> {
  const manifest = this.generatedManifest();
  const platformName = manifest.name;
  const platformSlug = platformName.toLowerCase().replace(/\s+/g, '-');
  
  // Step 1: Create or get Universe
  let universe = await this.spaceService.getUniverseBySlug(platformSlug);
  if (!universe) {
    universe = await this.spaceService.createUniverse({
      name: platformName,
      description: manifest.description
    });
  }
  
  // Step 2: Extract all modules from manifest
  const moduleNames = this.extractModulesFromNavigation(manifest);
  const createdModuleIds: string[] = [];
  
  // Step 3: Create each module separately
  for (const moduleName of moduleNames) {
    const moduleData = this.extractModuleDataFromManifest(manifest, moduleName);
    
    // Create module in space_modules collection
    const module = await firstValueFrom(
      this.backendModuleApi.createSpaceModule(spaceId, {
        name: moduleName,
        slug: toKebabCase(moduleName),
        type: 'feature-module',
        description: moduleData.description,
        icon: moduleData.icon,
        universeId: universe.id,
        scope: 'universe',
        defaultConfig: {
          entities: moduleData.entities,
          actions: moduleData.actions,
          embeddables: moduleData.embeddables
        },
        ai: {
          description: moduleData.description,
          keywords: [platformName, moduleName],
          capabilities: moduleData.entities.map(e => e.name),
          complexity: 'moderate',
          suggestionWeight: 80
        }
      })
    );
    
    createdModuleIds.push(module._id);
  }
  
  // Step 4: Update universe with modules
  await firstValueFrom(
    this.backendUniverseApi.updateUniverse(spaceId, universe.id, {
      modules: createdModuleIds,
      moduleTreeVersion: universe.moduleTreeVersion + 1
    })
  );
  
  // Step 5: Navigate to universe canvas
  this.router.navigate(['/space', spaceSlug, 'universe', platformSlug, 'canvas']);
}

Phase 2: Fix editModule() Method

Current: Creates a ModuleContext (for modularity-lib workbench) Target: Navigate to the actual generated module in the universe

New Implementation:

async editModule(moduleName: string): Promise<void> {
  const manifest = this.generatedManifest();
  const platformSlug = manifest.name.toLowerCase().replace(/\s+/g, '-');
  
  // Find the module in space_modules
  const modules = await firstValueFrom(
    this.backendModuleApi.getSpaceModules(spaceId, {
      universeId: `universe-${platformSlug}-xxx`,
      name: moduleName
    })
  );
  
  if (modules.length === 0) {
    this.toast.error('Module not found');
    return;
  }
  
  const module = modules[0];
  
  // Navigate to module in context of universe
  this.router.navigate([
    '/space', spaceSlug,
    'universe', platformSlug,
    'module', module.slug
  ]);
}

Phase 3: Fix proceedToWorkbench() Method

Current: Creates a single ModuleContext with all platform data Target: Navigate to universe canvas where user can arrange modules

New Implementation:

async proceedToWorkbench(): Promise<void> {
  const manifest = this.generatedManifest();
  const platformSlug = manifest.name.toLowerCase().replace(/\s+/g, '-');
  const spaceSlug = this.universeContext.spaceSlug();
  
  // Navigate to universe canvas (modular-universe)
  this.router.navigate([
    '/space', spaceSlug,
    'universe', platformSlug,
    'canvas'
  ], {
    queryParams: {
      source: 'vibe-universe-generator',
      newlyGenerated: 'true'
    }
  });
}

Phase 4: Enhance Module Cards

Add to each module card:

interface ModuleCardData {
  name: string;
  description: string;
  icon: string;
  
  // Counts
  entityCount: number;
  actionCount: number;
  embeddableCount: number;
  
  // Status
  status: 'draft' | 'ready' | 'deployed';
  
  // Links
  moduleId: string;
  universeId: string;
  universeName: string;
}

🗄️ MongoDB Schema Alignment

Universe Document

{
  _id: "universe-fitness-management-1767058598901",
  name: "Fitness Management",
  slug: "fitness-management",
  description: "Complete fitness management platform",
  spaceId: "69250a03857479fe44376823",
  
  // Module references (IDs only)
  modules: [
    "mod-member-management-xxx",
    "mod-trainer-management-xxx",
    ...
  ],
  
  // Structure (tree)
  structure: [
    {
      moduleId: "mod-member-management-xxx",
      order: 1,
      config: {}
    },
    ...
  ],
  
  deploymentStatus: "draft",
  moduleTreeVersion: 1,
  moduleSchemaVersion: "2025.12"
}

Module Document

{
  _id: "mod-member-management-xxx",
  name: "Member Management",
  slug: "member-management",
  type: "feature-module",
  description: "Manage gym members with profiles and memberships",
  icon: "fas fa-users",
  
  // Link to universe
  spaceId: "69250a03857479fe44376823",
  universeId: "universe-fitness-management-1767058598901",
  scope: "universe",
  
  // Module data
  defaultConfig: {
    entities: [
      {
        id: "entity-member-xxx",
        name: "Member",
        fields: [...]
      }
    ],
    actions: [
      {
        id: "action-create-member-xxx",
        name: "CreateMember",
        ...
      }
    ],
    embeddables: [
      {
        id: "emb-member-list-xxx",
        name: "MemberList",
        ...
      }
    ]
  },
  
  // AI metadata
  ai: {
    description: "Manage gym members",
    keywords: ["fitness", "member", "gym"],
    capabilities: ["Member"],
    complexity: "moderate",
    suggestionWeight: 80
  },
  
  isActive: true,
  order: 1
}

🔄 Service Integration

Services to Use

Service Purpose Method
SpaceService Create universe createUniverse(data)
BackendUniverseApiService Update universe updateUniverse(spaceId, universeId, updates)
BackendModuleApiService Create modules createSpaceModule(spaceId, moduleData)
UniverseModuleService Link modules to universe install(universeId, moduleData)

Proper Flow

// 1. Create Universe
const universe = await this.spaceService.createUniverse({
  name: platformName,
  description: manifest.description
});

// 2. Create each Module
for (const moduleName of moduleNames) {
  const moduleData = extractModuleDataFromManifest(manifest, moduleName);
  
  // Save to space_modules
  const module = await firstValueFrom(
    this.backendModuleApi.createSpaceModule(spaceId, {
      ...moduleData,
      universeId: universe.id,
      scope: 'universe'
    })
  );
  
  moduleIds.push(module._id);
}

// 3. Update Universe with module IDs
await firstValueFrom(
  this.backendUniverseApi.updateUniverse(spaceId, universe.id, {
    modules: moduleIds
  })
);

// 4. Navigate to universe canvas
this.router.navigate(['/space', spaceSlug, 'universe', universe.slug, 'canvas']);

🎨 UI Changes

Platform Summary Component

Before:

After:

Module Card Enhancement

<div class="module-card">
  <div class="module-header">
    <i class="fas {{ module.icon }}"></i>
    <h4>{{ module.name }}</h4>
  </div>
  
  <p class="module-description">{{ module.description }}</p>
  
  <div class="module-stats">
    <span><i class="fas fa-database"></i> {{ module.entityCount }} entities</span>
    <span><i class="fas fa-bolt"></i> {{ module.actionCount }} actions</span>
    <span><i class="fas fa-th-large"></i> {{ module.embeddableCount }} components</span>
  </div>
  
  <div class="module-actions">
    <button (click)="editModule(module)">
      <i class="fas fa-edit"></i> Edit
    </button>
    <button (click)="previewModule(module)">
      <i class="fas fa-eye"></i> Preview
    </button>
  </div>
</div>

✅ Success Criteria


📁 Files to Modify

File Changes
vibe-universe-generator.component.ts Refactor deployToUniverse(), editModule(), proceedToWorkbench()
platform-summary.component.ts Enhance module cards with metadata
platform-summary.component.html Update UI to show module details

Confidence Level: 97%

This architecture aligns with the Building Blocks Architecture and ensures proper separation of concerns.