2026 03 20 Library Absorption Module Builder Migration
Documentation for Plans
Library Absorption & Module Builder Migration — Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Absorb the useful parts of 4 architecturally-stuck libraries (modularity-lib, gograb-ai-lib, module-generator, modular-universe) into vitto-studio and vitto-chat, delete dead code, create a vitto-chat module-builder plugin, and ensure all NX libs compile and route correctly with zero deprecated references.
Architecture: Move modularity-lib's model types + cascade services + workbench UI into vitto-studio. Relocate gograb-ai-lib's active services (WorkflowStateService, VittoMonitorService, Image/VideoGenerationService) and 22 dashboard components into vitto-hub. Create a new vitto-chat plugin that wires module-building intelligence into chat. Delete module-generator, module-browser-lib, cursor-agents, multi-agent-dashboard, and all deprecated services. Update all imports monorepo-wide.
Tech Stack: Angular 20+, standalone components, signals, RxJS, NestJS, NX monorepo, vitest
Session: S248 | Prereq Plans: Platform Infrastructure Evolution
Review Fixes Applied (from plan-document-reviewer)
C1 (Missing ModularityModule/Manifest): Add modularity.module.ts and modularity.manifest.ts to Phase 3 Task 3.1 — copy to vitto-studio and update apps/gograb-space/src/app/app.config.ts import.
C2 (Oversimplified routes): Task 3.1 Step 5 must copy the FULL modularity.routes.ts (212 lines) including all WorkbenchStepRoutes children (models, state, actions, actions/:actionId, ui, test, deploy), ai-scaffold, test-export, and legacy redirects. Do NOT write a simplified version.
C3 (export * circular dep risk): ALL re-export shims must use NAMED exports, never export *. Example: export { ModuleContext, createEmptyModuleContext, calculateModuleProgress } from '@libs-structural/vitto-studio';
C4 (Steps directory location): The steps/ directory is a SIBLING of module-workbench/ in modularity-lib, NOT a child. Mirror this structure in vitto-studio: components/steps/ not components/module-workbench/steps/.
C5 (inject() outside injection context): Task 2.2 and 2.4 must use class-level inject() with { optional: true }, NOT inject() inside method bodies. Fix: private readonly vfs = inject(VfsService, { optional: true }); as a class field.
C6 (Missing gograb-ai-lib consumers): Services that STAY in gograb-ai-lib (not moved): AIFactoryService, AIOrchestratorService, VibeCodingOrchestratorService, AIModuleMatcherService, IntelligenceCoordinatorService, UniversalWidgetGeneratorService, GlobalAiSettingsService, TrainingDataExtractorService, PromptManagerPortalService, AnalyticsService, BackendAuthAdapterService, AiChatConfigService, AiChatLearningService, OrchestrationClientService. Components that STAY: AiChatCoreComponent, AiConfigComponent, AiModelSelectorComponent, ImageGenerationComponent, VideoGenerationComponent, VibeCodingInterfaceComponent, AgentPanelComponent, ModuleGenerationPanelComponent, AiGuideComponent, AiInfoComponent, AiConnectionStatusComponent, ApiKeyManagerComponent.
C7 (Missing @modular-universe alias): Task 5.2 Step 8 must also remove @modular-universe from tsconfig.base.json (not just @libs-structural/modular-universe).
C8 (tsconfig paths location): Library path aliases (@libs-structural/*, @libs-ai/*) are in tsconfig.base.json DIRECTLY, NOT in config/tsconfig-paths/. Task 5.2 Step 8 must edit tsconfig.base.json.
I1 (AIModuleReceiverService): Do NOT delete this service. Move it to vitto-studio with full functionality (SSE reception, backend fetch, reception state signals, getRecentModules()). Rewire from WorkflowSSEClientService to WorkflowStateService.
I2 (git add -A): Replace git add -A in Task 5.1 Step 7 with git add libs/ apps/ APIs/.
I3 (VittoObservabilityDataService): Add to Task 3.2 — move vitto-observability-data.service.ts and vitto-observability.types.ts to vitto-hub alongside ObservatoryDataService.
I4 (EnhancedImageGenerationService): Stays in gograb-ai-lib (internal wrapper, no external consumers outside the lib).
I5 (Plugin quickActions not reactive): Document as known limitation. The ChatPlugin interface defines quickActions as a static QuickAction[]. Future work: make it Signal<QuickAction[]> or a getter.
I6 (flow-engine-lib consumers): 5 files in flow-engine-lib import from @libs-ai/gograb-ai-lib. These STAY as-is since gograb-ai-lib is NOT deleted and these services remain in it. Add to Task 5.1 audit as "verified — no change needed."
S4 (space-map-lib consumer): space-map-lib/world-node.component.ts imports AiModelSelectorComponent from gograb-ai-lib. This STAYS since AiModelSelectorComponent remains in gograb-ai-lib.
Critical Risks & Mitigations
| Risk | Impact | Mitigation |
|---|---|---|
| Circular dependency when moving services between libs | Build fails monorepo-wide | Phase 1 moves ONLY models/types (no service deps). Services move in Phase 2 with re-export shims. |
| 22 gograb-ai-lib dashboard components reference internal services | Breaking those routes for gograb-dev/gograb-admin | Phase 3 moves components + their services together. Re-export barrel in gograb-ai-lib during transition. |
autoFlashState keys must not change |
Users lose persisted module data | Keep identical IndexedDB keys when moving ModuleContextService. |
| modularity routes registered in app.routes.ts | Route /modularity/workbench stops working |
Phase 2 re-exports from vitto-studio, app.routes.ts import path changes last. |
WorkflowSSEClientService has one live external consumer (ai-module-receiver.service.ts) |
Module registration after generation breaks | Phase 2 rewires AIModuleReceiverService to use WorkflowStateService instead before deleting WorkflowSSEClientService. |
File Map
New Files
| File | Responsibility |
|---|---|
libs/libs-structural/vitto-studio/src/lib/models/module-context.model.ts |
ModuleContext + factory functions (moved from modularity-lib) |
libs/libs-structural/vitto-studio/src/lib/models/entity-definition.model.ts |
EntityDefinition + factories (moved) |
libs/libs-structural/vitto-studio/src/lib/models/action-definition-v2.model.ts |
ActionDefinitionV2 + CRUD factory (moved) |
libs/libs-structural/vitto-studio/src/lib/models/embeddable-v2.model.ts |
EmbeddableDefinitionV2 + factories (moved) |
libs/libs-structural/vitto-studio/src/lib/models/state-definition.model.ts |
StateDefinition + factories (moved) |
libs/libs-structural/vitto-studio/src/lib/models/action-flow.model.ts |
ActionFlow + block templates (moved) |
libs/libs-structural/vitto-studio/src/lib/models/ai-metadata.model.ts |
AITrainableMetadata (moved) |
libs/libs-structural/vitto-studio/src/lib/models/index.ts |
Models barrel |
libs/libs-structural/vitto-studio/src/lib/adapters/phase-result-to-module-context.adapter.ts |
Vitto→ModuleContext seam (moved) |
libs/libs-structural/vitto-studio/src/lib/services/module-context.service.ts |
Central module state + cascade logic (moved, refactored for VFS) |
libs/libs-structural/vitto-studio/src/lib/services/module-validation.service.ts |
Quality gate (moved) |
libs/libs-structural/vitto-studio/src/lib/services/module-export.service.ts |
Real code generation → VFS (moved, stubs replaced) |
libs/libs-structural/vitto-studio/src/lib/services/module-storage.service.ts |
Module catalog (moved) |
libs/libs-structural/vitto-studio/src/lib/services/module-sync.service.ts |
MongoDB sync (moved) |
libs/libs-structural/vitto-studio/src/lib/services/flow-integration.service.ts |
Flow validation + code gen (moved) |
libs/libs-structural/vitto-studio/src/lib/services/action-flow-storage.service.ts |
Per-action flow persistence (moved) |
libs/libs-structural/vitto-studio/src/lib/services/contextual-block.service.ts |
Block palette (moved) |
libs/libs-structural/vitto-studio/src/lib/services/entity-extraction.service.ts |
AI entity extraction (moved) |
libs/libs-structural/vitto-studio/src/lib/services/embeddable-to-widget-mapper.service.ts |
Module→PageBuilder bridge (moved) |
libs/libs-structural/vitto-studio/src/lib/services/modularity-integration.service.ts |
Cross-tool events (moved, deploy wired to VFS) |
libs/libs-structural/vitto-studio/src/lib/services/workflow-state.service.ts |
Live SSE bridge to Vitto generation (moved from gograb-ai-lib) |
libs/libs-structural/vitto-studio/src/lib/components/module-workbench/ |
Full workbench UI (moved from modularity-lib) |
libs/libs-structural/vitto-studio/src/lib/components/module-workbench/steps/ |
6 step components (moved) |
libs/libs-structural/vitto-studio/src/lib/components/action-flow-builder/ |
Visual flow canvas (moved) |
libs/libs-structural/vitto-studio/src/lib/components/modularity-dashboard/ |
Module dashboard (moved) |
libs/libs-structural/vitto-studio/src/lib/components/module-card/ |
Module card (moved) |
libs/libs-structural/vitto-studio/src/lib/components/ai-builder/ |
AI module builder (moved) |
libs/libs-ai/vitto-chat/src/lib/plugins/module-builder.plugin.ts |
NEW: Module builder chat plugin |
libs/libs-ai/vitto-hub/src/lib/components/dashboards/ |
Dashboard components (moved from gograb-ai-lib) |
libs/libs-ai/vitto-hub/src/lib/services/vitto-monitor.service.ts |
VittoMonitorService (moved from gograb-ai-lib) |
libs/libs-ai/vitto-hub/src/lib/services/observatory-data.service.ts |
ObservatoryDataService (moved from gograb-ai-lib) |
libs/libs-ai/vitto-hub/src/lib/types/vitto.types.ts |
Vitto types (moved from gograb-ai-lib) |
Deleted Files/Directories
| Path | Reason |
|---|---|
libs/libs-ai/module-generator/ |
Entirely replaced by backend 6-phase pipeline |
libs/libs-structural/module-browser-lib/ |
Only consumer was stranded ModularUniverseBuilderComponent |
libs/libs-ai/cursor-agents/ |
Empty directory |
libs/libs-ai/multi-agent-dashboard/ |
Empty directory |
libs/libs-structural/modularity-lib/ |
All useful code absorbed into vitto-studio |
libs/libs-structural/modular-universe/ |
Live renderers moved to universe-canvas, rest dead |
Modified Files (key ones)
| File | Change |
|---|---|
libs/libs-structural/vitto-studio/src/index.ts |
Add all new exports |
libs/libs-ai/vitto-chat/src/index.ts |
Add module-builder plugin export |
libs/libs-ai/vitto-chat/src/lib/plugins/plugin-presets.ts |
Register module-builder plugin |
libs/libs-ai/vitto-hub/src/index.ts |
Add dashboard component + service exports |
apps/gograb-space/src/app/app.routes.ts |
Change modularity import from modularity-lib → vitto-studio |
apps/gograb-dev/src/app/app.routes.ts |
Change 17 dashboard imports from gograb-ai-lib → vitto-hub |
apps/gograb-admin/src/app/app.routes.ts |
Change 3 dashboard imports from gograb-ai-lib → vitto-hub |
apps/gograb-ai/src/app/app.routes.ts |
Change 2 component imports from gograb-ai-lib → vitto-hub |
tsconfig.base.json or config/tsconfig-paths/ |
Remove path aliases for deleted libs |
All files importing from @libs-structural/modularity-lib |
Update to @libs-structural/vitto-studio |
All files importing from @libs-ai/module-generator |
Update to @libs-structural/vitto-studio (types only) |
All files importing WorkflowStateService from @libs-ai/gograb-ai-lib |
Update to @libs-structural/vitto-studio |
All files importing VittoMonitorService from @libs-ai/gograb-ai-lib |
Update to @libs-ai/vitto-hub |
Phase 1: Move Models & Types (zero runtime risk)
Impact: Pure file moves. No behavior change. All imports updated. Models are pure TypeScript types + factory functions with zero service dependencies, so this is safe to do first.
Task 1.1: Move modularity-lib models to vitto-studio
Files:
Create:
libs/libs-structural/vitto-studio/src/lib/models/module-context.model.tsCreate:
libs/libs-structural/vitto-studio/src/lib/models/entity-definition.model.tsCreate:
libs/libs-structural/vitto-studio/src/lib/models/action-definition-v2.model.tsCreate:
libs/libs-structural/vitto-studio/src/lib/models/embeddable-v2.model.tsCreate:
libs/libs-structural/vitto-studio/src/lib/models/state-definition.model.tsCreate:
libs/libs-structural/vitto-studio/src/lib/models/action-flow.model.tsCreate:
libs/libs-structural/vitto-studio/src/lib/models/ai-metadata.model.tsCreate:
libs/libs-structural/vitto-studio/src/lib/models/index.tsModify:
libs/libs-structural/vitto-studio/src/index.tsStep 1: Create models directory in vitto-studio
mkdir -p libs/libs-structural/vitto-studio/src/lib/models
- Step 2: Copy all 7 model files
Copy each model file from libs/libs-structural/modularity-lib/src/lib/models/ to libs/libs-structural/vitto-studio/src/lib/models/. The files are pure types + factory functions with no Angular service imports, so they copy cleanly:
module-context.model.tsentity-definition.model.tsaction-definition-v2.model.tsembeddable-v2.model.tsstate-definition.model.tsaction-flow.model.tsai-metadata.model.ts
Update any internal cross-imports within the model files to use relative paths (they should already be relative).
- Step 3: Create models barrel
Create libs/libs-structural/vitto-studio/src/lib/models/index.ts re-exporting all model files.
- Step 4: Add models to vitto-studio index.ts
Add to libs/libs-structural/vitto-studio/src/index.ts:
// Module Builder Models
export * from './lib/models';
- Step 5: Create re-export shim in modularity-lib
Update libs/libs-structural/modularity-lib/src/lib/models/index.ts to re-export from vitto-studio:
// DEPRECATED: These models have moved to @libs-structural/vitto-studio
// This re-export exists for backward compatibility during migration.
export * from '@libs-structural/vitto-studio';
This ensures ALL existing consumers keep working without any import changes yet.
- Step 6: Verify build
Run: npx nx build vitto-studio --skip-nx-cache
Expected: Build succeeds with models exported.
- Step 7: Commit
git add libs/libs-structural/vitto-studio/src/lib/models/ libs/libs-structural/vitto-studio/src/index.ts libs/libs-structural/modularity-lib/src/lib/models/index.ts
git commit -m "[S248.1] refactor: move modularity-lib models to vitto-studio with re-export shim"
Task 1.2: Move vitto.types.ts to vitto-hub
Files:
Create:
libs/libs-ai/vitto-hub/src/lib/types/vitto.types.tsModify:
libs/libs-ai/vitto-hub/src/index.tsModify:
libs/libs-ai/gograb-ai-lib/src/lib/types/vitto.types.ts(shim)Step 1: Copy types file
Copy libs/libs-ai/gograb-ai-lib/src/lib/types/vitto.types.ts to libs/libs-ai/vitto-hub/src/lib/types/vitto.types.ts.
Check: any imports from ../ or relative paths inside the types file that reference gograb-ai-lib internals. If found, inline the types or adjust imports.
- Step 2: Export from vitto-hub index
Add to libs/libs-ai/vitto-hub/src/index.ts:
// Vitto Types
export * from './lib/types/vitto.types';
- Step 3: Create re-export shim in gograb-ai-lib
Update libs/libs-ai/gograb-ai-lib/src/lib/types/vitto.types.ts to:
// DEPRECATED: These types have moved to @libs-ai/vitto-hub
export * from '@libs-ai/vitto-hub';
- Step 4: Verify build
Run: npx nx build vitto-hub --skip-nx-cache
Expected: Build succeeds.
- Step 5: Commit
git add libs/libs-ai/vitto-hub/src/lib/types/ libs/libs-ai/vitto-hub/src/index.ts libs/libs-ai/gograb-ai-lib/src/lib/types/vitto.types.ts
git commit -m "[S248.1] refactor: move vitto.types.ts to vitto-hub with re-export shim"
Task 1.3: Move module-generator types to vitto-studio
Files:
Modify:
libs/libs-structural/vitto-studio/src/lib/models/index.tsModify:
libs/libs-ai/module-generator/src/index.ts(shim)Step 1: Extract useful types from module-generator
Read libs/libs-ai/module-generator/src/lib/types/module-generation.types.ts. Extract ONLY:
GeneratedModuleinterfaceGeneratedCodeModuleinterfacegeneratedModuleToUniversalModule()utility
Add these to a new file: libs/libs-structural/vitto-studio/src/lib/models/generated-module.model.ts
- Step 2: Export from vitto-studio models barrel
Add to libs/libs-structural/vitto-studio/src/lib/models/index.ts:
export * from './generated-module.model';
- Step 3: Create re-export shim in module-generator
Update libs/libs-ai/module-generator/src/index.ts to re-export the types:
// DEPRECATED: Types moved to @libs-structural/vitto-studio
export { GeneratedModule, GeneratedCodeModule, generatedModuleToUniversalModule } from '@libs-structural/vitto-studio';
- Step 4: Verify build
Run: npx nx build vitto-studio --skip-nx-cache
Expected: Build succeeds.
- Step 5: Commit
git add libs/libs-structural/vitto-studio/src/lib/models/ libs/libs-ai/module-generator/src/index.ts
git commit -m "[S248.1] refactor: move GeneratedModule types to vitto-studio"
Phase 2: Move Services to vitto-studio (the core migration)
Impact: Services move with full functionality. Re-export shims ensure zero breakage. The key change is wiring ModuleExportService to VFS and replacing stubs with real code gen.
Task 2.1: Move PhaseResultToModuleContextAdapter
Files:
Create:
libs/libs-structural/vitto-studio/src/lib/adapters/phase-result-to-module-context.adapter.tsModify:
libs/libs-structural/modularity-lib/src/lib/adapters/phase-result-to-module-context.adapter.ts(shim)Step 1: Copy adapter file
Copy libs/libs-structural/modularity-lib/src/lib/adapters/phase-result-to-module-context.adapter.ts to libs/libs-structural/vitto-studio/src/lib/adapters/.
Update model imports to use relative ../models/ paths instead of ../models/ (same, since we moved models already).
- Step 2: Copy adapter tests
Copy libs/libs-structural/modularity-lib/src/lib/adapters/phase-result-to-module-context.adapter.spec.ts to libs/libs-structural/vitto-studio/src/lib/adapters/.
- Step 3: Export from vitto-studio index
Add to libs/libs-structural/vitto-studio/src/index.ts:
export { PhaseResultToModuleContextAdapter } from './lib/adapters/phase-result-to-module-context.adapter';
- Step 4: Create re-export shim
Update modularity-lib adapter to re-export:
export { PhaseResultToModuleContextAdapter } from '@libs-structural/vitto-studio';
- Step 5: Run adapter tests
Run: npx vitest run libs/libs-structural/vitto-studio/src/lib/adapters/ --reporter=verbose
Expected: PASS
- Step 6: Commit
git add libs/libs-structural/vitto-studio/src/lib/adapters/ libs/libs-structural/modularity-lib/src/lib/adapters/
git commit -m "[S248.1] refactor: move PhaseResultToModuleContextAdapter to vitto-studio"
Task 2.2: Move ModuleContextService (the cascade engine)
Files:
Create:
libs/libs-structural/vitto-studio/src/lib/services/module-context.service.tsStep 1: Copy service file
Copy libs/libs-structural/modularity-lib/src/lib/services/module-context.service.ts to libs/libs-structural/vitto-studio/src/lib/services/.
Update imports:
Model imports →
../models/(already in vitto-studio)ModuleSyncService→ will be moved in Task 2.4 (use@Optional()injection as the original does)Step 2: Preserve autoFlashState keys
CRITICAL: The autoFlashState keys in this service MUST remain identical:
'current-module-context'(database:'modularity', collection:'module_contexts')'module-context:{moduleId}'for individual modules
Verify these keys match the original. If they change, users lose all persisted module data.
- Step 3: Add VFS write hook to the cascade
Add optional class-level injections (NOT inside methods — Angular requires injection context):
// Class-level optional injections:
private readonly vfs = inject(VfsService, { optional: true });
private readonly exportService = inject(ModuleExportService, { optional: true });
// At the end of addEntity(), after all cascade operations:
private writeModuleToVfs(context: ModuleContext): void {
if (!this.vfs || !this.exportService) return; // Not in studio context
const files = this.exportService.generateModuleFiles(context);
for (const file of files) {
this.vfs.writeFile(file.path, file.content);
}
}
This is optional injection — the service works without VFS (for non-studio contexts like the modularity dashboard).
- Step 4: Export and shim
Add to vitto-studio index.ts. Create re-export shim in modularity-lib services barrel.
- Step 5: Verify build
Run: npx nx build vitto-studio --skip-nx-cache
Expected: Build succeeds (with some services still referencing modularity-lib).
- Step 6: Commit
git add libs/libs-structural/vitto-studio/src/lib/services/module-context.service.ts libs/libs-structural/vitto-studio/src/index.ts libs/libs-structural/modularity-lib/src/lib/services/module-context.service.ts
git commit -m "[S248.1] refactor: move ModuleContextService to vitto-studio with VFS write hook"
Task 2.3: Move ModuleExportService — replace stubs with real code gen
Files:
- Create:
libs/libs-structural/vitto-studio/src/lib/services/module-export.service.ts
This is the most important task. The current service has placeholder implementations. We replace them with code that generates the same Angular patterns as the Vitto 6-phase pipeline.
- Step 1: Copy service and identify stubs
Copy libs/libs-structural/modularity-lib/src/lib/services/module-export.service.ts.
Identify all stub/placeholder code:
generateActionClass()→ placeholderexecute()bodygenerateModuleClass()→ lifecycle stubsAny
// TODOcommentsStep 2: Implement real
generateActionClass()
Replace the stub with code that generates a real Angular service:
generateActionClass(action: ActionDefinitionV2, context: ModuleContext): string {
const entityName = this.getEntityName(action, context);
const inputs = action.inputs.map(i => `${i.name}: ${this.tsType(i.type)}`).join(', ');
const outputType = action.outputs.length > 0
? this.tsType(action.outputs[0].type)
: 'void';
return `import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { API_BASE_URL } from '@libs-foundational/core-angular';
@Injectable({ providedIn: 'root' })
export class ${action.name}Service {
private readonly http = inject(HttpClient);
private readonly apiUrl = inject(API_BASE_URL);
execute(${inputs}): Observable<${outputType}> {
${this.generateHttpCall(action, entityName)}
}
}
`;
}
private generateHttpCall(action: ActionDefinitionV2, entityName: string): string {
const basePath = `\${this.apiUrl}/api/${entityName.toLowerCase()}s`;
switch (action.category) {
case 'crud':
if (action.name.startsWith('getAll')) return `return this.http.get<${entityName}[]>(\`${basePath}\`);`;
if (action.name.startsWith('get')) return `return this.http.get<${entityName}>(\`${basePath}/\${id}\`);`;
if (action.name.startsWith('create')) return `return this.http.post<${entityName}>(\`${basePath}\`, data);`;
if (action.name.startsWith('update')) return `return this.http.put<${entityName}>(\`${basePath}/\${id}\`, data);`;
if (action.name.startsWith('delete')) return `return this.http.delete<void>(\`${basePath}/\${id}\`);`;
return `return this.http.post(\`${basePath}/\${action.name}\`, {});`;
default:
return `return this.http.post(\`${basePath}/\${action.name}\`, { ${action.inputs.map(i => i.name).join(', ')} });`;
}
}
- Step 3: Implement real
generateModuleFiles()
New method that returns a complete { path, content }[] for a module:
generateModuleFiles(context: ModuleContext): Array<{ path: string; content: string }> {
const slug = context.moduleSlug;
const category = context.category || 'general';
const basePath = `modules/${category}/${slug}`;
const files: Array<{ path: string; content: string }> = [];
// 1. Entity models
for (const entity of context.entities) {
files.push({
path: `${basePath}/models/${entity.name.toLowerCase()}.model.ts`,
content: generateEntityInterface(entity),
});
}
// 2. Services (one per entity with real CRUD)
for (const entity of context.entities) {
const actions = context.actions.filter(a => a.sourceEntityId === entity.id);
files.push({
path: `${basePath}/services/${entity.name.toLowerCase()}.service.ts`,
content: this.generateEntityService(entity, actions, context),
});
}
// 3. Components (list + detail per entity)
for (const entity of context.entities) {
files.push(
{
path: `${basePath}/components/${entity.name.toLowerCase()}-list/${entity.name.toLowerCase()}-list.component.ts`,
content: this.generateListComponent(entity, context),
},
{
path: `${basePath}/components/${entity.name.toLowerCase()}-list/${entity.name.toLowerCase()}-list.component.html`,
content: this.generateListTemplate(entity, context),
},
{
path: `${basePath}/components/${entity.name.toLowerCase()}-list/${entity.name.toLowerCase()}-list.component.scss`,
content: this.generateListStyles(),
},
{
path: `${basePath}/components/${entity.name.toLowerCase()}-detail/${entity.name.toLowerCase()}-detail.component.ts`,
content: this.generateDetailComponent(entity, context),
},
{
path: `${basePath}/components/${entity.name.toLowerCase()}-detail/${entity.name.toLowerCase()}-detail.component.html`,
content: this.generateDetailTemplate(entity, context),
},
{
path: `${basePath}/components/${entity.name.toLowerCase()}-detail/${entity.name.toLowerCase()}-detail.component.scss`,
content: this.generateDetailStyles(),
},
);
}
// 4. Routes
files.push({
path: `${basePath}/${slug}.routes.ts`,
content: this.generateRoutesFile(context),
});
// 5. Index barrel
files.push({
path: `${basePath}/index.ts`,
content: this.generateIndexFile(context),
});
return files;
}
- Step 4: Implement component generators using SDK (ggs-*) components
The generated components must use the real SDK components from @libs-core/ui-framework:
private generateListTemplate(entity: EntityDefinition, context: ModuleContext): string {
const displayFields = entity.fields.filter(f => f.uiHints?.showInList !== false && f.name !== 'id');
const columns = displayFields.map(f => `{ field: '${f.name}', header: '${this.humanize(f.name)}' }`);
return `<div class="module-page">
<div class="page-header">
<h1>${this.humanize(entity.pluralName || entity.name + 's')}</h1>
<button ggs-button variant="primary" (click)="onCreate()">
<i class="fas fa-plus"></i> Create ${entity.name}
</button>
</div>
<ggs-table
[data]="items()"
[columns]="columns"
[loading]="loading()"
(rowClick)="onRowClick($event)">
</ggs-table>
</div>`;
}
- Step 5: Write tests for code generation
Create libs/libs-structural/vitto-studio/src/lib/services/__tests__/module-export.service.spec.ts:
describe('ModuleExportService', () => {
it('should generate valid TypeScript service for CRUD entity', () => {
const context = createEmptyModuleContext('Users', 'crud');
const entity = createEntityWithDefaults('User');
context.entities = [entity];
context.actions = createCrudActionsForEntity(entity.id, 'User', 'Users', entity.fields);
const files = service.generateModuleFiles(context);
const serviceFile = files.find(f => f.path.includes('user.service.ts'));
expect(serviceFile).toBeDefined();
expect(serviceFile!.content).toContain('inject(HttpClient)');
expect(serviceFile!.content).toContain('inject(API_BASE_URL)');
expect(serviceFile!.content).not.toContain('// TODO');
expect(serviceFile!.content).not.toContain('placeholder');
});
it('should generate list component using ggs-table', () => {
const context = createEmptyModuleContext('Users', 'crud');
const entity = createEntityWithDefaults('User');
context.entities = [entity];
const files = service.generateModuleFiles(context);
const template = files.find(f => f.path.includes('-list.component.html'));
expect(template).toBeDefined();
expect(template!.content).toContain('ggs-table');
expect(template!.content).toContain('ggs-button');
});
it('should generate routes file with real Angular routes', () => {
const context = createEmptyModuleContext('Tasks', 'crud');
const entity = createEntityWithDefaults('Task');
context.entities = [entity];
const files = service.generateModuleFiles(context);
const routes = files.find(f => f.path.includes('.routes.ts'));
expect(routes).toBeDefined();
expect(routes!.content).toContain('Routes');
expect(routes!.content).toContain('loadComponent');
});
});
- Step 6: Run tests
Run: npx vitest run libs/libs-structural/vitto-studio/src/lib/services/__tests__/module-export.service.spec.ts --reporter=verbose
Expected: ALL PASS
- Step 7: Commit
git add libs/libs-structural/vitto-studio/src/lib/services/module-export.service.ts libs/libs-structural/vitto-studio/src/lib/services/__tests__/
git commit -m "[S248.1] feat: real code generation in ModuleExportService — no stubs, uses SDK components"
Task 2.4: Move remaining services (batch)
Files: All remaining services from modularity-lib to vitto-studio.
- Step 1: Copy remaining services
Move these services (copy + update imports + re-export shim):
module-validation.service.tsmodule-storage.service.tsmodule-sync.service.tsflow-integration.service.tsaction-flow-storage.service.tscontextual-block.service.tsentity-extraction.service.tsembeddable-to-widget-mapper.service.tsmodularity-integration.service.tsplatform-state.service.tstool-navigation.service.ts
Each service: update model imports to ../models/, update service cross-imports to relative paths.
- Step 2: Wire
modularity-integration.service.tsdeploy to VFS
Replace the TODO: Call backend API in deployToWorkspace(). Use class-level injections (already injected at class level, NOT inside the method):
// Class-level (already injected):
private readonly exportService = inject(ModuleExportService);
private readonly vfsService = inject(VfsService, { optional: true });
async deployToWorkspace(context: ModuleContext): Promise<void> {
const files = this.exportService.generateModuleFiles(context);
if (this.vfsService) {
for (const file of files) {
this.vfsService.writeFile(file.path, file.content);
}
}
this.platformEvents$.next({
type: 'GENERATION_COMPLETED',
moduleId: context.moduleId,
timestamp: Date.now(),
});
}
- Step 3: Delete
ai-module-generator.service.ts(NOT moved)
This service uses setTimeout-based fake generation. It's superseded by WorkflowStateService. Do NOT move it.
- Step 4: Delete
ai-reactive-analysis.service.ts(NOT moved)
The 14-keyword heuristic analysis is superseded by EntityExtractionService (Anthropic-backed). The AI Builder component will use EntityExtractionService directly.
- Step 5: Delete
module-export-api.service.ts(NOT moved)
The backend endpoints it calls (/api/modules/export, /api/modules/register-nx) don't exist. Dead code.
- Step 6: Move
ai-module-receiver.service.tsto vitto-studio — rewire from WorkflowSSEClientService to WorkflowStateService
Move AIModuleReceiverService to vitto-studio (do NOT delete — it has substantial functionality: backend fetch, reception state signals, getRecentModules(), isReceiving computed).
Key change: replace the WorkflowSSEClientService.lastOrchestrationResult() effect with WorkflowStateService signals:
// Before (deprecated path):
// effect(() => {
// const result = this.workflowSSEClient.lastOrchestrationResult();
// if (result) this.receiveFromOrchestration(result);
// });
// After (active path via WorkflowStateService):
private readonly workflowState = inject(WorkflowStateService);
constructor() {
effect(() => {
const lastResult = this.workflowState.lastCompletedResult();
if (lastResult) this.receiveFromOrchestration(lastResult);
});
}
Also ensure StudioGenerationListenerService calls PhaseResultToModuleContextAdapter.adapt() on per-module SSE events so the workbench UI updates progressively:
// In StudioGenerationListenerService.handleModuleGenerated(), after writing files to VFS:
const moduleContext = this.adapter.adapt(event.data);
this.moduleContextService?.loadModuleContext(moduleContext);
- Step 7: Update modularity-lib services barrel to re-export from vitto-studio
Update libs/libs-structural/modularity-lib/src/lib/services/index.ts:
// DEPRECATED: All services moved to @libs-structural/vitto-studio
export * from '@libs-structural/vitto-studio';
- Step 8: Verify build
Run: npx nx build vitto-studio --skip-nx-cache && npx nx build modularity-lib --skip-nx-cache
Expected: Both build successfully.
- Step 9: Commit
git add libs/libs-structural/vitto-studio/src/lib/services/ libs/libs-structural/modularity-lib/src/lib/services/
git commit -m "[S248.1] refactor: move all modularity services to vitto-studio, delete dead services, wire deploy to VFS"
Task 2.5: Move WorkflowStateService to vitto-studio
Files:
Create:
libs/libs-structural/vitto-studio/src/lib/services/workflow-state.service.tsModify:
libs/libs-ai/gograb-ai-lib/src/lib/services/workflow-state.service.ts(shim)Step 1: Copy service
Copy libs/libs-ai/gograb-ai-lib/src/lib/services/workflow-state.service.ts to libs/libs-structural/vitto-studio/src/lib/services/.
Check imports: if it imports from ../types/vitto.types, update to @libs-ai/vitto-hub (where we moved the types in Task 1.2). If it imports other gograb-ai-lib internals, inline them.
- Step 2: Export from vitto-studio index and create shim
Export WorkflowStateService and all its types (WorkflowPhase, StartWorkflowRequest, WorkflowSSEEvent, ModuleManifest, ModuleGeneratedEvent) from vitto-studio.
Create re-export shim in gograb-ai-lib.
- Step 3: Verify all 6 external consumers still build
Run:
npx nx build vitto-studio --skip-nx-cache
npx nx build vitto-chat --skip-nx-cache
npx nx build vibe-universe --skip-nx-cache
Expected: All build (consuming via shim for now).
- Step 4: Commit
git add libs/libs-structural/vitto-studio/src/lib/services/workflow-state.service.ts libs/libs-ai/gograb-ai-lib/src/lib/services/workflow-state.service.ts libs/libs-structural/vitto-studio/src/index.ts
git commit -m "[S248.1] refactor: move WorkflowStateService to vitto-studio with re-export shim"
Phase 3: Move Components
Impact: Workbench UI moves to vitto-studio. Dashboard components move to vitto-hub. Routes updated.
Task 3.1: Move workbench components to vitto-studio
Files:
Create:
libs/libs-structural/vitto-studio/src/lib/components/module-workbench/Create:
libs/libs-structural/vitto-studio/src/lib/components/action-flow-builder/Create:
libs/libs-structural/vitto-studio/src/lib/components/modularity-dashboard/Create:
libs/libs-structural/vitto-studio/src/lib/components/module-card/Create:
libs/libs-structural/vitto-studio/src/lib/components/ai-builder/Create:
libs/libs-structural/vitto-studio/src/lib/components/module-creation-wizard/Step 1: Copy all component directories
Copy these directories from libs/libs-structural/modularity-lib/src/lib/components/ to libs/libs-structural/vitto-studio/src/lib/components/:
module-workbench/(includessteps/subdirectory with 6 step components)action-flow-builder/modularity-dashboard/module-card/ai-builder/module-creation-wizard/Step 2: Update all imports in copied components
In every copied .ts file:
from '@libs-structural/modularity-lib'→ relative imports to../../services/and../../models/from '@libs-ai/gograb-ai-lib'→from '@libs-structural/vitto-studio'(for WorkflowStateService)Verify template files (
.html) reference only components that exist in the target libStep 3: Fix ActionFlowBuilderComponent — convert @Input/@Output to signals
The current component uses legacy @Input()/@Output() decorators. Convert to signal-based:
// Before:
@Input() actionId: string;
@Input() actionName: string;
@Input() moduleId: string;
@Output() flowChanged = new EventEmitter<ActionFlow>();
// After:
readonly actionId = input.required<string>();
readonly actionName = input<string>('');
readonly moduleId = input<string>('');
readonly flowChanged = output<ActionFlow>();
- Step 4: Fix AIBuilderComponent — use EntityExtractionService instead of AIReactiveAnalysisService
The AI Builder currently uses the deleted AIReactiveAnalysisService (14-keyword heuristic). Replace with:
// Replace AIReactiveAnalysisService with EntityExtractionService
private readonly entityExtraction = inject(EntityExtractionService);
analyzeDescription(text: string): void {
this.entityExtraction.extract(text).subscribe(result => {
this.detectedEntities.set(result.entities);
this.analysisConfidence.set(result.confidence);
this.analysisSource.set(result.source); // 'ai' or 'local'
});
}
- Step 5: Create modularity routes file in vitto-studio
Create libs/libs-structural/vitto-studio/src/lib/routes/modularity.routes.ts:
import { Routes } from '@angular/router';
export const MODULARITY_ROUTES: Routes = [
{
path: '',
loadComponent: () => import('../components/modularity-dashboard/modularity-dashboard.component')
.then(m => m.ModularityDashboardComponent),
},
{
path: 'ai-builder',
loadComponent: () => import('../components/ai-builder/ai-builder.component')
.then(m => m.AIModuleBuilderComponent),
},
{
path: 'workbench',
loadComponent: () => import('../components/module-workbench/module-workbench.component')
.then(m => m.ModuleWorkbenchComponent),
},
{
path: 'workbench/:moduleId',
loadComponent: () => import('../components/module-workbench/module-workbench.component')
.then(m => m.ModuleWorkbenchComponent),
},
];
- Step 6: Export routes from vitto-studio index
export { MODULARITY_ROUTES } from './lib/routes/modularity.routes';
- Step 7: Create re-export shim for routes
Update libs/libs-structural/modularity-lib/src/index.ts to re-export routes:
export { MODULARITY_ROUTES as ModularityRoutes } from '@libs-structural/vitto-studio';
- Step 8: Verify build
Run: npx nx build vitto-studio --skip-nx-cache
Expected: Build succeeds.
- Step 9: Commit
git add libs/libs-structural/vitto-studio/src/lib/components/ libs/libs-structural/vitto-studio/src/lib/routes/ libs/libs-structural/vitto-studio/src/index.ts libs/libs-structural/modularity-lib/src/index.ts
git commit -m "[S248.1] feat: move workbench UI to vitto-studio, fix signal inputs, wire EntityExtractionService"
Task 3.2: Move dashboard components to vitto-hub
Files:
Create:
libs/libs-ai/vitto-hub/src/lib/components/dashboards/Create:
libs/libs-ai/vitto-hub/src/lib/services/vitto-monitor.service.tsCreate:
libs/libs-ai/vitto-hub/src/lib/services/observatory-data.service.tsCreate:
libs/libs-ai/vitto-hub/src/lib/services/vitto-observability-data.service.tsStep 1: Move VittoMonitorService
Copy libs/libs-ai/gograb-ai-lib/src/lib/services/vitto-monitor.service.ts → libs/libs-ai/vitto-hub/src/lib/services/.
Update type imports to use local ../types/vitto.types.
Create re-export shim in gograb-ai-lib.
- Step 2: Move ObservatoryDataService + VittoObservabilityDataService
Copy both services. Update imports. Create shims.
- Step 3: Move ImageGenerationService + VideoGenerationService
These are used by vitto-chat generation panels. Move to libs/libs-ai/vitto-hub/src/lib/services/.
Update the consumers in vitto-chat:
chat-image-panel.component.ts:from '@libs-ai/gograb-ai-lib'→from '@libs-ai/vitto-hub'chat-video-panel.component.ts: same
Create re-export shims in gograb-ai-lib.
- Step 4: Move the 22 active dashboard components
Copy these component directories from libs/libs-ai/gograb-ai-lib/src/lib/components/ to libs/libs-ai/vitto-hub/src/lib/components/dashboards/:
agent-observatory/observatory-dashboard/vitto-traces/ai-dashboard-v2/usage-dashboard/billing-dashboard/mcp-projects/agent-mesh-visualization/command-center/platform-intelligence-dashboard/cursor-agents-dashboard-enhanced/space-assistants-dashboard/intelligence-pyramid/trigger-monitor/orchestration-view/visual-memory-map/memory-browser/mcp-multi-platform-dashboard/agent-comparison-matrix/module-category-analysis/pattern-evolution-timeline/generation-pipeline-dashboard/ai-playground/
Update all service imports within these components to reference the local services (now in vitto-hub).
- Step 5: Export all from vitto-hub index
Add all dashboard components + services to libs/libs-ai/vitto-hub/src/index.ts.
- Step 6: Create re-export shims in gograb-ai-lib components barrel
Update libs/libs-ai/gograb-ai-lib/src/lib/components/index.ts to re-export moved components from @libs-ai/vitto-hub.
- Step 7: Verify builds
npx nx build vitto-hub --skip-nx-cache
npx nx build vitto-chat --skip-nx-cache
npx nx build gograb-ai-lib --skip-nx-cache
Expected: All build.
- Step 8: Commit
git add libs/libs-ai/vitto-hub/ libs/libs-ai/gograb-ai-lib/src/lib/services/ libs/libs-ai/gograb-ai-lib/src/lib/components/
git commit -m "[S248.1] refactor: move 22 dashboard components + services to vitto-hub"
Task 3.3: Move PageModuleRenderer + PageContentRenderer to universe-canvas
Files:
Create:
libs/libs-space/universe-canvas/src/lib/components/page-module-renderer/Create:
libs/libs-space/universe-canvas/src/lib/components/page-content-renderer/Step 1: Copy the two live renderers
These are the only active components from modular-universe. Move them to universe-canvas (where their only consumers live):
modular-universe/src/lib/components/page-module-renderer/→universe-canvas/src/lib/components/page-module-renderer/modular-universe/src/lib/components/page-content-renderer/→universe-canvas/src/lib/components/page-content-renderer/modular-universe/src/lib/components/widget-host/→universe-canvas/src/lib/components/widget-host/(used by PageContentRenderer)Step 2: Update imports in universe-canvas consumers
In canvas-section.component.ts and runtime-preview.component.ts: change imports from @libs-structural/modular-universe to relative paths.
- Step 3: Verify build
npx nx build universe-canvas --skip-nx-cache
Expected: Build succeeds.
- Step 4: Commit
git add libs/libs-space/universe-canvas/src/lib/components/
git commit -m "[S248.1] refactor: move PageModuleRenderer + PageContentRenderer to universe-canvas"
Phase 4: Create vitto-chat Module Builder Plugin
Impact: New functionality. Vitto becomes a module-building copilot.
Task 4.1: Create the module-builder plugin
Files:
Create:
libs/libs-ai/vitto-chat/src/lib/plugins/module-builder.plugin.tsModify:
libs/libs-ai/vitto-chat/src/lib/plugins/plugin-presets.tsModify:
libs/libs-ai/vitto-chat/src/index.tsStep 1: Write the plugin factory
Create libs/libs-ai/vitto-chat/src/lib/plugins/module-builder.plugin.ts:
import { Signal } from '@angular/core';
import { ChatPlugin, QuickAction, SlashCommandDefinition } from './chat-plugin.interface';
import { VittoRichContext } from '../types/chat.types';
export interface ModuleBuilderPluginConfig {
contextSignal: Signal<VittoRichContext | null>;
moduleContextSignal?: Signal<any>;
onEntityExtract?: (entities: string[]) => void;
onModuleGenerate?: (description: string) => void;
onModuleValidate?: () => void;
onModuleExport?: () => void;
}
export function createModuleBuilderPlugin(config: ModuleBuilderPluginConfig): ChatPlugin {
return {
id: 'module-builder',
label: 'Module Builder',
icon: 'puzzle-piece',
quickActions: buildQuickActions(config),
slashCommands: buildSlashCommands(config),
enrichMessage(msg) {
const ctx = config.contextSignal();
if (!ctx || ctx.contextType !== 'modularity') return msg;
const moduleCtx = config.moduleContextSignal?.();
if (!moduleCtx) return msg;
return {
...msg,
metadata: {
...msg.metadata,
moduleBuilder: {
moduleId: moduleCtx.moduleId,
moduleName: moduleCtx.moduleName,
entityCount: moduleCtx.entities?.length ?? 0,
actionCount: moduleCtx.actions?.length ?? 0,
embeddableCount: moduleCtx.embeddables?.length ?? 0,
progress: moduleCtx.progress ?? 0,
status: moduleCtx.status,
entities: moduleCtx.entities?.map((e: any) => ({
name: e.name,
fieldCount: e.fields?.length ?? 0,
})),
},
},
};
},
onContextChange(ctx: VittoRichContext) {
// No-op for now — could pre-load module context
},
onDrop(data) {
if (data.type === 'module') {
return {
id: `msg-${Date.now()}`,
role: 'user' as const,
content: `Analyze this module and suggest improvements: ${data.name || data.id}`,
timestamp: new Date(),
};
}
if (data.type === 'entity') {
return {
id: `msg-${Date.now()}`,
role: 'user' as const,
content: `Help me design actions and UI for the ${data.name || data.id} entity`,
timestamp: new Date(),
};
}
return null;
},
};
}
function buildQuickActions(config: ModuleBuilderPluginConfig): QuickAction[] {
const ctx = config.contextSignal();
if (!ctx || ctx.contextType !== 'modularity') return [];
const actions: QuickAction[] = [
{
id: 'mb-generate',
label: 'Build a module',
icon: 'wand-magic-sparkles',
message: 'I want to create a new module. Help me define the entities and their relationships.',
},
{
id: 'mb-extract-entities',
label: 'Extract entities',
icon: 'diagram-project',
message: 'Extract entities from this description: ',
},
];
const moduleCtx = config.moduleContextSignal?.();
if (moduleCtx) {
actions.push(
{
id: 'mb-validate',
label: 'Validate module',
icon: 'check-double',
handler: () => config.onModuleValidate?.(),
},
{
id: 'mb-export',
label: 'Export to VFS',
icon: 'file-export',
handler: () => config.onModuleExport?.(),
},
);
}
return actions;
}
function buildSlashCommands(config: ModuleBuilderPluginConfig): SlashCommandDefinition[] {
return [
{
name: 'module',
description: 'Module builder commands: create, entities, validate, export',
usage: '/module create <description> | /module entities <text> | /module validate | /module export',
category: 'generation',
handler: (args: string) => {
const [subcommand, ...rest] = args.trim().split(/\s+/);
const payload = rest.join(' ');
switch (subcommand) {
case 'create':
config.onModuleGenerate?.(payload);
break;
case 'entities':
config.onEntityExtract?.(payload.split(',').map(s => s.trim()));
break;
case 'validate':
config.onModuleValidate?.();
break;
case 'export':
config.onModuleExport?.();
break;
}
},
},
];
}
- Step 2: Register in plugin presets
Add to libs/libs-ai/vitto-chat/src/lib/plugins/plugin-presets.ts inside createStandardPluginSet():
// After generation plugin, before teach plugin:
if (!isConsumer) {
plugins.push(
createModuleBuilderPlugin({
contextSignal: config.contextSignal,
moduleContextSignal: config.moduleContextSignal,
onEntityExtract: config.onEntityExtract,
onModuleGenerate: config.onModuleGenerate,
onModuleValidate: config.onModuleValidate,
onModuleExport: config.onModuleExport,
}),
);
}
Update PluginPresetConfig interface to include the new optional fields.
- Step 3: Register welcome content for modularity context
Add to the welcome content registry initialization (wherever the host app registers contexts):
welcomeRegistry.register({
contextType: 'modularity',
subtitle: 'I can help you build modules — define entities, wire actions, and generate production code.',
starters: [
{ label: 'Build a module', message: 'I want to create a new module for managing...', icon: 'wand-magic-sparkles' },
{ label: 'Extract entities', message: 'Extract entities from this: ', icon: 'diagram-project' },
{ label: 'Validate current module', message: '/module validate', icon: 'check-double' },
],
capabilities: [
{ title: 'Entity Design', description: 'Extract entities from natural language and auto-generate CRUD', icon: 'database' },
{ title: 'Code Generation', description: 'Generate real Angular components using SDK (ggs-*) components', icon: 'code' },
{ title: 'Flow Builder', description: 'Design action flows with visual canvas and test execution', icon: 'route' },
{ title: 'Validation', description: 'Quality gate with weighted scoring before export', icon: 'shield-check' },
],
});
- Step 4: Export from vitto-chat index
Add to libs/libs-ai/vitto-chat/src/index.ts:
export { createModuleBuilderPlugin, ModuleBuilderPluginConfig } from './lib/plugins/module-builder.plugin';
- Step 5: Verify build
Run: npx nx build vitto-chat --skip-nx-cache
Expected: Build succeeds.
- Step 6: Commit
git add libs/libs-ai/vitto-chat/src/lib/plugins/module-builder.plugin.ts libs/libs-ai/vitto-chat/src/lib/plugins/plugin-presets.ts libs/libs-ai/vitto-chat/src/index.ts
git commit -m "[S248.1] feat: create module-builder plugin for vitto-chat — entity extraction, validation, VFS export"
Phase 5: Update All Imports & Delete Dead Libs
Impact: Remove all re-export shims. Update every import to point directly to the new locations. Delete the old libraries entirely.
Task 5.1: Update all imports monorepo-wide
- Step 1: Update modularity-lib imports
Search and replace across the monorepo:
# Find all files importing from @libs-structural/modularity-lib
grep -r "from '@libs-structural/modularity-lib'" --include='*.ts' -l
For each file: update import path from @libs-structural/modularity-lib → @libs-structural/vitto-studio.
Key files:
apps/gograb-space/src/app/app.routes.ts—ModularityRoutes→MODULARITY_ROUTESfrom@libs-structural/vitto-studioAPIs/backend-api/src/app/ai-agents/services/module-generation-agent.service.ts— model typesAPIs/backend-ai-api/src/app/workflow/phase-executor/phase-module-context.adapter.ts— model typesAll universe-canvas and vibe-universe files
Step 2: Update module-generator imports
grep -r "from '@libs-ai/module-generator'" --include='*.ts' -l
For each file: update import path to @libs-structural/vitto-studio (types only).
- Step 3: Update gograb-ai-lib service imports
grep -r "WorkflowStateService.*from '@libs-ai/gograb-ai-lib'" --include='*.ts' -l
grep -r "VittoMonitorService.*from '@libs-ai/gograb-ai-lib'" --include='*.ts' -l
grep -r "ImageGenerationService.*from '@libs-ai/gograb-ai-lib'" --include='*.ts' -l
grep -r "VideoGenerationService.*from '@libs-ai/gograb-ai-lib'" --include='*.ts' -l
Update:
WorkflowStateService→from '@libs-structural/vitto-studio'VittoMonitorService→from '@libs-ai/vitto-hub'ImageGenerationService→from '@libs-ai/vitto-hub'VideoGenerationService→from '@libs-ai/vitto-hub'Step 4: Update gograb-ai-lib component imports in app routes
Update lazy-load imports in:
apps/gograb-dev/src/app/app.routes.ts— 17 components →from '@libs-ai/vitto-hub'apps/gograb-admin/src/app/app.routes.ts— 3 components →from '@libs-ai/vitto-hub'apps/gograb-ai/src/app/app.routes.ts— 2 components →from '@libs-ai/vitto-hub'Step 5: Update modular-universe imports
grep -r "from '@libs-structural/modular-universe'" --include='*.ts' -l
Update PageModuleRenderer/PageContentRenderer consumers to import from @libs-space/universe-canvas.
- Step 6: Verify full monorepo build
npx nx run-many --target=build --projects=vitto-studio,vitto-chat,vitto-hub,gograb-space,gograb-dev,gograb-admin,gograb-ai --skip-nx-cache
Expected: All build successfully with zero @libs-structural/modularity-lib or @libs-ai/module-generator references remaining.
- Step 7: Commit
git add libs/ apps/ APIs/
git commit -m "[S248.1] refactor: update all imports from old libs to new locations"
Task 5.2: Delete dead libraries
- Step 1: Remove modularity-lib
rm -rf libs/libs-structural/modularity-lib/
- Step 2: Remove module-generator
rm -rf libs/libs-ai/module-generator/
- Step 3: Remove modular-universe
rm -rf libs/libs-structural/modular-universe/
- Step 4: Remove module-browser-lib
rm -rf libs/libs-structural/module-browser-lib/
- Step 5: Remove cursor-agents
rm -rf libs/libs-ai/cursor-agents/
- Step 6: Remove multi-agent-dashboard
rm -rf libs/libs-ai/multi-agent-dashboard/
- Step 7: Clean deprecated services from gograb-ai-lib
Delete these dead services from libs/libs-ai/gograb-ai-lib/src/lib/services/:
workflow-sse-client.service.ts(deprecated S204)generation-router.service.ts(deprecated S204)vitto-chat.service.ts(deprecated S133)
Delete their exports from the services barrel.
- Step 8: Remove tsconfig path aliases from
tsconfig.base.json
Library paths are in tsconfig.base.json DIRECTLY (NOT in config/tsconfig-paths/ — that directory is only for @module/* paths). Remove these entries from tsconfig.base.json compilerOptions.paths:
@libs-structural/modularity-lib@libs-ai/module-generator@libs-structural/modular-universe@modular-universe(separate alias, also in tsconfig.base.json)@libs-structural/module-browser-lib@libs-ai/cursor-agents(if present)
Note: @libs-ai/multi-agent-dashboard does NOT have a tsconfig entry (confirmed by grep).
- Step 9: Remove from NX workspace
Run nx reset to clear the project graph cache.
Verify:
npx nx show projects | grep -E 'modularity-lib|module-generator|modular-universe|module-browser-lib|cursor-agents|multi-agent-dashboard'
Expected: No output (all removed).
- Step 10: Verify full build
npx nx run-many --target=build --all --skip-nx-cache 2>&1 | tail -20
Expected: All projects build. Zero references to deleted libs.
- Step 11: Commit
git add -A
git commit -m "[S248.1] chore: delete 6 deprecated libraries — modularity-lib, module-generator, modular-universe, module-browser-lib, cursor-agents, multi-agent-dashboard"
Phase 6: E2E Tests
Impact: Validates the entire migration works end-to-end.
Task 6.1: Module workbench E2E test
Files:
Create:
libs/libs-structural/vitto-studio/src/lib/components/module-workbench/__tests__/module-workbench.e2e.spec.tsStep 1: Write E2E test for entity cascade
import { TestBed } from '@angular/core/testing';
import { ModuleContextService } from '../../../services/module-context.service';
import { createEmptyModuleContext, createEntityWithDefaults } from '../../../models';
describe('Module Workbench E2E: Entity Cascade', () => {
let contextService: ModuleContextService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ModuleContextService],
});
contextService = TestBed.inject(ModuleContextService);
});
it('should cascade entity addition to state, actions, embeddables, permissions, routes', () => {
const context = createEmptyModuleContext('Tasks', 'crud');
contextService.setContext(context);
const entity = createEntityWithDefaults('Task');
contextService.addEntity(entity);
const updated = contextService.context();
expect(updated!.entities).toHaveLength(1);
expect(updated!.stateDefinitions).toHaveLength(1); // auto-created
expect(updated!.actions.length).toBeGreaterThanOrEqual(5); // 5 CRUD actions
expect(updated!.embeddables).toHaveLength(2); // list + card
expect(updated!.permissions.length).toBeGreaterThanOrEqual(4); // read/create/update/delete
expect(updated!.routes.length).toBeGreaterThanOrEqual(2); // list + detail
});
it('should cascade entity removal — clean up all associated resources', () => {
const context = createEmptyModuleContext('Tasks', 'crud');
contextService.setContext(context);
const entity = createEntityWithDefaults('Task');
contextService.addEntity(entity);
contextService.removeEntity(entity.id);
const updated = contextService.context();
expect(updated!.entities).toHaveLength(0);
expect(updated!.stateDefinitions).toHaveLength(0);
expect(updated!.actions).toHaveLength(0);
expect(updated!.embeddables).toHaveLength(0);
expect(updated!.permissions).toHaveLength(0);
});
});
- Step 2: Run test
Run: npx vitest run libs/libs-structural/vitto-studio/src/lib/components/module-workbench/__tests__/ --reporter=verbose
Expected: ALL PASS
- Step 3: Commit
git add libs/libs-structural/vitto-studio/src/lib/components/module-workbench/__tests__/
git commit -m "[S248.1] test: add E2E tests for module workbench entity cascade"
Task 6.2: Module export E2E test
Files:
Create:
libs/libs-structural/vitto-studio/src/lib/services/__tests__/module-export-e2e.spec.tsStep 1: Write E2E test for full code generation pipeline
describe('ModuleExportService E2E: Full Pipeline', () => {
it('should generate a complete, valid module from ModuleContext → files', () => {
// Create a realistic module context
const context = createEmptyModuleContext('ProjectManagement', 'crud');
// Add two entities
const project = createEntityWithDefaults('Project');
project.fields.push(
{ id: 'f1', name: 'title', type: 'string', required: true, uiHints: { showInList: true } },
{ id: 'f2', name: 'status', type: 'enum', required: true, enumValues: ['active', 'completed', 'archived'] },
{ id: 'f3', name: 'dueDate', type: 'date', required: false },
);
context.entities.push(project);
const task = createEntityWithDefaults('Task');
task.fields.push(
{ id: 'f4', name: 'title', type: 'string', required: true },
{ id: 'f5', name: 'projectId', type: 'reference', referenceType: 'belongs-to', referenceEntityId: project.id },
{ id: 'f6', name: 'priority', type: 'number', required: true },
);
context.entities.push(task);
// Generate CRUD actions
context.actions = [
...createCrudActionsForEntity(project.id, 'Project', 'Projects', project.fields),
...createCrudActionsForEntity(task.id, 'Task', 'Tasks', task.fields),
];
// Generate files
const files = service.generateModuleFiles(context);
// Verify file count: 2 models + 2 services + 2×3 components (ts+html+scss) + routes + index
expect(files.length).toBeGreaterThanOrEqual(16);
// Verify no stubs or TODOs
for (const file of files) {
expect(file.content).not.toContain('// TODO');
expect(file.content).not.toContain('placeholder');
expect(file.content).not.toContain('not implemented');
expect(file.content.length).toBeGreaterThan(10);
}
// Verify services use real HttpClient
const projectService = files.find(f => f.path.includes('project.service.ts'));
expect(projectService!.content).toContain('HttpClient');
expect(projectService!.content).toContain('API_BASE_URL');
expect(projectService!.content).toContain('Observable');
// Verify components use SDK
const listTemplate = files.find(f => f.path.includes('project-list.component.html'));
expect(listTemplate!.content).toContain('ggs-table');
// Verify routes file
const routesFile = files.find(f => f.path.includes('.routes.ts'));
expect(routesFile!.content).toContain('loadComponent');
expect(routesFile!.content).toContain('Routes');
});
});
- Step 2: Run test
Run: npx vitest run libs/libs-structural/vitto-studio/src/lib/services/__tests__/module-export-e2e.spec.ts --reporter=verbose
Expected: ALL PASS
- Step 3: Commit
git add libs/libs-structural/vitto-studio/src/lib/services/__tests__/module-export-e2e.spec.ts
git commit -m "[S248.1] test: add E2E test for full module export pipeline — no stubs verified"
Task 6.3: Module builder plugin E2E test
Files:
Create:
libs/libs-ai/vitto-chat/src/lib/plugins/__tests__/module-builder.plugin.spec.tsStep 1: Write plugin behavior tests
describe('Module Builder Plugin', () => {
it('should produce quick actions only in modularity context', () => {
const contextSignal = signal<VittoRichContext | null>(null);
const plugin = createModuleBuilderPlugin({ contextSignal });
// No context → no quick actions
expect(plugin.quickActions).toHaveLength(0);
// Set modularity context
contextSignal.set({ contextType: 'modularity' as any });
// Re-create to get new quick actions (they're computed at creation time)
const plugin2 = createModuleBuilderPlugin({ contextSignal });
expect(plugin2.quickActions!.length).toBeGreaterThan(0);
expect(plugin2.quickActions!.some(a => a.id === 'mb-generate')).toBe(true);
});
it('should enrich messages with module context when in workbench', () => {
const contextSignal = signal<VittoRichContext | null>({ contextType: 'modularity' as any });
const moduleContextSignal = signal({
moduleId: 'test-1',
moduleName: 'Tasks',
entities: [{ name: 'Task', fields: [] }],
actions: [],
embeddables: [],
progress: 40,
status: 'building',
});
const plugin = createModuleBuilderPlugin({ contextSignal, moduleContextSignal });
const enriched = plugin.enrichMessage!({
id: 'msg-1',
role: 'user',
content: 'Help me',
timestamp: new Date(),
});
expect(enriched.metadata?.moduleBuilder).toBeDefined();
expect(enriched.metadata.moduleBuilder.moduleName).toBe('Tasks');
expect(enriched.metadata.moduleBuilder.entityCount).toBe(1);
expect(enriched.metadata.moduleBuilder.progress).toBe(40);
});
it('should handle module drop with context message', () => {
const contextSignal = signal<VittoRichContext | null>(null);
const plugin = createModuleBuilderPlugin({ contextSignal });
const result = plugin.onDrop!({ type: 'module', id: 'mod-1', name: 'Users' } as any);
expect(result).not.toBeNull();
expect(result!.content).toContain('Users');
});
it('should provide /module slash command', () => {
const contextSignal = signal<VittoRichContext | null>(null);
const onModuleGenerate = vi.fn();
const plugin = createModuleBuilderPlugin({ contextSignal, onModuleGenerate });
expect(plugin.slashCommands).toHaveLength(1);
expect(plugin.slashCommands![0].name).toBe('module');
plugin.slashCommands![0].handler('create A task management system');
expect(onModuleGenerate).toHaveBeenCalledWith('A task management system');
});
});
- Step 2: Run tests
Run: npx vitest run libs/libs-ai/vitto-chat/src/lib/plugins/__tests__/module-builder.plugin.spec.ts --reporter=verbose
Expected: ALL PASS
- Step 3: Commit
git add libs/libs-ai/vitto-chat/src/lib/plugins/__tests__/
git commit -m "[S248.1] test: add E2E tests for module-builder plugin"
Task 6.4: Adapter + validation integration test
Files:
Create:
libs/libs-structural/vitto-studio/src/lib/adapters/__tests__/adapter-validation-e2e.spec.tsStep 1: Write integration test
describe('PhaseResultToModuleContextAdapter → ModuleValidationService E2E', () => {
it('should produce a validatable ModuleContext from Vitto phase output', () => {
const adapter = new PhaseResultToModuleContextAdapter();
const validator = new ModuleValidationService();
// Simulate Vitto 6-phase output
const phaseResult = {
modules: [{
id: 'gen-1',
name: 'UserManagement',
description: 'Manage users and roles',
category: 'system',
entities: [{
name: 'User',
fields: [
{ name: 'id', type: 'String', required: true },
{ name: 'email', type: 'String', required: true },
{ name: 'name', type: 'String', required: true },
{ name: 'role', type: 'String', required: false },
],
}],
actions: [],
generatedFiles: [],
}],
metadata: { generationId: 'test', timestamp: Date.now(), totalFiles: 0 },
};
const moduleContext = adapter.adapt(phaseResult);
// Should have cascaded everything
expect(moduleContext.entities.length).toBe(1);
expect(moduleContext.stateDefinitions.length).toBe(1);
expect(moduleContext.actions.length).toBeGreaterThanOrEqual(5);
expect(moduleContext.embeddables.length).toBe(2);
// Should pass basic validation
const result = validator.validate(moduleContext);
expect(result.score).toBeGreaterThan(40);
expect(result.exportReadiness.canExportAsManifest).toBe(true);
});
});
- Step 2: Run test
Run: npx vitest run libs/libs-structural/vitto-studio/src/lib/adapters/__tests__/ --reporter=verbose
Expected: PASS
- Step 3: Commit
git add libs/libs-structural/vitto-studio/src/lib/adapters/__tests__/
git commit -m "[S248.1] test: add adapter→validation integration E2E test"
Phase 7: NX Libs & Component Cleanup
Impact: Ensures every NX lib compiles, all deprecated exports are removed, all project.json configs are correct, and the workspace is clean.
Task 7.1: Verify all NX projects build
- Step 1: Run full affected build
npx nx run-many --target=build --all --skip-nx-cache 2>&1 | tee /tmp/build-output.txt
- Step 2: Identify any build failures
grep -E 'ERROR|FAIL|Cannot find' /tmp/build-output.txt
- Step 3: Fix any remaining broken imports
For each error: update the import path. The most likely issues are:
Transitive imports through a deleted lib
Barrel exports that reference removed services
implicit dependenciesinproject.jsonreferencing deleted libsStep 4: Commit fixes
git add -A
git commit -m "[S248.1] fix: resolve remaining build errors from library migration"
Task 7.2: Clean up gograb-ai-lib — remove deprecated exports
- Step 1: Audit gograb-ai-lib services barrel
Read libs/libs-ai/gograb-ai-lib/src/lib/services/index.ts. For each export, check:
Is the service still in this lib (not moved)?
Is the service still used by any consumer?
If moved → remove the re-export shim (direct imports should be updated by now)
Step 2: Remove all re-export shims
Delete all lines in gograb-ai-lib that say // DEPRECATED: ... moved to .... By now, all consumers should import directly from the new location.
- Step 3: Audit gograb-ai-lib components barrel
Same process for libs/libs-ai/gograb-ai-lib/src/lib/components/index.ts. Remove re-export shims for moved dashboard components.
- Step 4: Remove unused LLM provider services
Delete these unused direct LLM services (all bypassed by Vitto):
openai.service.tsanthropic.service.tsgoogle.service.tsopenai-proxy.service.tsanthropic-proxy.service.tsanthropic-test.service.tsopenai-test.service.ts
Only delete if grep -r confirms no active consumers (exclude demos-lib which is also deprecated).
- Step 5: Verify gograb-ai-lib builds
npx nx build gograb-ai-lib --skip-nx-cache
Expected: Build succeeds with a significantly smaller footprint.
- Step 6: Commit
git add libs/libs-ai/gograb-ai-lib/
git commit -m "[S248.1] chore: clean deprecated exports and unused services from gograb-ai-lib"
Task 7.3: Update project.json implicit dependencies
- Step 1: Update vitto-studio project.json
Add implicit dependencies for the models and services it now owns:
{
"implicitDependencies": ["core-angular", "core-models", "storage-system", "log-system", "platform-preview"]
}
- Step 2: Update vitto-hub project.json
Add implicit dependencies for dashboard components:
{
"implicitDependencies": ["core-angular", "core-models", "vitto-core"]
}
- Step 3: Update vitto-chat project.json
Add implicit dependency on vitto-studio (for module-builder plugin types):
{
"implicitDependencies": ["core-angular", "vitto-core", "vitto-studio"]
}
- Step 4: Remove deleted libs from all project.json implicit deps
grep -r 'modularity-lib\|module-generator\|modular-universe\|module-browser-lib\|cursor-agents\|multi-agent-dashboard' --include='project.json' -l
For each file: remove the deleted lib from implicitDependencies.
- Step 5: Clear NX cache and verify project graph
nx reset
npx nx graph --file=/tmp/graph.html
Open /tmp/graph.html to verify no broken edges.
- Step 6: Commit
git add -A
git commit -m "[S248.1] chore: update project.json dependencies for library migration"
Task 7.4: Final verification — lint, build, test
- Step 1: Run lint on all affected
npx nx run-many --target=lint --projects=vitto-studio,vitto-chat,vitto-hub --skip-nx-cache
Fix any lint errors.
- Step 2: Run all tests
npx nx run-many --target=test --projects=vitto-studio,vitto-chat,vitto-hub --skip-nx-cache
All tests must pass.
- Step 3: Run full build
npx nx run-many --target=build --all --skip-nx-cache
All projects must build.
- Step 4: Verify zero deprecated references remain
grep -r "@libs-structural/modularity-lib" --include='*.ts' -l | grep -v node_modules | grep -v dist
grep -r "@libs-ai/module-generator" --include='*.ts' -l | grep -v node_modules | grep -v dist
grep -r "@libs-structural/modular-universe" --include='*.ts' -l | grep -v node_modules | grep -v dist
grep -r "@libs-structural/module-browser-lib" --include='*.ts' -l | grep -v node_modules | grep -v dist
Expected: No output for any of these.
- Step 5: Commit any final fixes
git add -A
git commit -m "[S248.1] chore: final verification — all libs build, test, lint clean"
Rollback Strategy
| Phase | Rollback |
|---|---|
| Phase 1 (models) | Remove vitto-studio/models/, restore modularity-lib models barrel |
| Phase 2 (services) | Remove vitto-studio services, restore modularity-lib services barrel |
| Phase 3 (components) | Remove vitto-studio components, restore modularity-lib + gograb-ai-lib components |
| Phase 4 (plugin) | Remove module-builder.plugin.ts, revert plugin-presets.ts |
| Phase 5 (imports) | Restore old import paths (git revert the commit) |
| Phase 5 (deletions) | git checkout HEAD~1 -- libs/libs-structural/modularity-lib/ libs/libs-ai/module-generator/ ... |
Each phase can be reverted independently because re-export shims are kept until Phase 5.
Success Criteria
| Metric | Verification |
|---|---|
| Zero references to deleted libs | grep -r "@libs-structural/modularity-lib" --include='*.ts' returns empty |
| All NX projects build | npx nx run-many --target=build --all succeeds |
| All tests pass | npx nx run-many --target=test --projects=vitto-studio,vitto-chat,vitto-hub succeeds |
Module workbench accessible at /modularity/workbench |
Navigate in browser, verify step components render |
| Entity cascade works | Add entity in workbench, verify state+actions+embeddables auto-created |
| Code generation produces real code | Export module, verify no stubs/TODOs in generated files |
| vitto-chat shows module-builder actions in modularity context | Open chat in workbench, verify quick actions appear |
| Dashboard routes work in gograb-dev | Navigate to /intelligence/*, verify components render |
gograb-ai-lib is significantly smaller |
Compare line count before/after |