diff --git a/docs/reports/SSDL_DISCUSSION_AI_TURN_CYCLE_20260613.md b/docs/reports/SSDL_DISCUSSION_AI_TURN_CYCLE_20260613.md new file mode 100644 index 00000000..30914f51 --- /dev/null +++ b/docs/reports/SSDL_DISCUSSION_AI_TURN_CYCLE_20260613.md @@ -0,0 +1,190 @@ +# SSDL Report: Discussion AI Turn Cycle + +**Track/Context:** Technical Architecture Reference +**Date:** 2026-06-13 +**Status:** Completed +**Subject:** Full SSDL trace of a discussion AI turn cycle from user prompt to AI response and handoff. + +--- + +## 1. Executive Summary + +This report traces the execution flow and data lifecycle of a single **Discussion AI Turn Cycle** in the Manual Slop orchestrator. The cycle starts with a user-submitted prompt in the ImGui interface, flows through thread-offloaded controllers and event queues, enters the LLM provider context-enrichment and tool execution engine (HITL clutch), streams partial tokens back to the UI thread, and finally updates the persistent state, returning control to the user. + +We model this end-to-end flow using the **Spec/Sketch Description Language (SSDL)** syntax. + +--- + +## 2. End-to-End SSDL Topology Diagram + +This diagram displays the flow across three distinct execution boundaries: +1. **The UI Thread** (ImGui render loop ticking at 60 FPS) +2. **Background IO/Worker Threads** (asynchronous worker pools) +3. **Queue Processors** (mediating communication between threads) + +``` +=================================================================================================== + DISCUSSION AI TURN CYCLE TOPOLOGY +=================================================================================================== + +[UI Thread (60 FPS)] [Worker Thread (IO Pool)] [Worker Thread (AI / Tools)] +-------------------- ------------------------- ---------------------------- + +[Q:ui_ai_input] + │ + ▼ +[I:render_message_panel] + │ +[B:Gen+Send Clicked?] ─── yes ───► [I:_handle_generate_send] + │ + (submit_io) + │ + ▼ + [I:_do_generate] + (construct context) + │ + ▼ + [I:events.UserRequestEvent] + │ + (put queue) + │ + ▼ + [S:event_queue (Q)] + │ + (dequeue loop) + │ + ▼ + [_process_event_queue] + │ + (submit_io) + │ + ▼ + [_handle_request_event] + │ + [B:RAG Enabled?] + ╱ ╲ + yes no + ╱ ╲ + ▼ ▼ + [I:rag_engine.search] [I:parse_symbols] + │ │ + ▼ ▼ + └──────► [M] ◄──────┘ + │ + ▼ + [I:ai_client.send] + │ + ▼ + [I:run_with_tool_loop] ◄──────────────────────┐ + │ │ (next round) + ▼ │ + [B:Tool Calls Returned?] │ + ╱ ╲ │ + yes no │ + ╱ ╲ │ + ▼ ▼ │ + [I:_confirm_and_run (HITL)] [I:Stream Callback] │ + [B:Clutch Approved?] │ │ + ╱ ╲ ▼ │ + yes no [S:event_queue] │ + ╱ ╲ │ │ + ▼ ▼ │ (dequeue) │ + [I:_run_script] [I:abort] ▼ │ + [I:mcp_dispatch] │ [S:_pending_gui_tasks] │ + │ │ │ │ + ▼ ▼ │ (UI Thread tick) │ + └───────► [M] ◄──────────┘ ▼ │ + │ [I:_handle_ai_response] │ + ▼ │ │ + [I:Record Tool Result] ▼ │ + │ (append stream view) │ + ▼ │ │ + [I:Trim Token History] └───────────────────┘ + │ + (loop ends) + │ + ▼ + [I:Final Result Wrapper] + │ + ▼ + [S:event_queue] + │ + (dequeue) + ▼ + [S:_pending_gui_tasks] + │ + (UI tick) + ▼ + [I:_handle_ai_response] + │ + ▼ + [I:render_response_panel] + │ + ▼ + [T:User] +``` + +--- + +## 3. Step-by-Step Execution Trace + +### Phase 1: User Request Generation (UI Thread) +1. **Query Input**: The ImGui render loop queries the text input buffer: + `[Q:ui_ai_input] -> [I:render_message_panel]` +2. **Branch Check**: The loop checks if the `Gen + Send` button is clicked and if the queue is idle: + `[B:Gen+Send Clicked? (send_busy?)]` +3. **Dispatch**: If clicked, the controller triggers `App._handle_generate_send()`, which delegates to the controller: + `[I:_handle_generate_send]` + +### Phase 2: Context Construction & Queue Placement (IO Thread) +1. **Thread Offloading**: `AppController._handle_generate_send` submits a worker to the IO thread pool: + `self.submit_io(worker)` +2. **Curation Aggregation**: The background worker calls `_do_generate()` which flushes config, builds the active project configuration, and curates context files: + `[I:_do_generate] ─── (queries context_files)` +3. **Payload Wrapping**: Wraps the collected data into a `UserRequestEvent` struct. +4. **Queue Placement**: Pushes the event to the thread-safe queue: + `[S:event_queue] (user_request)` + +### Phase 3: Background Event Processing & Enrichment (AI/Worker Thread) +1. **Event Dequeue**: The event thread loop (`_process_event_queue()`) fetches the `"user_request"` event. +2. **Thread Offloading**: It submits the request handler to execute asynchronously on the IO pool: + `self.submit_io(self._handle_request_event, payload)` +3. **RAG Retrieval**: The request thread queries ChromaDB using the user prompt and prepends chunks to the query: + `[Q:rag_engine] -> [I:rag_engine.search] -> [S:user_msg]` +4. **Symbol Resolution**: Parsed code symbols are looked up in active files and Python AST definitions are appended: + `[I:parse_symbols] -> [I:get_symbol_definition] -> [S:user_msg]` +5. **Comms Logging**: Pushes a comms logging request event onto the queue. +6. **Client Setup**: Configures global variables, custom and base system prompts, and temperature boundaries on the `ai_client` instance. +7. **Provider Invocation**: Dispatches the enriched request to the client endpoint: + `[I:ai_client.send]` + +### Phase 4: The Tool Loop & Human-In-The-Loop (HITL) Gate +1. **Provider Resolution**: `ai_client` maps to the active vendor (e.g. Gemini, Grok, MiniMax). +2. **Loop Iteration**: Runs `run_with_tool_loop(client, request, capabilities)`. +3. **Tool Call Check**: If the provider returns tool requests: + * **HITL Clutch Approval**: For each tool, the clutch mode is checked (ask vs auto). If ask, the loop raises `mma_spawn_approval` or `mma_step_approval` events. + * **Execution Suspension**: The background worker thread blocks/waits for approval state. + * **User Decision**: In the GUI thread, the user approves or rejects. + * **Execution**: If approved, the tool runs (PowerShell via `_run_script` or MCP client API dispatch): + `[I:_run_script] / [I:mcp_client.async_dispatch]` + * **Result Record**: Appends the tool outputs to history and prunes history if token limit is exceeded. + * **Loop Iteration**: Loops back to call the LLM again with results. +4. **Streaming Callback**: For every text chunk received from the LLM, the `stream_callback` triggers: + `[I:_on_ai_stream] -> [S:event_queue] (response)` + +### Phase 5: Handoff Back to User (UI Thread) +1. **Enqueue Stream**: The event loop `_process_event_queue` dequeues `"response"` events and pushes them to `self._pending_gui_tasks`. +2. **UI Thread Dequeue**: The main ImGui render loop ticks (60 FPS) and calls `app._process_pending_gui_tasks()`. +3. **Update UI State**: Runs `_handle_ai_response()`, which appends text to `self.ai_response` and sets `self._ai_status = "streaming..."` or `"done"`. +4. **Blink Alert**: Triggers UI window blinking and focuses the Response panel: + `[S:_trigger_blink]` +5. **Final Render**: Renders final markdown output in `render_response_panel`. Keyboard focus returns to the input field, ready for the user's next request: + `[T:User]` + +--- + +## 4. Key Architectural Invariants + +* **Thread-Safety**: All mutable updates to GUI-rendering variables (like `ai_response` and `ai_status`) occur strictly on the main thread via the `_pending_gui_tasks` synchronization list. +* **Non-Blocking GUI**: The ImGui render loop never performs network I/O or file compilation directly. All RAG, parsing, model API connections, and tool executions run on the background IO pool. +* **Data Integrity**: Enriched prompts are logged to history exactly as sent to the LLM (including RAG snippets and symbol definitions), maintaining auditability.