S236 Platform Generation Pipeline Fixes

Documentation for Sessions

S236 — Platform Generation Pipeline Fixes

Date: March 18-19, 2026 Session: 236 Status: Partial (code changes complete, pending live testing) Branch: session-236-237 (shared with concurrent S237)


What Was Wrong

When a user asked Vitto to generate a platform (e.g., "Build me a Parental Management Platform with points, tasks, and rewards"), the generation pipeline ran successfully — 5 modules, 131 files, quality score 70 — but the Live Preview never showed the platform. The user saw a blank "Ready when you are" screen even after refreshing.

Additionally, the Generations panel showed "No generations yet" despite the code existing in GitLab, and the Review panel showed "No pending files to review".

In simple terms: the platform was built but the user couldn't see it.


Timeline of Investigation & Fixes

Phase 1: Understanding the Full Pipeline (Analysis)

Before making any changes, we traced the entire generation flow end-to-end:

  1. User asks Vitto → Vitto calls start_module_generation tool
  2. Backend runs 6-phase pipeline (ENHANCE → ANALYZE → DECOMPOSE → PLAN → EXECUTE → INTEGRATE → DEPLOY)
  3. DEPLOY phase commits code to GitLab on a feature branch and creates a generation manifest
  4. SSE events flow from backend → plugin → chat engine → dock shell → generation listener
  5. Generation listener refreshes VFS (Virtual File System) from GitLab
  6. Preview service compiles VFS content with rspack and shows it in an iframe

We identified 5 distinct failures in this chain, each compounding the others.


Phase 2: Fix #1 — SSE Event Race Condition (Backend)

The Problem: The "generation completed" notification sometimes never reached the user's browser.

Why it happened: The backend set status = 'completed' and then saved a checkpoint to the database (which takes time). During that database save, a polling loop detected the completion, disconnected the event stream, and then the "completed" notification tried to send — but the stream was already disconnected.

The Fix: We now send the notification FIRST, before marking the session as completed. This guarantees the notification goes out while the stream is still connected.

File: APIs/backend-vitto-api/src/app/module-generation/phases/module-gen-phase.executor.ts


Phase 3: Fix #2 — Preview Compiled Too Early (Frontend)

The Problem: Even when the "completed" notification arrived, the preview showed "No modules generated yet."

Why it happened: After receiving the completion notification, the system started loading module files from GitLab (takes 1-5 seconds). But it also immediately told the preview to compile — before the files had actually loaded. The preview looked at the file system, found nothing, and showed an error.

The Fix: The preview now waits for all files to finish loading from GitLab before attempting to compile. We use a proper "all files loaded" signal instead of firing immediately.

File: libs/libs-structural/vitto-studio/src/lib/services/studio-generation-listener.service.ts


Phase 4: Fix #3 — One-Time Subscription Bug (Frontend)

The Problem: Even with correct timing, the "files loaded" signal was being ignored after the first page load.

Why it happened: The code had a take(1) operator that means "listen only once, then stop forever." On a fresh page load, the first signal was "0 modules loaded" (correct — the platform doesn't exist yet). After that, the listener stopped. When the generation completed and modules WERE loaded, the signal fired again but nobody was listening.

The Fix: Removed the take(1) so the listener stays active for the entire page session.

File: libs/libs-structural/vitto-studio/src/lib/components/studio-dock-shell/studio-dock-shell.component.ts


Phase 5: Fix #4 — Reading from the Wrong Branch (Frontend + Backend)

The Problem: Even with all the above fixes, the file system was loading from an empty branch.

Why it happened: Generated code goes to a feature branch (e.g., feature/generation-1773866366723). A separate "activation" process merges it to the develop branch. But activation requires a "generation manifest" to be created — and the manifest wasn't being created (see Fix #5). So develop stayed empty, and the preview had nothing to show.

The Fix: The backend now includes the feature branch name in the completion notification. The frontend switches to that branch before loading files. This bypasses the broken manifest → activation → merge chain entirely.

Files:


Phase 6: Fix #5 — Silent Manifest Failure (Backend Diagnostics)

The Problem: The Generations panel shows "No generations yet" — the manifest is never created.

Why it happened: The API activity logs show that the POST /generations endpoint was never called during the DEPLOY phase. The manifest creation code is gated on successful GitLab commit AND uses optional chaining (backendApiClient?.) which silently returns undefined if the service is null. There was zero logging when this happened.

The Fix: Added comprehensive error-level logging at every point where the manifest creation can be silently skipped:

This will identify the exact root cause on the next generation run.

File: APIs/backend-vitto-api/src/app/module-generation/phases/module-gen-phase.executor.ts


Summary of All Changes

File What Changed Why
module-gen-phase.executor.ts Emit events before status change; include featureBranch; add diagnostic logging Fixes SSE race condition, enables branch bypass, diagnoses manifest failure
module-gen.plugin.ts Forward featureBranch field in SSE events Passes branch info from backend to frontend
studio-generation-listener.service.ts Wait for VFS completion; switch to feature branch Prevents empty preview; reads from correct branch
studio-dock-shell.component.ts Remove take(1) from modulesLoaded$ subscription Allows re-triggering after generation
vfs-sync.service.ts Add switchToBranch() and clearLoadedSlugs() methods Enables branch switching and cache clearing

What's Working Now


What Still Needs Work

Must Do (Next Session)

  1. Live test — Restart backend-vitto-api and run a new generation to verify the fixes
  2. Diagnose manifest root cause — The new logging will reveal whether the issue is gitConfig, backendApiClient, or HTTP call failure
  3. Fix manifest creation — Once diagnosed, fix the underlying cause so the Generations panel works

Should Do (Near-Term)

  1. Environment placeholders — Generated environment.ts has test-space-id and test-universe-id instead of real values
  2. Two 500 errors — During DEPLOY, 2 of 5 POST /ai-api/modules calls returned 500. Need to investigate what causes intermittent module persistence failures.
  3. Excessive mood inference calls — The API logs show /vitto-api/moods/infer being called every 15 seconds during generation (~80 calls over 20 minutes). Consider reducing frequency during long-running operations.

Could Do (Future)

  1. Preview auto-refresh after activation — When a generation IS activated (merged to develop), the VFS should auto-switch back to develop
  2. Rollback UI — The lastGenerationCommitSha signal enables rollback, but no UI exists yet

Architecture Lessons Learned

  1. Emit events before status changes — When a polling consumer watches for status changes, any await between the status change and event emission creates a race condition window.

  2. Never use take(1) on lifecycle-spanning signals — If a Subject needs to fire multiple times (init + post-action), take(1) silently kills the subscription.

  3. Wait for completion signals, not timers — Fixed-delay timers (500ms) are fragile. Use proper completion signals (forkJoin → Subject.next()).

  4. Include bypass data in events — When a chain (manifest → activate → merge → VFS) can fail at any link, include the final destination data (branch name) in the event so consumers can skip the chain.

  5. Log the absence, not just the error — When optional chaining silently skips a call, the absence of a log entry is the bug. Always log explicitly when a critical path is skipped.


MCP Decisions Logged

ID Type Description
dev_1773921302780_hkxsxgj bugfix SSE race condition — emit before status change
dev_1773921315730_oil3e2i bugfix VFS timing — wait for modulesLoaded$
dev_1773921324971_tfhpg1m bugfix take(1) removal on modulesLoaded$
dev_1773921343702_txsy2r0 bugfix featureBranch in completed event + VFS switch
dev_1773921357980_vk3b2hm investigation Manifest creation diagnostic logging

Conventions Added


Generated by Claude Code — Session 236