Log in
docs/accept-execute-flow.md 164 lines · 14.5 KB

Accept & Execute Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  BROWSER (WASM)                                                     β”‚
β”‚                                                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                               β”‚
β”‚  β”‚ "Approve &       β”‚  on_click                                     β”‚
β”‚  β”‚  Execute" button  β”œβ”€β”€β”€β”€β”€β”€β”                                       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚                                        β”‚
β”‚                             β–Ό                                       β”‚
β”‚                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                               β”‚
β”‚                   β”‚ ApprovalBar      β”‚                               β”‚
β”‚                   β”‚ set_phase(       β”‚                               β”‚
β”‚                   β”‚   Decomposing)   β”‚                               β”‚
β”‚                   β”‚ dispatch action  β”‚                               β”‚
β”‚                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                               β”‚
β”‚                            β”‚                                        β”‚
β”‚                            β”‚ POST /api/start_execution{hash}        β”‚
β”‚                            β”‚ (Leptos server fn)                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
                             β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  SERVER (SSR / Axum)                                                β”‚
β”‚                                                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                           β”‚
β”‚  β”‚ start_execution()                     β”‚                          β”‚
β”‚  β”‚                                       β”‚                          β”‚
β”‚  β”‚  1. Verify .pas/spec.md exists  β”‚                          β”‚
β”‚  β”‚                                       β”‚                          β”‚
β”‚  β”‚  2. β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚                          β”‚
β”‚  β”‚     β”‚ $ pas decompose         β”‚      β”‚                          β”‚
β”‚  β”‚     β”‚   .pas/spec.md    β”‚      β”‚                          β”‚
β”‚  β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚                          β”‚
β”‚  β”‚                 β”‚ stdout               β”‚                          β”‚
β”‚  β”‚                 β–Ό                      β”‚                          β”‚
β”‚  β”‚     Parse "Epic ID: attractor-xxx"    β”‚                          β”‚
β”‚  β”‚                 β”‚                      β”‚                          β”‚
β”‚  β”‚  3. β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚                          β”‚
β”‚  β”‚     β”‚ $ pas scaffold          β”‚      β”‚                          β”‚
β”‚  β”‚     β”‚   <epic-id>             β”‚      β”‚                          β”‚
β”‚  β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚                          β”‚
β”‚  β”‚                 β”‚                      β”‚                          β”‚
β”‚  β”‚                 β–Ό                      β”‚                          β”‚
β”‚  β”‚     Read pipelines/<epic-id>.dot      β”‚                          β”‚
β”‚  β”‚                 β”‚                      β”‚                          β”‚
β”‚  β”‚  4. Parse .dot β†’ PipelineGraph        β”‚                          β”‚
β”‚  β”‚                 β”‚                      β”‚                          β”‚
β”‚  β”‚  5. β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚                          β”‚
β”‚  β”‚     β”‚ tokio::spawn background     β”‚  β”‚                          β”‚
β”‚  β”‚     β”‚ run_pipeline_with_streaming β”‚  β”‚                          β”‚
β”‚  β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚                          β”‚
β”‚  β”‚                 β”‚                      β”‚                          β”‚
β”‚  β”‚  Return ExecutionResponse             β”‚                          β”‚
β”‚  β”‚  { session_id, epic_id,              β”‚                          β”‚
β”‚  β”‚    pipeline_path }                    β”‚                          β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚             β”‚               β”‚                                       β”‚
β”‚             β”‚               β–Ό (background task)                     β”‚
β”‚             β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚             β”‚    β”‚ run_pipeline_with_streaming()      β”‚              β”‚
β”‚             β”‚    β”‚                                    β”‚              β”‚
β”‚             β”‚    β”‚  Initialize Context (workdir,      β”‚              β”‚
β”‚             β”‚    β”‚    graph attrs)                    β”‚              β”‚
β”‚             β”‚    β”‚         β”‚                          β”‚              β”‚
β”‚             β”‚    β”‚         β–Ό                          β”‚              β”‚
β”‚             β”‚    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚ For each node:      β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚                     β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚  publish_event ───────────► SSE broadcast     β”‚
β”‚             β”‚    β”‚  β”‚  { type:node_start, β”‚     channel              β”‚
β”‚             β”‚    β”‚  β”‚    node_id, label } β”‚     (in-memory)          β”‚
β”‚             β”‚    β”‚  β”‚         β”‚           β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚  Execute handler    β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚  (registry lookup)  β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚         β”‚           β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚  publish_event ───────────► SSE broadcast     β”‚
β”‚             β”‚    β”‚  β”‚  { type:node_completeβ”‚     channel             β”‚
β”‚             β”‚    β”‚  β”‚    status, cost,    β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚    notes }          β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚         β”‚           β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚  Apply context      β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚  updates            β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚         β”‚           β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚  Select next edge   β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β”‚  (or terminal)      β”‚           β”‚              β”‚
β”‚             β”‚    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚              β”‚
β”‚             β”‚    β”‚            β”‚                       β”‚              β”‚
β”‚             β”‚    β”‚            β–Ό                       β”‚              β”‚
β”‚             β”‚    β”‚  publish_event ────────────► SSE broadcast       β”‚
β”‚             β”‚    β”‚  { type:pipeline_complete,   channel              β”‚
β”‚             β”‚    β”‚    total_cost,                                    β”‚
β”‚             β”‚    β”‚    completed_nodes }                              β”‚
β”‚             β”‚    β”‚            β”‚                       β”‚              β”‚
β”‚             β”‚    β”‚  clear_session_state()             β”‚              β”‚
β”‚             β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β”‚                                                                     β”‚
β”‚  SSE Endpoint: GET /api/stream/{session_id}                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                           β”‚
β”‚  β”‚ stream_events()                       β”‚                          β”‚
β”‚  β”‚  - Replays buffered events on         β”‚                          β”‚
β”‚  β”‚    reconnect (state_sync)             β”‚                          β”‚
β”‚  β”‚  - Forwards broadcast β†’ SSE           β”‚                          β”‚
β”‚  β”‚  - KeepAlive pings                    β”‚                          β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                           β”‚
β”‚                     β”‚                                               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚ SSE stream
                      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  BROWSER (WASM) β€” after server fn returns                           β”‚
β”‚                                                                     β”‚
β”‚  ApprovalBar.Effect                                                 β”‚
β”‚    on_approve(session_id) ──► switches view to ExecutionPanel       β”‚
β”‚                                                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                           β”‚
β”‚  β”‚ ExecutionPanel                        β”‚                          β”‚
β”‚  β”‚                                       β”‚                          β”‚
β”‚  β”‚  Connects to /api/stream/{session_id} β”‚                          β”‚
β”‚  β”‚  via EventSource (SSE)                β”‚                          β”‚
β”‚  β”‚         β”‚                             β”‚                          β”‚
β”‚  β”‚         β–Ό                             β”‚                          β”‚
β”‚  β”‚  process_event() for each SSE msg:    β”‚                          β”‚
β”‚  β”‚                                       β”‚                          β”‚
β”‚  β”‚  "node_start"                         β”‚                          β”‚
β”‚  β”‚    β†’ add node to list (InProgress)    β”‚                          β”‚
β”‚  β”‚                                       β”‚                          β”‚
β”‚  β”‚  "node_complete"                      β”‚                          β”‚
β”‚  β”‚    β†’ update node status               β”‚                          β”‚
β”‚  β”‚      (Success/Failed/Skipped)         β”‚                          β”‚
β”‚  β”‚    β†’ update cost display              β”‚                          β”‚
β”‚  β”‚                                       β”‚                          β”‚
β”‚  β”‚  "pipeline_complete"                  β”‚                          β”‚
β”‚  β”‚    β†’ set is_running = false           β”‚                          β”‚
β”‚  β”‚    β†’ show "Done" badge                β”‚                          β”‚
β”‚  β”‚                                       β”‚                          β”‚
β”‚  β”‚  "error"                              β”‚                          β”‚
β”‚  β”‚    β†’ show error message               β”‚                          β”‚
β”‚  β”‚    β†’ set is_running = false           β”‚                          β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                           β”‚
β”‚                                                                     β”‚
β”‚  Renders: ExecutionNode components                                  β”‚
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”                                β”‚
β”‚  β”‚ Node 1 β”‚ β”‚ Node 2 β”‚ β”‚ Node 3 β”‚ ...                            β”‚
β”‚  β”‚ βœ“ Done β”‚ β”‚ ⟳ Run  β”‚ β”‚ Β· Wait β”‚                                β”‚
β”‚  β”‚ $0.02  β”‚ β”‚        β”‚ β”‚        β”‚                                 β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Sequence Summary

  1. Click β†’ ApprovalBar dispatches Leptos server fn start_execution()
  2. Server verifies .pas/spec.md exists
  3. Decompose β†’ $ pas decompose .pas/spec.md β†’ parses epic ID
  4. Scaffold β†’ $ pas scaffold <epic-id> β†’ generates pipeline .dot file
  5. Parse β†’ reads .dot file, builds PipelineGraph
  6. Spawn β†’ background tokio task runs run_pipeline_with_streaming()
  7. Return β†’ ExecutionResponse { session_id, epic_id, pipeline_path }
  8. Browser receives response, switches to ExecutionPanel, opens SSE to /api/stream/{session_id}
  9. Pipeline loop β†’ for each graph node: resolve handler β†’ execute β†’ publish node_start/node_complete via broadcast channel β†’ select next edge
  10. SSE relay β†’ stream_events() bridges broadcast channel to SSE, with reconnect replay
  11. Complete β†’ publishes pipeline_complete, clears session state