2026 03 19 Platform Generation Quality V3
Documentation for Plans
Platform Generation Quality v3 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: Enrich the generation pipeline to produce production-ready platforms using the full libs/core SDK (workflows, filters, entity lookups, module registration) with backend schema registration and seed data.
Architecture: 6 changes across the ANALYZE→EXECUTE→INTEGRATE pipeline. Prompts teach the LLM about building blocks. ANALYZE detects which blocks each entity needs. EXECUTE passes that metadata. INTEGRATE registers schemas and seeds data. The platform-base-template gets the missing workflow-engine library. The Generations tab bug is fixed separately.
Tech Stack: Angular 20+, NestJS (backend-vitto-api), MongoDB, TypeScript, LLM prompts (markdown templates)
Spec: docs/superpowers/specs/2026-03-19-platform-generation-quality-v3-design.md
File Map
Files to Create
| File | Responsibility |
|---|---|
repo-templates/platform-base-template/libs/core/workflow-engine/ |
Copy of workflow-engine lib for platform template |
Files to Modify
| File | Lines | Change |
|---|---|---|
repo-templates/platform-base-template/tsconfig.base.json |
~44 | Add @libs-core/workflow-engine path mapping |
APIs/backend-vitto-api/src/app/module-generation/module-generation.types.ts |
~203-254 | Add BuildingBlockSpec, SchemaSpec, SeedDataSpec types |
APIs/backend-vitto-api/src/prompts/module-gen/system-analyze.prompt.md |
~33-76 | Add buildingBlocks to entity output schema |
APIs/backend-vitto-api/src/prompts/module-gen/implement.prompt.md |
~22-24, ~623-646 | Add 5 building block sections + schemas/seedData output |
APIs/backend-vitto-api/src/app/module-generation/phases/execute.phase.ts |
~371-401 | Pass buildingBlocks metadata to LLM prompt |
APIs/backend-vitto-api/src/app/module-generation/phases/integrate.phase.ts |
~31-145 | Add schema registration + seed data POST after validation |
libs/libs-structural/vitto-studio/src/lib/services/generation.service.ts |
TBD | Fix signal population from SSE events |
libs/libs-structural/vitto-studio/src/lib/panels/generations-panel.component.ts |
~55-57 | Fix isEmpty computed / data flow |
Task 0: JIT Compatibility Blocker Check
Purpose: Verify that SDK components using signal input() render correctly in the rspack WASM preview (Angular JIT). This is a blocker — if they fail, Tasks 4-5 need fallback patterns.
Files:
Read:
libs/core/ui-framework/src/lib/components/ggs-filter-panel/ggs-filter-panel.component.tsRead:
libs/core/ui-framework/src/lib/components/ggs-entity-lookup/ggs-entity-lookup.component.tsRead:
libs/core/workflow-engine/src/lib/components/ggs-status-transition/ggs-status-transition.component.tsStep 1: Check component input styles
Read the three component files above. Confirm whether they use input() (signal) or @Input() (decorator). Record findings:
GgsFilterPanelComponent→ signalinput()or@Input()?GgsEntityLookupComponent→ signalinput()or@Input()?GgsStatusTransitionComponent→ signalinput()or@Input()?Step 2: Test in live preview
Use Playwright to navigate to localhost:6200/space/chrome-space-1/universe/tortuga/studio. In the Code tab, create a minimal test component that imports one of these components. Trigger a compile and check the browser console for JIT errors.
Alternatively, check if Angular JIT (v20+) now supports signal inputs — this was a limitation in earlier versions but may have been resolved.
- Step 3: Document findings and decide path
If JIT supports signal inputs: proceed with all building blocks as designed. If JIT fails: for each failing component, design an inline fallback:
lib-status-transition→ inline<ggs-badge>with status labelggs-filter-panel→ simple<select>dropdownsggs-entity-lookup→ plain<input>with(blur)handler
Record decision in the spec's risk table.
Task 1: Add workflow-engine to Platform-Base-Template
Purpose: The template's tsconfig.base.json is missing @libs-core/workflow-engine. Without it, generated code importing WorkflowDefinition or lib-status-transition won't compile.
Files:
Modify:
repo-templates/platform-base-template/tsconfig.base.json:~44Create:
repo-templates/platform-base-template/libs/core/workflow-engine/(copy from gspace1)Step 1: Add path mapping to tsconfig.base.json
Open /Users/fguijarro/developer/repos-gspace/repo-templates/platform-base-template/tsconfig.base.json. In the paths section (~line 44, near the other @libs-core/* entries), add:
"@libs-core/workflow-engine": ["libs/core/workflow-engine/src/index.ts"],
"@libs-core/workflow-engine/*": ["libs/core/workflow-engine/src/*"]
- Step 2: Copy workflow-engine library to template
Copy the entire directory from gspace1:
cp -r /Users/fguijarro/developer/repos-gspace/gspace1/libs/core/workflow-engine /Users/fguijarro/developer/repos-gspace/repo-templates/platform-base-template/libs/core/workflow-engine
- Step 3: Verify the library exports resolve
cd /Users/fguijarro/developer/repos-gspace/repo-templates/platform-base-template
cat libs/core/workflow-engine/src/index.ts
Confirm it exports WorkflowEngineService, GgsStatusTransitionComponent, etc.
- Step 4: Also verify @libs-core/shared-models exports WorkflowDefinition
grep -r "WorkflowDefinition" /Users/fguijarro/developer/repos-gspace/repo-templates/platform-base-template/libs/core/shared-models/src/
If WorkflowDefinition is NOT in the template's shared-models, copy the workflow types file too.
- Step 5: Commit
git add repo-templates/platform-base-template/tsconfig.base.json repo-templates/platform-base-template/libs/core/workflow-engine/
git commit -m "[S244.1] feat: add workflow-engine library to platform-base-template"
Task 2: Add Types to module-generation.types.ts
Purpose: Define TypeScript types for building block metadata, schema specs, and seed data that flow through the pipeline.
Files:
Modify:
APIs/backend-vitto-api/src/app/module-generation/module-generation.types.ts:~254Step 1: Read current types file
Read /Users/fguijarro/developer/repos-gspace/gspace1/APIs/backend-vitto-api/src/app/module-generation/module-generation.types.ts, specifically lines 200-260 (around ModuleGenAnalyzeResult and EntitySpec).
- Step 2: Add BuildingBlockSpec type
After the EntitySpec interface (around line 230), add:
export interface ForeignKeySpec {
field: string;
targetEntity: string;
targetModule: string; // 'same' if within this module, or module slug
}
export interface BuildingBlockSpec {
hasWorkflow: boolean;
workflowField?: string;
workflowStates?: string[];
foreignKeys: ForeignKeySpec[];
hasMedia: boolean;
filterableFields: string[];
}
- Step 3: Add buildingBlocks to EntitySpec
Find the EntitySpec interface and add:
buildingBlocks?: BuildingBlockSpec;
- Step 4: Add SchemaSpec and SeedDataSpec types
After the GeneratedFileSpec interface (~line 490), add:
export interface SchemaFieldSpec {
name: string;
type: 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array' | 'reference';
required?: boolean;
label?: string;
validation?: {
enum?: string[];
min?: number;
max?: number;
minLength?: number;
maxLength?: number;
};
}
export interface SchemaSpec {
collection: string;
displayName: string;
fields: SchemaFieldSpec[];
}
export interface SeedDataSpec {
[collection: string]: Record<string, unknown>[];
}
- Step 5: Update ModuleGenExecuteResult to include schemas and seedData
Find the ModuleGenExecuteResult interface (NOT GeneratedModule — that's the visual-path type). Add:
schemas?: SchemaSpec[];
seedData?: SeedDataSpec;
These fields hold the LLM-generated schema and seed data extracted alongside files during the EXECUTE phase.
- Step 6: Update normalizeAnalyzeResult to preserve buildingBlocks
CRITICAL: The normalizeAnalyzeResult() function explicitly maps each entity to only name, description, fields, and relationships. Any buildingBlocks from the LLM response is silently dropped. Find this function and add buildingBlocks to the entity mapping:
// In normalizeAnalyzeResult, find the coreEntities mapping:
coreEntities: (raw.coreEntities || []).map((e: any) => ({
name: e.name,
description: e.description,
fields: e.fields || e.attributes || [],
relationships: e.relationships || [],
buildingBlocks: e.buildingBlocks || undefined, // ADD THIS LINE
})),
Without this change, the entire buildingBlocks pipeline is broken — the ANALYZE LLM produces the metadata, the normalizer strips it, and EXECUTE never sees it.
- Step 7: Commit
git add APIs/backend-vitto-api/src/app/module-generation/module-generation.types.ts
git commit -m "[S244.2] feat: add building block, schema, and seed data types to generation pipeline"
Task 3: Enrich system-analyze.prompt.md
Purpose: Teach the ANALYZE phase LLM to detect which building blocks each entity needs (workflow, foreign keys, media, filterable fields).
Files:
Modify:
APIs/backend-vitto-api/src/prompts/module-gen/system-analyze.prompt.md:~33-76Step 1: Read current analyze prompt
Read /Users/fguijarro/developer/repos-gspace/gspace1/APIs/backend-vitto-api/src/prompts/module-gen/system-analyze.prompt.md (84 lines).
- Step 2: Add buildingBlocks to entity output schema
In the output JSON format section (after the relationships array in the coreEntities object), add:
"buildingBlocks": {
"hasWorkflow": true,
"workflowField": "status",
"workflowStates": ["pending", "in-progress", "completed"],
"foreignKeys": [
{ "field": "categoryId", "targetEntity": "Category", "targetModule": "same" }
],
"hasMedia": false,
"filterableFields": ["status", "priority", "categoryId"]
}
- Step 3: Add detection rules
After the output format section, before the validation rules, add:
## Building Block Detection Rules
For each entity, analyze its fields to populate `buildingBlocks`:
1. **Workflow detection**: If the entity has a field named `status` (or `state`, `phase`) with enum/string values representing lifecycle stages → set `hasWorkflow: true`, `workflowField` to the field name, `workflowStates` to the enum values
2. **Foreign key detection**: If a field name ends with `Id` (e.g., `categoryId`, `assigneeId`, `parentId`) AND references another entity in the system → add to `foreignKeys[]` with `targetEntity` (PascalCase) and `targetModule` ("same" if same module, or the target module's slug)
3. **Media detection**: If a field name contains `image`, `photo`, `media`, `file`, `attachment`, `avatar`, `thumbnail`, or `logo` → set `hasMedia: true`
4. **Filterable fields**: Include ALL fields that have enum/select values, plus any `*Id` foreign key fields, plus `createdAt`/`updatedAt` date ranges. Minimum 2 filterable fields per entity.
- Step 4: Commit
git add APIs/backend-vitto-api/src/prompts/module-gen/system-analyze.prompt.md
git commit -m "[S244.3] feat: add building block detection to ANALYZE phase prompt"
Task 4: Enrich implement.prompt.md — Building Block Patterns
Purpose: Teach the EXECUTE phase LLM to generate workflow definitions, filter definitions, entity lookups, module registration, and seed data — using verified component APIs.
Files:
Modify:
APIs/backend-vitto-api/src/prompts/module-gen/implement.prompt.md:~22-24, ~623-646Step 1: Read current implement prompt
Read /Users/fguijarro/developer/repos-gspace/gspace1/APIs/backend-vitto-api/src/prompts/module-gen/implement.prompt.md. Focus on:
Lines 1-30 (header, variables, context)
Lines 600-667 (output format, type mapping rules)
Find the ABSOLUTE BANS section
Find where component/service golden examples are
Step 2: Add Building Block Patterns section
After the existing golden examples section (and before the output format), insert a new section titled ## BUILDING BLOCK PATTERNS. This section is CONDITIONAL — only relevant patterns are included based on the entity's buildingBlocks metadata in the spec JSON.
## BUILDING BLOCK PATTERNS
Use these patterns when the entity spec's `buildingBlocks` metadata indicates the need. Check `buildingBlocks.hasWorkflow`, `buildingBlocks.foreignKeys`, `buildingBlocks.filterableFields`, etc.
### Workflow Definition (when buildingBlocks.hasWorkflow === true)
Generate `workflow/{{entity}}-workflow.definition.ts`:
\`\`\`typescript
import { WorkflowDefinition } from '@libs-core/shared-models';
export const {{ENTITY}}_STATUS_WORKFLOW: WorkflowDefinition = {
id: '{{entity}}-status',
entityType: '{{entity}}',
statusField: '{{buildingBlocks.workflowField}}',
states: [
// Map each value in buildingBlocks.workflowStates to a state object.
// First state is type: 'initial', last is type: 'final', rest are 'intermediate'.
// Colors: initial→'warning', intermediate→'info', final→'success', cancelled→'neutral'
],
transitions: [
// Generate logical transitions between states.
// Each transition needs: id, from, to, label, permissions: ['{{entities}}:update']
// Terminal/destructive transitions should have requireConfirmation: true
],
};
export function provide{{Entity}}Workflow() {
return [{ provide: '{{ENTITY}}_WORKFLOW', useValue: {{ENTITY}}_STATUS_WORKFLOW }];
}
\`\`\`
In detail component template, use:
\`\`\`html
<lib-status-transition
[entityType]="'{{entity}}'"
[entity]="crud.entity()"
(transitionCompleted)="onStatusChanged($event)"
/>
\`\`\`
In routes, inject the workflow provider:
\`\`\`typescript
{
path: '',
providers: [provide{{Entity}}Workflow()],
children: [...]
}
\`\`\`
### Filter Definitions (ALWAYS — every list component)
In the list component, add `filterDefinitions` to `useCrudList` config:
\`\`\`typescript
filterDefinitions: [
// For each field in buildingBlocks.filterableFields:
// - enum fields → type: 'select' with options array
// - *Id foreign key fields → type: 'select' with options loaded from related entity
// - date fields → type: 'date-range'
// - boolean fields → type: 'select' with [{ value: 'true', label: 'Yes' }, { value: 'false', label: 'No' }]
],
syncWithUrl: true,
\`\`\`
In the list template, place filters ABOVE the shell:
\`\`\`html
<ggs-filter-panel
[filters]="crud.filterDefinitions()"
[activeFilters]="crud.activeFilters()"
(filtersChange)="crud.setFilters($event)"
(clearAll)="crud.clearFilters()"
/>
<ggs-filter-chips
[activeFilters]="crud.activeFilters()"
(removeFilter)="crud.removeFilter($event.field)"
(clearAll)="crud.clearFilters()"
/>
\`\`\`
Import: `GgsFilterPanelComponent, GgsFilterChipsComponent` from `@libs-core/ui-framework`.
### Entity Lookup for Foreign Keys (when buildingBlocks.foreignKeys is non-empty)
For each foreign key in `buildingBlocks.foreignKeys`, generate a lookup function and template in the FORM component:
\`\`\`typescript
// For foreignKey { field: 'categoryId', targetEntity: 'Category' }
readonly categoryLoadFn = (query: string): Observable<Category[]> =>
this.categoryApi.getList({ page: 1, limit: 20, search: query }).pipe(map(r => r.items));
readonly categoryDisplayFn = (cat: Category): string => cat.name;
readonly categoryInitialLoadFn = (): Observable<Category[]> =>
this.categoryApi.getList({ page: 1, limit: 20 }).pipe(map(r => r.items));
onCategorySelected(category: Category | null): void {
this.crud.form().patchValue({ categoryId: category?.id ?? '' });
}
\`\`\`
Template:
\`\`\`html
<ggs-entity-lookup
[loadFn]="categoryLoadFn"
[displayFn]="categoryDisplayFn"
[initialLoadFn]="categoryInitialLoadFn"
placeholder="Search categories..."
(selectionChange)="onCategorySelected($event)"
/>
\`\`\`
Import: `GgsEntityLookupComponent` from `@libs-core/ui-framework`.
### Module Registration (ALWAYS)
Generate `{{module}}.module.ts`:
\`\`\`typescript
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { ModuleDecorator, BrowserModuleContract, ModuleManifest } from '@libs-core/module-base';
import { {{ModuleName}}Routes } from './{{module}}.routes';
@ModuleDecorator({
id: '{{moduleSlug}}',
version: '1.0.0',
name: '{{Module Name}}',
description: '{{description}}',
basePath: '{{moduleSlug}}',
repositories: [],
permissions: [
// Generate 5 standard CRUD permissions: list, read, create, update, delete
// Format: { id: '{{entities}}:action', name: '{{entities}}:action', resource: '{{entities}}', action: 'action' }
],
navigation: {
menuItems: [{
id: '{{moduleSlug}}-main',
label: '{{Entities}}',
icon: '/* appropriate FontAwesome icon */',
route: 'list',
order: 100,
permissions: ['{{entities}}:list'],
}],
},
tags: ['{{moduleSlug}}', 'crud'],
})
@Injectable({ providedIn: 'root' })
export class {{ModuleName}}Module implements BrowserModuleContract {
readonly manifest: ModuleManifest = {
id: '{{moduleSlug}}',
version: '1.0.0',
name: '{{Module Name}}',
description: '{{description}}',
basePath: '{{moduleSlug}}',
permissions: [/* same as decorator */],
embeddableComponents: [],
};
readonly routes = {{ModuleName}}Routes;
configure<T = Record<string, unknown>>(_config: T): Observable<void> { return of(void 0); }
initialize(): Observable<void> { return of(void 0); }
start(): Observable<void> { return of(void 0); }
stop(): Observable<void> { return of(void 0); }
destroy(): Observable<void> { return of(void 0); }
}
\`\`\`
- Step 3: Update output format to include schemas and seedData
Find the output format JSON section (~lines 623-646). Add two new top-level fields to the expected output:
{
"files": [...],
"summary": {...},
"schemas": [
{
"collection": "{{entities}}",
"displayName": "{{Entities}}",
"fields": [
{ "name": "fieldName", "type": "string|number|boolean|date|object|array|reference", "required": true, "label": "Display Label" },
{ "name": "status", "type": "string", "required": true, "label": "Status", "validation": { "enum": ["pending", "active"] } }
]
}
],
"seedData": {
"{{entities}}": [
{ "_id": "seed-{{entity}}-001", "name": "Example Record 1", "status": "pending" },
{ "_id": "seed-{{entity}}-002", "name": "Example Record 2", "status": "active" }
]
}
}
Add instruction: "Generate 3-5 realistic seed records per entity. Each seed record MUST include a stable _id field with format seed-{entity}-NNN. Use realistic domain-appropriate data, not lorem ipsum."
- Step 4: Add rule about schema field types
In the type mapping rules section (~line 652), add:
## Schema Field Type Rules (for schemas[] output)
- Use LOWERCASE types only: 'string', 'number', 'boolean', 'date', 'object', 'array', 'reference'
- Enum fields use type: 'string' with validation.enum (NOT type: 'enum')
- Date fields use type: 'date' (NOT 'Date')
- Foreign key fields use type: 'reference'
- Step 5: Commit
git add APIs/backend-vitto-api/src/prompts/module-gen/implement.prompt.md
git commit -m "[S244.4] feat: add building block patterns and schema/seed output to implement prompt"
Task 5: Pass Building Block Metadata to EXECUTE Phase
Purpose: Wire the ANALYZE phase's buildingBlocks output into the EXECUTE phase's LLM prompt so the LLM knows which patterns to apply per entity.
Files:
Modify:
APIs/backend-vitto-api/src/app/module-generation/phases/execute.phase.ts:~371-401Step 1: Read execute.phase.ts
Read /Users/fguijarro/developer/repos-gspace/gspace1/APIs/backend-vitto-api/src/app/module-generation/phases/execute.phase.ts, lines 360-420.
- Step 2: Enrich specJson with buildingBlocks
Find where specJson is constructed (around line 389). Before the this.promptBuilder.buildModuleGenPrompt() call, enrich the spec with building block data:
// Enrich entity specs with building block metadata from ANALYZE phase
const enrichedSpec = {
...moduleSpec,
entities: (moduleSpec.entities || []).map(entity => {
const analyzeEntity = session.analyzeResult?.coreEntities?.find(
ce => ce.name === entity.name
);
return {
...entity,
buildingBlocks: analyzeEntity?.buildingBlocks || {
hasWorkflow: false,
foreignKeys: [],
hasMedia: false,
filterableFields: [],
},
};
}),
};
const specJson = JSON.stringify(enrichedSpec, null, 2);
- Step 3: Verify session carries analyzeResult
Check that the session object passed to execute() contains analyzeResult from the ANALYZE phase. Look at the phase executor (~`module-gen-phase.executor.ts`) to confirm the session accumulates results.
If the session doesn't carry analyzeResult, trace how phase results are stored and retrieve it from the session's checkpoint data.
- Step 4: Extract schemas and seedData from LLM response
CRITICAL: The extractCodeFiles() method only extracts the files array from the LLM JSON response. schemas and seedData are discarded. Find extractCodeFiles() in execute.phase.ts and update it to also capture these fields.
After parseLlmJson() succeeds and the parsed object is available, extract:
// After parsing the LLM response JSON:
const parsedOutput = parseLlmJson(responseContent);
// Extract files (existing logic)
const files = parsedOutput.files || [];
// Extract schemas and seedData (NEW)
const schemas = parsedOutput.schemas || [];
const seedData = parsedOutput.seedData || {};
Then attach these to the ModuleGenExecuteResult:
// When building the execute result:
executeResult.schemas = schemas;
executeResult.seedData = seedData;
- Step 5: Commit
git add APIs/backend-vitto-api/src/app/module-generation/phases/execute.phase.ts
git commit -m "[S244.5] feat: pass building block metadata and extract schemas/seed from EXECUTE phase"
Task 6: Seed Data in INTEGRATE Phase
Purpose: After code generation and validation, seed initial data so generated platforms have real data on first load. Note: schema registration is already handled by BackendSetupPhaseService (runs between EXECUTE and INTEGRATE). This task adds ONLY seed data seeding.
Important context:
IntegratePhaseService.execute()receivesrequest: ModuleGenRequestandexecuteResult: ModuleGenExecuteResultas separate parameters, NOT a session object.BackendSetupPhaseServicealready registers schemas withPOST /data/schemas. Do NOT duplicate this.- Follow the injection pattern from
BackendSetupPhaseServiceforHttpServiceandConfigService.
Files:
Modify:
APIs/backend-vitto-api/src/app/module-generation/phases/integrate.phase.ts:~31-145Read:
APIs/backend-vitto-api/src/app/module-generation/phases/backend-setup.phase.ts(reference pattern)Step 1: Read integrate.phase.ts and backend-setup.phase.ts
Read both files. From backend-setup.phase.ts, note:
How
HttpServiceandConfigServiceare injectedThe config key used for the API URL (likely
BACKEND_API_URL, notAPI_BASE_URL)How it already handles schema registration
Step 2: Add HttpService and ConfigService injection
Add to the constructor of IntegratePhaseService:
import { HttpService } from '@nestjs/axios';
import { ConfigService } from '@nestjs/config';
import { firstValueFrom } from 'rxjs';
// In constructor (follow BackendSetupPhaseService's pattern):
constructor(
private readonly promptBuilder: PromptBuilderService,
private readonly providerFactory: ProviderFactoryService,
private readonly httpService: HttpService,
private readonly configService: ConfigService,
) {}
- Step 3: Add seed data registration after validation
After the existing validation/repair logic, before the return, add seed data seeding. Use the method's actual parameters (request and executeResult):
// Seed initial data with backend-api
const spaceId = request.spaceId;
const universeId = request.universeId;
const apiBaseUrl = this.configService.get('BACKEND_API_URL', 'http://localhost:3000');
if (spaceId && universeId && executeResult.seedData) {
for (const [collection, records] of Object.entries(executeResult.seedData)) {
if (records?.length) {
try {
await firstValueFrom(
this.httpService.post(
`${apiBaseUrl}/api/spaces/${spaceId}/universes/${universeId}/data/${collection}/seed`,
{ records }
)
);
this.logger.log(`Seeded ${records.length} records for ${collection}`);
} catch (err) {
this.logger.warn(`Seed data failed for ${collection}: ${err.message}`);
// Non-blocking — seed failure shouldn't stop generation
}
}
}
}
- Step 4: Verify HttpModule is imported in ModuleGenerationModule
Check that HttpModule from @nestjs/axios is imported in the NestJS module that provides IntegratePhaseService. If not, add it. Also check ConfigModule.
- Step 5: Commit
git add APIs/backend-vitto-api/src/app/module-generation/phases/integrate.phase.ts
git commit -m "[S244.6] feat: seed initial data in INTEGRATE phase"
Task 7: Fix Generations Tab
Purpose: The Generations tab shows "No generations yet" after a successful generation. Trace the data flow and fix.
Files:
Read:
libs/libs-structural/vitto-studio/src/lib/panels/generations-panel.component.ts:~31-57Read:
libs/libs-structural/vitto-studio/src/lib/panels/generations-panel.component.html:~168-173Read:
libs/libs-structural/vitto-studio/src/lib/services/generation.service.tsRead:
libs/libs-structural/vitto-studio/src/lib/services/studio-generation-listener.service.tsStep 1: Read the Generations panel component
Read /Users/fguijarro/developer/repos-gspace/gspace1/libs/libs-structural/vitto-studio/src/lib/panels/generations-panel.component.ts. Understand what signals it reads and what conditions trigger the empty state.
- Step 2: Read the GenerationService
Read /Users/fguijarro/developer/repos-gspace/gspace1/libs/libs-structural/vitto-studio/src/lib/services/generation.service.ts. Focus on:
The
generationssignal — how is it populated?What events/methods write to it?
Is it universe-scoped? (Does it clear when switching universes?)
Step 3: Read the StudioGenerationListenerService
Read /Users/fguijarro/developer/repos-gspace/gspace1/libs/libs-structural/vitto-studio/src/lib/services/studio-generation-listener.service.ts. Find:
What SSE events it handles
Whether
module-gen.completedwrites toGenerationService.generationsWhether there's a disconnect between SSE event handling and generations signal update
Step 4: Trace the data flow
Map the complete flow:
- Backend emits
module-gen.completedSSE event with modules data StudioGenerationListenerServicereceives it → does it callGenerationService.addGeneration()?GenerationService.generationssignal → does it update?GenerationsPanel.isEmpty()→ does it recompute?
Identify where the chain breaks.
- Step 5: Apply the fix
Based on findings, apply the appropriate fix. Common causes:
SSE event handler doesn't call
GenerationService.addGeneration()GenerationServiceexpects a different event format than what backend sendsUniverse filtering drops the generation (mismatched universeId)
Signal doesn't trigger change detection (unlikely with signals but possible with nested objects)
Step 6: Verify in browser
Navigate to localhost:6200/space/chrome-space-1/universe/tortuga/studio, switch to Generations tab, and confirm:
Previous generations appear (if persisted)
Or confirm the signal updates when a new generation would complete
Step 7: Commit
git add <specific-files-changed>
git commit -m "[S244.7] fix: populate Generations tab with completed generation data"
Task 8: End-to-End Verification
Purpose: Run a full generation through Vitto and verify all new features work together.
Files: None to modify — this is a verification task.
- Step 1: Ensure backends are running
# Check ports 3000 (backend-api) and 3003 (backend-vitto-api)
lsof -i :3000 | head -5
lsof -i :3003 | head -5
If not running, start them via yarn serve:backend-api and yarn serve:backend-vitto.
- Step 2: Generate a new platform via Vitto
Navigate to localhost:6200/space/chrome-space-1/universe/tortuga/studio. In the Vitto chat, ask:
"Generate a task management system with tasks (name, description, status: pending/in-progress/completed, priority: low/medium/high, assigneeId, dueDate) and categories (name, description, color)"
- Step 3: Verify generated code quality
After generation completes, check the Code tab. Verify ALL 10 success criteria:
- API services extend
UniverseDataCrudService<T>(not rawUniverseDataService) - Module file exists with
@ModuleDecorator+BrowserModuleContract - Workflow definition exists for Task entity (has status field)
- List component has
filterDefinitionsfor status and priority - Form component has
GgsEntityLookupComponentforcategoryIdforeign key - Seed data file exists with 3-5 realistic records per entity
- All files follow the expected directory structure
- No
anytypes, no Promises, no Material imports
- Step 4: Verify live preview compiles
Check that the preview shows "Compiled (N assets, Xms)" and renders the modules with tabs/navigation.
- Step 5: Verify backend schema registration
curl -s http://localhost:3000/api/spaces/<spaceId>/universes/<universeId>/data/schemas | jq .
Confirm schemas for tasks and categories are registered.
- Step 6: Verify seed data
curl -s -X POST http://localhost:3000/api/spaces/<spaceId>/universes/<universeId>/data/tasks/query \
-H 'Content-Type: application/json' \
-d '{"page": 1, "pageSize": 10}' | jq .
Confirm 3-5 seed records exist.
- Step 7: Verify CRUD cycle in preview
In the live preview:
- Click "Tasks" in navigation
- Verify seed data appears in the list with filter panel
- Click "Create Task" — verify form has entity lookup for category
- Create a new task — verify it appears in the list
- Click a task — verify detail view shows status transition component
- Edit a task — verify form populates correctly
- Delete a task — verify it disappears from list
- Step 8: Verify Generations tab
Switch to the Generations tab. Confirm it shows the completed generation with module names, timestamp, and status.