2026 03 23 Generation Pipeline Optimization Design

Documentation for Plans

Generation Pipeline Optimization — Speed, Cost, Interactivity

Session: 257 | Date: 2026-03-23 | Status: Design (revised after spec review)


Problem Statement

Platform generation is slow (15 min for 5 modules), expensive ($2.50 per generation), and feels unresponsive — users watch repetitive phase messages with no visual feedback until everything completes.

Root causes:

  1. Default output mode is VISUAL — generates JSON blueprints but no code files. The existing progressive preview code (S246) is dead because SSE events never carry files.
  2. The implement.prompt.md system prompt (~10K tokens) is re-sent identically with every EXECUTE call — no prompt caching.
  3. Visual path runs in the critical path — when set to BOTH, visual JSON and code generate as parallel LLM calls per module, doubling API calls.
  4. All phases run strictly sequentially — PLAN must finish ALL modules before EXECUTE starts any.

What's already working (verified):


Changes (4 items)

A. CODE-First Output, Visual Deferred to Background Haiku

What: Change the default outputMode from VISUAL to CODE. After all code modules complete, fire background Haiku calls to generate visual JSON metadata (non-blocking, fire-and-forget with error logging).

Where:

Flow change:

BEFORE: Per module → [Visual LLM (Sonnet)] + [Code LLM (Sonnet)] in parallel
AFTER:  Per module → [Code LLM (Sonnet)] only in critical path
        After all complete → [Visual LLM (Haiku)] per module, fire-and-forget background

Impact:

Risk: Low. Visual JSON arrives late for Studio workbench metadata panel. Acceptable — users watch the live preview, not the metadata panel.


B. Prompt Caching on EXECUTE System Prompts

What: Enable Anthropic prompt caching on the implement.prompt.md system prompt, which is identical for every EXECUTE call (only the user message changes per module).

Where:

How Anthropic prompt caching works:

Cost savings calculation:

Risk: Low. Cache misses just fall back to normal pricing. The provider refactoring is localized to claude.provider.ts.


C. Pipeline Overlap: Stream Modules from PLAN → EXECUTE

What: Currently PLAN collects ALL modules into an execution plan, then EXECUTE starts. Instead, PLAN emits each module's plan as it resolves, and EXECUTE starts generating code immediately.

Where:

Flow change:

BEFORE: PLAN (all modules) ──────────→ EXECUTE starts first module
AFTER:  PLAN(M1) → EXECUTE(M1) starts immediately
        PLAN(M2) → EXECUTE(M2) starts (parallel with M1, if independent)
        PLAN(M3) → queued until batch slot opens

Constraints:

Impact: First module starts generating ~30-60s earlier. More noticeable for platforms with 5+ modules.

Risk: HIGH. This is the most complex change. The executor orchestration, checkpointing, and inter-module context all need redesign. Should be done last, possibly in a separate session.


D. Activate Progressive Preview (Already Built, Currently Dead)

What: Change A (CODE-first output) automatically activates the existing S246 progressive preview code. SSE events will now carry files, and handleModuleGenerated() will process them instead of returning early.

Additional work needed:

Impact: User sees the first module rendering in preview ~3 minutes after generation starts, instead of waiting 15+ minutes. Each subsequent module appears incrementally.

Risk: Low for basic functionality. App shell partial module handling is new but straightforward.


Revised Cost Model

5-module CRUD platform generation:

Component Before After Savings
EXECUTE code (5 × Sonnet) $1.84 $1.84 —
EXECUTE visual (5 × Sonnet, critical path) $0.12 — $0.12 (deferred)
Deferred visual (5 × Haiku, background) — $0.01 —
System prompt caching (EXECUTE) — -$0.11 $0.11
ENHANCE (Haiku) $0.01 $0.01 —
ANALYZE + DECOMPOSE (Sonnet) $0.04 $0.04 —
PLAN (Opus) $0.02 $0.02 —
INTEGRATE (Haiku) $0.01 $0.01 —
Validate/Fix (0-4 × Sonnet) $0.04 $0.04 —
Total ~$2.08 ~$1.85 ~$0.23 (11%)

The primary value is timing and UX, not cost reduction.

Timing model:

Metric Before After
Time to first preview ~15 min ~3 min
Total generation time ~15 min ~12 min (with pipeline overlap)
LLM calls in critical path 10 5
Perceived responsiveness Dead screen Incremental module rendering

Implementation Order

  1. A. CODE-first output — Highest impact, unblocks D. Change defaults on 3 controller endpoints + frontend audit.
  2. D. Progressive preview — Depends on A. Partial app shell synthesis + recompile trigger verification.
  3. B. Prompt caching — Independent. Requires claude.provider.ts refactoring (string → content block format).
  4. C. Pipeline overlap — Highest complexity, do last (possibly separate session). Requires executor/checkpoint redesign.

Files to Modify

File Changes
APIs/backend-vitto-api/src/app/module-generation/module-generation.controller.ts Default outputMode → CODE on 3 endpoints
APIs/backend-vitto-api/src/app/module-generation/phases/execute.phase.ts Deferred visual background job, cacheSystemPrompt flag
APIs/backend-vitto-api/src/app/llm/providers/claude.provider.ts System prompt → content block array for cache_control
APIs/backend-vitto-api/src/app/llm/llm.types.ts Add cacheSystemPrompt to SendOptions
libs/libs-structural/platform-preview/src/lib/services/bundler-filesystem.service.ts Partial module app shell synthesis
Frontend audit needed: Grep all callers for explicit outputMode: 'visual' overrides.

E. Increase Parallel Batch Size (PARALLEL_MODULE_GEN_BATCH=5)

What: Change the parallel module generation batch size from 3 to 5. For a 5-module platform, this means all modules generate in a single batch instead of two sequential batches — cutting EXECUTE wall time by ~40%.

Where: .env.local — env var PARALLEL_MODULE_GEN_BATCH=5

Impact: For 5-module platforms, drops from 2 sequential batches to 1. Wall time improvement: ~4-6 minutes faster.

Risk: Higher concurrent API load. Anthropic rate limits may throttle at 5 parallel calls. Monitor for 429 errors. Can be tuned down to 4 if needed.


F. JSON Re-Prompt on Parse Failure

What: When extractCodeFiles() fails all 3 parsing strategies (parseLlmJson, brace-depth, individual object extraction), instead of returning empty, re-prompt the LLM with a strict JSON structure instruction. Adopted from gmodules1's explicit retry pattern.

Where: APIs/backend-vitto-api/src/app/module-generation/phases/execute.phase.ts — end of extractCodeFiles() method.

Flow:

LLM response → parseLlmJson → FAIL
            → brace-depth  → FAIL
            → individual objects → FAIL
            → RE-PROMPT: "Your response was not valid JSON. Return ONLY: { files: [...] }"
            → Parse retry response → SUCCESS or give up

Impact: Eliminates a class of generation failures where the LLM produces valid code wrapped in invalid JSON (markdown fences, explanatory text, truncated braces).

Risk: Low. Adds one extra LLM call only on failure (currently ~5% of generations). Cost is negligible.


G. CONFIRM Phase — User Gate Before EXECUTE

What: After PLAN completes, emit an SSE event with the execution plan and pause. The user sees: what modules will be generated, estimated cost, dependencies. They can approve, modify, or cancel before spending money on code generation.

Where:

Flow:

ENHANCE → ANALYZE → DECOMPOSE → PLAN
  → Emit SSE: module-gen.confirm-plan { modules, estimatedCost, dependencies }
  → PAUSE (wait for user confirmation or 5-min auto-approve timeout)
  → User approves → EXECUTE → INTEGRATE
  → User cancels → Emit module-gen.cancelled, clean up session

Impact: Saves ~$2 when user catches a bad plan early. Builds trust — users feel in control. Reduces wasted generations.

Risk: Medium. Adds complexity to session state management (paused state, confirmation endpoint, timeout handling). Frontend needs a new UI component.


What's NOT Changing


Removed from Spec

Pipeline overlap (PLAN→EXECUTE streaming) — Removed after analysis. PLAN is a single LLM call that produces all modules at once — there's nothing to stream. Overlapping saves ~30s on a 12-minute pipeline (3% improvement) for HIGH complexity (executor/checkpoint redesign). Not worth it.


Future Investigation

Structured output / tool_use for code generation — Instead of prompting the LLM to return JSON and parsing with fallback strategies, use Claude's tool_use with a strict JSON schema that enforces { files: [{ path, content, language }] }. This would eliminate parsing failures entirely. Needs investigation to verify Claude handles 32K+ token tool responses.