S204 Handoff

Documentation for Sessions

S204: Generation Pipeline E2E — Handoff Document

Session Summary

Goal: Verify the full code generation pipeline E2E (UI → Vitto → GitLab → MongoDB) and fix every gap found.

Result: 21+ sub-commits (S204.1–S204.21). Pipeline works end-to-end — code generates, commits to GitLab, and persists rich metadata to MongoDB. Major architectural improvements to local fallback, universe data persistence, chat UI streaming, and deprecated code removal.

Status: Generation pipeline is FUNCTIONAL. GitLab commits succeed. Chat UI fix (S204.21) and universe slug fix need frontend recompile + backend restart to verify.


What Was Done

Phase 1: Deprecation & Consolidation (S204.6, S204.9)

Phase 2: Bug Fixes (S204.7–S204.17)

Sub Bug Root Cause Fix
.7 CastError on generationHistory modules changed from number to array in S200, 3 callsites still did || 0 Array.isArray(m) ? m.length : ...
.8 SSE events not forwarded to chat Only 3 event types forwarded, terminal events silently dropped Expanded to 9 event types
.11 "5 modules, 0 files" — no GitLab repo universeId lost in 5-layer context chain (extracted from plain text pageContext) Pass explicitly through all 5 layers
.12/.16 Vitto ignores missing context, searches memories Soft instruction in tool response — LLM treats as suggestion Hard error + explicit tool blocklist + doNotRetry flag
.13 ESLint "lexical declaration in case block" const in switch case without braces Wrapped case bodies in { }
.14 Empty chat cards after generation task.completed with empty response created empty message Guard: response || toolCalls.length > 0 + filter non-phase events
.15 GitLab 400 on group name "Space: {slug}" Colon : rejected by GitLab API sanitizeGitLabPath() at 3 levels
.15 Vitto auto-retries failed generation No stop signal doNotRetry: true in tool response
.16 "Untitled" memories VittoMemory has summary but no title Derive title from first 80 chars of summary
.17 GitLab commit duplicate files + N+1 API calls Template + LLM produce same paths Map<path, FileCommit> dedup + optimistic create-all

Phase 3: UX Polish (S204.10, S204.14)

Phase 4: Architecture Improvements (S204.18–S204.20)

Phase 5: Chat UI & Naming (S204.21)


Architecture State After S204

Generation Flow (Single Path)

UI (vibe-universe) → WorkflowStateService.startWorkflow()
  → GET /vitto-api/module-generation/start (SSE)
  → 7-phase pipeline: ENHANCE → ANALYZE → DECOMPOSE → PLAN → EXECUTE → INTEGRATE → DEPLOY
  → DEPLOY: GitLab commit + MR + universe manifest update
  → On GitLab failure (admin/dev + opt-in): ~/.gograb/generated/ fallback

Chat UI Streaming Architecture

Backend SSE: tool.progress { eventType: 'module-gen.phase-start', phase: 'EXECUTE', ... }
  → VittoChatEngineService.onmessage():
      1. streamingService.setPhase('EXECUTE')     → drives thinkingContext label
      2. streamingService.state.isStreaming = true → activates thinkingContext
      3. Creates progress card message (role: 'task') with tool metadata
  → VittoChatStreamingService.thinkingContext:
      'EXECUTE' → "Generating code..."            → shown in UI thinking indicator
  → On task.completed:
      streamingService.stopStream()                → resets phase, clears label

Context Chain (5 Layers)

Frontend: UniverseContextService.universeId()
  → Controller: vitto.controller.ts (universeId, spaceSlug, universeSlug in body)
  → Engine: vitto-engine.service.ts (prefers explicit over pageContext)
  → AgentLoop: agent-loop.service.ts (forwards to executeTool)
  → Tool: tool-registry.service.ts (reads from context?.universeId)

Inter-Service Communication

vitto (3003) → backend-api (3000):  BackendApiClientService  (users, spaces, prefs, universe slug)
vitto (3003) → backend-ai-api (3001): BackendAiClientService  (handoffs, learning, modules)
ai-api (3001) → backend-api (3000):  PlatformApiClientService (platform queries)
Auth: BACKEND_API_INTERNAL_TOKEN as Bearer header (same as SYSTEM_TOKEN)
Dev: localhost:{port} | Prod: {service}.gograb.space (public HTTPS)

Universe Document (After Generation)

universe {
  structure: V2StructureNode[]        // Navigation tree (sidebar + modules + pages)
  gitConfig: { repoPath, commitSha }  // GitLab repo info
  deploymentStatus: 'generated'       // Updated from 'draft' after successful generation
  generationManifest: {               // S204.20 — rich platform representation
    version: '1.0',
    systemName: 'Sports League Manager',
    modules[]: {
      name, slug, category,
      entities[]: { name, fields[]: { name, type, required } },
      routes[]: { path, title, pageType },
      embeddables[], actions[]
    },
    navigation[]: { label, route, icon, order },
    files: { total, paths[]: { path, language, module }, byModule[] },
    quality: { score, moduleCount, entityCount, totalTokens, durationMs },
    deployment: { gitLab: { commitSha, branch }, persistedModuleIds[] }
  }
}

Known Gaps & Pending Work

Must Verify (Immediate — needs restart)

  1. Chat UI "Thinking..." fix (S204.21): Frontend recompile needed. The streaming service phase wiring should replace "Thinking..." with per-phase labels. Verify by triggering generation and watching the indicator change through all 7 phases.

  2. GitLab universe slug fix (S204.21): Backend-vitto-api restart needed. Verify that new generations create repos named vitto-uni-test-1 instead of universe_1772912869184_w1y1ktx. The existing repo won't rename — only new repos use the resolved slug.

  3. Generation manifest persistence (S204.20): Verify generationManifest appears on the universe document in MongoDB after a successful generation. Check via db.universes.findOne({ slug: 'vitto-uni-test-1' }).

Must Fix (Next Session)

  1. gitConfig 500 error: PUT /spaces/{spaceId}/universes/{universeId} fails when universeId is a generated string (not MongoDB ObjectId). Backend-api expects ObjectId. Need to either: use actual universe ObjectId from creation, or make the endpoint accept slug-based IDs.

  2. Memory title field: Currently using stopgap (derive from first 80 chars of summary). Should add optional title field to VittoMemory schema and populate at write time.

  3. Stale GitLab feature branches: Each generation creates a new feature/generation-{timestamp} branch. Old branches from failed/superseded runs accumulate. Add cleanup: on new generation, close stale MRs and delete old feature branches for the same universe.

Should Improve (Near-term)

  1. Service organization: module-gen-phase.executor.ts is ~3000 lines. Split into focused services:

    • GitLabDeployService (commit, MR, fallback, stale branch cleanup)
    • UniverseManifestService (structure, manifest, gitConfig persistence)
    • LocalFallbackService (disk write, preference check)
  2. Module filtering: Vitto memories aren't properly scoped by userId/spaceId. recall_vitto_memory should filter by the current user's space.

  3. Generated code quality: The standalone output at ~/.gograb/generated/ needs an angular.json and proper tsconfig for ng serve to work. Currently has package.json but no Angular workspace config.

  4. Frontend generation preferences UI: GenerationPreferences exists in the schema but there's no UI to toggle localFallbackEnabled or change outputMode. Add a section to the user settings page.

Strategic (Future Sessions)

  1. Generation history on universe: Track multiple generation runs — each generationManifest should be versioned, with the latest one active and previous ones in a generationHistory[] array. This enables diffing and rollback.

  2. Post-generation validation: After GitLab commit, trigger a CI pipeline that runs ng build on the generated code. Report build success/failure back to the universe document.

  3. Vitto reads manifest for context: When a user asks Vitto "what modules does my platform have?", Vitto should read universe.generationManifest instead of searching memories. Add a read_universe_manifest tool or enhance query_platform.

  4. Railway internal networking: All inter-service calls go through public HTTPS domains. Railway supports private networking ({service}.railway.internal) which would reduce latency and bypass TLS overhead.

  5. Sub-agent personality layer: Use a cheaper/faster model (Haiku) to generate Vitto's personality responses during generation phases — fun commentary, progress narration, etc. — while the main pipeline uses the full model for code generation.


Key Files Modified

File Lines What Changed
module-gen-phase.executor.ts ~3000 Local fallback rewrite, manifest persistence, gitCommitInfo tracking, universe slug resolution
vitto-chat-engine.service.ts ~830 Phase timing, personality quips, universe context, S204.21: streaming service phase wiring
vitto-chat-streaming.service.ts ~200 S204.21: expanded thinkingContext with 7 generation phases + generation tools
chat.types.ts ~220 S204.21: VittoPhase expanded with ENHANCE, DECOMPOSE, INTEGRATE, DEPLOY
task-progress-card.component.ts ~80 S204.21: phaseLabel map updated with all 8 phases
user-preferences.schema.ts ~390 Added GenerationPreferences sub-schema
backend-api-client.service.ts ~270 Added getGenerationPreferences()
tool-registry.service.ts ~1200 SSE forwarding, hard error, doNotRetry, memory titles
vitto-engine.service.ts ~600 universeId/slugs in params
agent-loop.service.ts ~400 Forward spaceSlug/universeSlug to executeTool
vitto.controller.ts ~200 Accept universeId/slugs in POST body
universe-git.service.ts ~500 Slug sanitization, file dedup, optimistic commits
generation-hub.service.ts 73 Deprecated stub
chat-module-panel.component.ts 105 Rewired to WorkflowStateService

Conventions Established

  1. Local fallback: NEVER write generated code inside monorepo. ~/.gograb/generated/ only. Gated by role + preference + GitLab failure.
  2. Generation manifest: Universe doc MUST have generationManifest after generation. This is Vitto's primary platform understanding.
  3. Inter-service auth: BACKEND_API_INTERNAL_TOKEN = SYSTEM_TOKEN. Dedicated client services in connectivity/.
  4. LLM tool errors: Hard error + explicit blocklist + doNotRetry. Never soft instructions.
  5. GitLab slugs: sanitizeGitLabPath() before ANY API call. Group names reject : and special chars.
  6. Context chains: All 5 layers must explicitly pass universeId, spaceSlug, universeSlug. Never rely on pageContext extraction.
  7. Chat streaming: Both streaming paths (SSE engine + streaming service) must stay in sync. Engine must call streamingService.setPhase() on phase events and stopStream() on completion.
  8. GitLab repo naming: Always resolve human-readable universe slug from backend-api. Never use raw universeId as the repo name.

MCP Intelligence Captured


Quick Start for Next Agent

# 1. Restart backend to pick up all changes
# Kill existing backend-vitto-api process, then:
yarn serve:backend-vitto

# 2. Verify frontend recompiled (Angular dev server should auto-detect changes)
# If not, restart:
yarn serve:space

# 3. Test generation E2E
# - Go to /vibe on port 6200
# - Enter a universe, type a generation prompt
# - Watch the "Thinking..." label — should cycle through phase names
# - Check GitLab: repo should use universe slug, not ID
# - Check MongoDB: universe doc should have generationManifest

# 4. Key log lines to watch in vitto-api terminal:
# [ModuleGen:Executor] PRE-FLIGHT: Resolved universe slug: "xxx"
# [ModuleGen:Executor] DEPLOY: Persisted generation manifest to universe
# [ToolRegistry] start_module_generation: Waiting for session xxx