📋 Pipeline Overview
Stage 1: Submit & Route
handlePromptSubmit handles validation, exit-word handling, queue vs immediate.
Stage 2: Input Classification
processUserInput manages image resize, slash/bash/text branching, hooks.
Stage 3: Message Construction
processTextPrompt and createUserMessage build typed UserMessage objects.
Stage 4: API Normalization
normalizeMessagesForAPI flattens, deduplicates, strips virtual messages.
🚀 Stage 1: handlePromptSubmit
Two execution paths: queue processor (pre-validated commands) and direct input (reference expansion, exit checking, queue guard). Immediate commands (/config, /doctor) can execute while query is in progress.
💡 Concurrency
Queue guard reserves BEFORE processUserInput starts, preventing race conditions during awaits.
🔍 Stage 2: processUserInput
Images resize in parallel via Promise.all. Three-way branch: bash mode, slash command, text prompt. Hidden fourth branch: ultraplan keyword rewrites to /ultraplan.
💡 Bridge Safety
Messages from iOS/web arrive with skipSlashCommands: true. bridgeOrigin flag allows known-safe commands through while blocking unsafe ones.
📝 Stage 3: Message Construction
createUserMessage stamps: uuid (stable identity), isMeta (model-visible but hidden from transcript), origin (provenance), permissionMode (safety snapshot), toolUseResult, imagePasteIds.
💡 isMeta Messages
Image metadata messages (dimensions, source path) sent to model but hidden from UI. Gives spatial context without polluting transcript.
⚙️ Stage 4: API Normalization
Reorder attachments
Bubble up until hitting tool result or assistant boundary.
Strip virtual messages
Display-only messages never reach the API.
Merge consecutive same-role
API requires strict alternating user/assistant turns.
Tool result pairing
Every tool_use must have matching tool_result. Orphans get SYNTHETIC_TOOL_RESULT_PLACEHOLDER.
💡 Training Data Guard
SYNTHETIC_TOOL_RESULT_PLACEHOLDER exported so HFI submission path can detect and reject payloads with fake tool results.
📊 Message Taxonomy & Hooks
Six message types: UserMessage, AssistantMessage, AttachmentMessage, SystemMessage, ProgressMessage, TombstoneMessage. UserPromptSubmit hooks run after classification, before API call - can block, annotate, or stop any prompt.
💡 Memory Correction Hint
When auto-memory enabled, rejection/cancellation messages get postscript nudging model to save user preferences to memory.