PAS Web Interface β Implementation Plan
Context
PAS (Pascal's Discrete Attractor) is a DOT-based pipeline runner for AI workflows. You're building a parallel workflow on another branch that generates PRDs and spec files, decomposes them into beads, and creates .dot pipeline files. This web interface provides a visual layer for that planning process β a place to prompt, review, iterate on PRD/spec documents, and then kick off pipeline execution with live streaming progress.
The repo is a git worktree of the main PAS project on feature/interface-web.
Architecture
Leptos fullstack app β single Rust crate that compiles to both server (Axum) and client (WASM). Uses cargo-leptos as the build tool.
New Crate: attractor-web
crates/attractor-web/
βββ Cargo.toml
βββ src/
β βββ lib.rs # App definition, hydrate entry
β βββ main.rs # Server binary (Axum)
β βββ app.rs # Router: /, /editor, /execute
β βββ state.rs # AppState (sessions, broadcast channels)
β βββ pages/
β β βββ mod.rs
β β βββ prompt.rs # Chat input β LLM generates PRD/spec
β β βββ editor.rs # Two-pane markdown editor (PRD | Spec)
β β βββ execution.rs # Pipeline execution with live streaming
β βββ components/
β β βββ mod.rs
β β βββ chat_input.rs # Multi-line prompt input
β β βββ markdown_pane.rs # Textarea + live preview
β β βββ node_status.rs # Pipeline node progress indicator
β βββ server/
β βββ mod.rs
β βββ generate.rs # Server fn: prompt β PRD + spec via claude CLI
β βββ execute.rs # Server fn: start pipeline, return session_id
β βββ stream.rs # SSE endpoint: bridge PipelineEvents to browser
β βββ session.rs # Session tracking, checkpoint/resume
βββ style/
β βββ main.scss
βββ public/
Data Flow
1. User types prompt at /
2. Server calls: claude -p "<system+user prompt>" --output-format stream-json
β Streams partial content back to browser via server fn
β Accumulates final result, splits into PRD + Spec sections
3. Navigate to /editor with PRD (left pane) and Spec (right pane)
4. User edits both documents freely, iterates
5. User clicks "Execute" β server fn:
- Generates session_id (UUID v4)
- Writes PRD + Spec to workdir/.pas/
- Spawns pipeline via PipelineExecutor with EventEmitter
- Returns session_id
6. Browser opens EventSource to /api/stream/{session_id}
β EventEmitter.subscribe() β SSE events to browser
β ExecutionPage shows node progress, streaming output, cost
Streaming: Two Layers
Layer 1: Claude CLI β Server (for PRD/spec generation)
claude -p "..." --output-format stream-json --include-partial-messages- Read stdout line-by-line as NDJSON
- Each line has
typefield:system,assistant(text deltas),result - Stream text deltas to browser as they arrive
Layer 2: Pipeline Events β Browser (for execution)
- The existing
EventEmitter(broadcast channel) inevents.rsalready emitsPipelineEventvariants:StageStarted,StageCompleted,EdgeSelected, etc. - SSE endpoint subscribes to the emitter and forwards events as JSON
- Browser
EventSourcereceives and renders them
Modifications to Existing Crates
attractor-pipeline/src/handlers/mod.rs β CodergenHandler changes:
- Add
CodergenConfigto support--output-format stream-json+--session-id - When
stream-jsonmode: read stdout line-by-line, parse NDJSON, forward content deltas to an optionalbroadcast::Sender, accumulate finalresultfor Outcome - When
jsonmode (default): unchanged behavior, backward compatible - Add
--session-id <uuid>flag instead of--no-session-persistencewhen a session_id is provided
attractor-pipeline/src/checkpoint.rs β Add session_id: Option<String> to PipelineCheckpoint for resume across checkpoint/restore cycles.
attractor-pipeline/src/engine.rs β Accept optional EventEmitter in PipelineExecutor (may already be wired; the web crate will construct one and subscribe).
Key Dependencies
leptos = "0.7"
leptos_axum = "0.7"
leptos_router = "0.7"
leptos_meta = "0.7"
axum = "0.8"
pulldown-cmark = "0.12" # Markdown rendering (compiles to WASM)
tokio-stream = "0.1" # BroadcastStream for SSE
# Plus workspace deps: tokio, serde, serde_json, uuid, tracing
# Plus internal: attractor-types, attractor-pipeline, attractor-dot (server-only)
Session ID & Checkpoint/Resume
start_pipeline()generates a UUID v4 session_id- Stored in
AppState.sessions: HashMap<String, SessionState> SessionStateholds: session_id, EventEmitter, pipeline status, checkpoint path- CodergenHandler passes
--session-id <uuid>to claude CLI (instead of--no-session-persistence) - If browser disconnects and reconnects to
/api/stream/{session_id}, it re-subscribes to the existing broadcast channel - If the server restarts,
load_checkpoint()restores state and the same session_id resumes the claude conversation
Implementation Phases
Phase 1: Scaffold (get pixels on screen)
- Add
crates/attractor-webto workspace - Set up Leptos + Axum with
cargo-leptos - Three routes with placeholder content:
/,/editor,/execute ChatInputcomponent on/- Two side-by-side
MarkdownPanecomponents on/editor(hardcoded content) - Verify
cargo leptos watchworks
Phase 2: PRD/Spec Generation
generate_prd_specserver function inserver/generate.rs- Shell out to
claude -pwith a system prompt that produces structured PRD + Spec - Start with
--output-format json(simpler; streaming comes in Phase 3) - Wire prompt page β server fn β navigate to editor with results
Phase 3: Streaming Infrastructure
- Modify
CodergenHandlerwithCodergenConfigforstream-jsonsupport - Add
session_idtoPipelineCheckpoint - SSE endpoint at
/api/stream/{session_id} - Upgrade PRD generation to use
stream-jsonfor live typing effect
Phase 4: Pipeline Execution
start_pipelineserver function- Wire "Execute" button β start pipeline β open SSE stream
ExecutionPagerenders node progress, content, cost in real time
Phase 5: Resume & Polish
- Session resume on browser reconnect
- Checkpoint-based resume on server restart
- Styling, loading states, error handling
Verification
cargo leptos watchβ app builds and renders at localhost:3000- Type a prompt β PRD + Spec appear in two-pane editor
- Edit both documents, click Execute
- Execution page shows live node progress via SSE
- Disconnect browser, reconnect β stream resumes
cargo test --workspaceβ all existing tests still pass