Skip to content

Proposal: Synthesize Mode

Status: Implemented (local-first v1) · Last updated: 2026-07-13

Summary

An IDE-like workspace for turning sources into documents: collapsible sidebar of projects/files/sources, resizable tabbed panes holding chat threads, markdown editors, and source viewers side by side. The UI is SvelteReader's WorkspaceLayout; the data model and agent are socratic-seminar's.

Motivation

Synthesize is where the other modes converge: sources from Search, annotations from Read, and (structurally) the same workspace Debate needs. SvelteReader's synthesize mode is the strongest layout reference in the reference set; socratic-seminar already implements the matching data model (projects → threads + versioned artifacts + sources) and the agent that edits files through approval-gated tools.

Design

  • Layout: port SvelteReader's WorkspaceLayout.svelte pattern — left sidebar (drag-resize 180–400px, collapsible) + two tabbed columns with draggable divider; tabs render chat / editor / source viewer via snippets.
  • Data model (socratic-seminar db/types.ts, one IndexedDB per npub): Project, Thread (+ verbatim pi TranscriptRecord), Artifact + ArtifactVersion (versioned markdown snapshots), Source/Bibliography, WorkspaceState/LayoutState.
  • Editor: CodeMirror 6 with Obsidian-style live preview (socratic-seminar's codemirror/livePreview.ts); [[Title]] wiki-links between artifacts and sources.
  • Agent: pi runner with the file tools (read_file/patch_file with approval gate), sources, todos, clarify — socratic-seminar's agent/ directory nearly verbatim. Reads see live editor content.
  • Nostr sync: deferred to a shared decision with Debate mode (same entities). Local-first ships first; relays-as-filesystem follows the event-kind design in the Debate proposal.

Reference material

  • SvelteReader frontend/src/lib/components/synthesize/WorkspaceLayout, TabbedPanel, SynthSidebar, ProjectDashboard
  • socratic-seminar src/lib/db/, src/lib/agent/, src/lib/codemirror/, src/lib/components/{Editor,ChatPanel,ToolCallDisplay}.svelte

Decisions (2026-07-13)

  • Shared workspace core now: the workspace (layout, db entities, editor, agent wiring) is built mode-agnostic in $lib/workspace/; Synthesize is its first consumer, Debate later = the same core + the seminar template/persona. Synthesize-only bits (persona, dashboard copy) stay under $lib/synthesize/ or the route.
  • Full mode, built in phases (see plan below), committed to master phase by phase.
  • Mobile: below a breakpoint the sidebar becomes an overlay drawer and the two tabbed columns collapse to one pane. No separate mobile design.
  • Embeddings deferred: plain title/text search over sources; no in-browser transformer models in the bundle. The agent reads source content directly.
  • Data model: socratic-seminar's shapes verbatim (they are SvelteReader's types with the LangGraph fields already stripped): Project, Thread + TranscriptRecord (verbatim pi AgentMessage[]), Artifact with embedded ArtifactVersion[], Source (+ deferred file fields), WorkspaceState per project / LayoutState per npub. New stores land in the existing per-npub plebchat::<npub> DB via a version bump — no second database.

Phase plan

  1. Data model + dashboard$lib/workspace/ types + db stores (DB v3), projects store, /synthesize project dashboard (create/rename/tag/delete), /synthesize/[id] shell.
  2. WorkspaceLayout port — sidebar (files/sources/threads, drag-resize 180–400px, collapsible) + two tabbed columns with draggable divider, snippet-rendered tabs, persisted WorkspaceState/LayoutState; mobile single-pane + drawer.
  3. Editor + versioning — CodeMirror 6 markdown with live preview (socratic-seminar codemirror/livePreview.ts), [[Title]] links, version snapshots + history, read-only source viewer.
  4. Agent$lib/ai runner + workspace tools (list_files/read_file auto-approved, patch_file/write_file approval-gated), sources tools, chat panel with tool cards; reads see live editor content.
  5. e2e + docs — Playwright (mocked SSE endpoint like e2e/search.test.ts): project CRUD, artifact editing + versions, agent patch approval. MkDocs page.

Open questions

  • Nostr sync (unchanged): deferred to the shared event-kind decision with Debate mode; local-first ships first.
  • Sources from Search mode: importing a Search thread's sources into a project is a natural follow-up once both exist; not in this build-out.

Progress

  • Shared workspace core decision (with Debate) — yes, $lib/workspace/
  • Phase 1: IndexedDB schema (DB v3) + projects store + dashboard + ?project= deep links
  • Phase 2: WorkspaceLayout port (sidebar + tabbed panes, drag-to-split, persisted layout, mobile drawer). Interim panes: textarea file editor (CodeMirror is Phase 3), placeholder chat (agent is Phase 4), manual add-source modal. Dropped from the SvelteReader sidebar for now: file tags, thread status filters.
  • Phase 3: CodeMirror editor with live preview + [[links]] + versions. Live-content store layer (dirty tracking, debounced flush; versions only by explicit snapshot), version toolbar (prev/next/snapshot), theme-aware livePreview recolored to semantic tokens, Cmd/Ctrl+click wiki-links open-or-create artifacts.
  • Phase 4: Agent integration. $lib/ai runner gained the mode-agnostic approval seam (approvalRequired + pendingApproval/respond) and async transcript hydration; workspace tools = list/read/grep/glob/write/patch files (patch approval-gated, reads see live editor content) + list/read sources; per-thread runners persist verbatim transcripts to the transcripts store and auto-title threads. ChatPanel shows tool cards, a search/replace approval banner with rejection feedback, and reuses the shared AI settings dialog. Deferred from socratic-seminar: ask_user/choices clarify tools, todos, think.
  • Phase 5: Playwright e2e (built alongside each phase: project lifecycle, tabs/persistence, versions, wiki-links, patch approve/reject, unconfigured gate — 8 tests) + LIVE=1 smoke (real endpoint: patch proposal → approval → edited file, verified green 2026-07-13) + docs/synthesize.md user guide.
  • Type-homed columns (2026-07-16, superseding SvelteReader's free-form two-column model): files and sources live in the LEFT column, chat threads in the RIGHT — strict, no cross-column tab dragging (the Split-Right drop affordance and the open/close-panel buttons are gone). The right pane exists exactly while chat tabs exist; opening a chat always splits, closing the last chat tab returns the editor to full width. Saved arrangements re-partition on load (rehome), and crossing the phone breakpoint folds everything into the single column and back. "New chat" reuses an existing empty thread, and closing a never-used chat's tab deletes it (removeIfEmpty) — no orphaned empties. The per-pane "+" menus keep the same items everywhere; everything (menus, ⌘K, sidebar, agent write/approval reveals) routes by type home.
  • View context for the agent (2026-07-16): the system prompt (rebuilt each send) gains a "What the user is looking at" section — open file/source tabs with the active file marked, plus the text currently highlighted in an editor or source viewer (runtime-only wsContext store; CodeMirror selections survive composer focus, source-viewer selections are captured on pointer release; 2k-char cap). Default split moved to 2/3 document / 1/3 chat.
  • Reference-parity pass (2026-07-16, from the SvelteReader feature audit): New File modal (filename + template grid from $lib/workspace/templates.ts + drag-drop import of text files — the templates seam is also Debate's Socratic Seminar seeding path); URL-fetching sources (AddSourceModal "From the web" mode: multi-URL, Firecrawl reader markdown, per-URL status; manual paste stays the no-key path); unread dots (viewed flag on artifacts/sources — set false on create and on agent patch_file to a non-visible file, cleared by a WorkspaceView effect when the item is the active tab); richer tab "+" menu (New file / New chat / Add source / Open…) and a real ⌘K QuickOpen palette searching files/chats/sources (SvelteReader only rendered the ⌘K hint). Modals are owned by WorkspaceView and column-targeted. Still deferred: ask_user/choices clarify tools, image artifacts/file-type icons, source web search.

Follow-ups (post-v1)

  • Nostr sync (shared event-kind decision with Debate).
  • Import a Search thread's sources into a project; ~~agent-driven source scraping (Firecrawl)~~ — user-driven URL fetching landed 2026-07-16 (AddSourceModal); an agent-callable scrape tool remains open.
  • ~~Sidebar file tags + thread status filters~~ — done 2026-07-14, see workspace-thread-status-and-file-tags.md.
  • Clarify/todos/think tools from socratic-seminar; Debate mode = this core + seminar persona.