From 9a636af9090b122db2e55737fca3e78550aab9df Mon Sep 17 00:00:00 2001 From: bndw Date: Sat, 28 Feb 2026 19:14:01 -0800 Subject: fix: scope artifacts to sessions --- research.md | 414 ------------------------------------------------------------ 1 file changed, 414 deletions(-) delete mode 100644 research.md (limited to 'research.md') diff --git a/research.md b/research.md deleted file mode 100644 index b7d0897..0000000 --- a/research.md +++ /dev/null @@ -1,414 +0,0 @@ -# Research: Claude Flow Architecture - -## Existing Codebase Analysis - -### Template Structure - -The starting point is a minimal Electron + Vite + React + better-sqlite3 template: - -``` -minimal-electron-vite-react-better-sqlite/ -├── src/main/ -│ ├── index.ts # Electron main process -│ └── preload.ts # IPC bridge (empty) -├── renderer/ -│ ├── index.html # Entry HTML -│ └── src/ -│ └── main.tsx # React entry ("hi") -├── package.json -├── tsconfig.json -└── vite.config.ts -``` - -### Key Patterns in Template - -**Main Process (`src/main/index.ts`):** -- Uses `app.isPackaged` for dev/prod detection -- Database stored in `app.getPath('userData')` — correct for Electron apps -- Uses WAL mode for SQLite (`journal_mode = WAL`) -- Window created with `contextIsolation: true`, `nodeIntegration: false` — secure defaults -- Preload script path: `path.join(__dirname, 'preload.js')` - -**Vite Config:** -- Root is `renderer/` directory -- Base is `./` for file:// loads in production -- Dev server on port 5173 with `strictPort: true` -- Output to `renderer/dist` - -**Build/Dev Scripts:** -- `npm run dev` — concurrent Vite + TypeScript watch + Electron -- Uses `wait-on tcp:5173` to wait for Vite before launching Electron -- `@electron/rebuild` handles native module rebuilding - -### What's Missing (We Need to Build) - -1. IPC handlers for renderer → main communication -2. Proper database layer with migrations -3. React components and state management -4. Claude integration -5. Workflow state machine - ---- - -## Claude Agent SDK Research - -### Package Information - -The SDK has been renamed from "Claude Code SDK" to "Claude Agent SDK". - -**NPM Package:** `@anthropic-ai/claude-agent-sdk` - -**Installation:** -```bash -npm install @anthropic-ai/claude-agent-sdk -``` - -**Authentication:** -- Set `ANTHROPIC_API_KEY` environment variable -- Also supports Bedrock, Vertex AI, Azure via environment flags - -### Core API: `query()` - -The primary function returns an async generator that streams messages: - -```typescript -import { query } from "@anthropic-ai/claude-agent-sdk"; - -for await (const message of query({ - prompt: "Find and fix the bug in auth.py", - options: { - allowedTools: ["Read", "Edit", "Bash"], - permissionMode: "acceptEdits", - cwd: "/path/to/project" - } -})) { - console.log(message); -} -``` - -### Built-in Tools - -| Tool | Purpose | -|------|---------| -| **Read** | Read files (text, images, PDFs, notebooks) | -| **Write** | Create/overwrite files | -| **Edit** | Precise string replacements | -| **Bash** | Run terminal commands | -| **Glob** | Find files by pattern | -| **Grep** | Search file contents with regex | -| **WebSearch** | Search the web | -| **WebFetch** | Fetch/parse web pages | -| **Task** | Spawn subagents | - -### Permission Modes - -| Mode | Behavior | -|------|----------| -| `default` | Standard permissions, may prompt | -| `acceptEdits` | Auto-approve file edits | -| `bypassPermissions` | Allow everything (dangerous) | -| `plan` | Planning only, no execution | - -**Critical for our workflow:** -- **Research/Plan/Annotate phases**: Use `plan` mode or restrict `allowedTools` to read-only -- **Implement phase**: Use `acceptEdits` or `bypassPermissions` // REVIEW: make a user toggle - -### System Prompts - -Can be customized via options: - -```typescript -options: { - systemPrompt: "You are in RESEARCH mode. Read files deeply, write findings to research.md. DO NOT modify any source files.", - // OR use preset with append: - systemPrompt: { - type: "preset", - preset: "claude_code", - append: "Additional instructions here..." - } -} -``` - -### Session Management - -Sessions can be resumed using session IDs: - -```typescript -// First query captures session ID -let sessionId: string; -for await (const message of query({ prompt: "Read auth module" })) { - if (message.type === "system" && message.subtype === "init") { - sessionId = message.session_id; - } -} - -// Resume later with full context -for await (const message of query({ - prompt: "Now find all places that call it", - options: { resume: sessionId } -})) { - // Claude remembers the previous conversation -} -``` - -**Key insight:** Sessions persist to disk by default. We can store the session ID in SQLite and resume later. - -### Hooks - -Hooks intercept agent behavior at key points: - -```typescript -import { query, HookCallback, PreToolUseHookInput } from "@anthropic-ai/claude-agent-sdk"; - -const blockWrites: HookCallback = async (input, toolUseID, { signal }) => { - const preInput = input as PreToolUseHookInput; - if (["Write", "Edit"].includes(preInput.tool_name)) { - return { - hookSpecificOutput: { - hookEventName: "PreToolUse", - permissionDecision: "deny", - permissionDecisionReason: "In planning mode - no code changes allowed" - } - }; - } - return {}; -}; - -for await (const message of query({ - prompt: "...", - options: { - hooks: { - PreToolUse: [{ matcher: "Write|Edit", hooks: [blockWrites] }] - } - } -})) { ... } -``` - -**Available hook events:** -- `PreToolUse` — Before tool executes (can block/modify) -- `PostToolUse` — After tool executes (can log/transform) -- `Stop` — Agent execution ending -- `SessionStart` / `SessionEnd` — Session lifecycle -- `SubagentStart` / `SubagentStop` — Subagent lifecycle - -### Message Types - -The query yields different message types: - -```typescript -type SDKMessage = - | SDKAssistantMessage // Claude's response (includes tool_use) - | SDKUserMessage // User input - | SDKResultMessage // Final result with usage stats - | SDKSystemMessage // Init message with session_id, tools, etc. - | SDKPartialMessage // Streaming chunks (if enabled) - | SDKStatusMessage // Status updates - | ... -``` - -**SDKResultMessage** contains: -- `result` — Final text output -- `total_cost_usd` — API cost -- `usage` — Token counts -- `duration_ms` — Total time -- `num_turns` — Conversation turns - -### Query Object Methods - -The query object has methods for control: - -```typescript -const q = query({ prompt: "...", options: { ... } }); - -// Change settings mid-session -await q.setPermissionMode("acceptEdits"); -await q.setModel("opus"); - -// Get session info -const init = await q.initializationResult(); -const commands = await q.supportedCommands(); -const models = await q.supportedModels(); - -// Interrupt/cancel -await q.interrupt(); -q.close(); -``` - ---- - -## Architecture Decisions - -### Phase Enforcement Strategy - -We have two complementary approaches: - -**1. Permission Mode + Allowed Tools:** -```typescript -const phaseConfig = { - research: { - permissionMode: "plan", - allowedTools: ["Read", "Glob", "Grep", "WebSearch", "WebFetch"], - systemPrompt: "You are in RESEARCH mode..." - }, - plan: { - permissionMode: "plan", - allowedTools: ["Read", "Glob", "Grep", "Write"], // Write only for plan.md - systemPrompt: "You are in PLANNING mode..." - }, - annotate: { - permissionMode: "plan", - allowedTools: ["Read", "Write"], // Only update plan.md - systemPrompt: "You are in ANNOTATION mode..." - }, - implement: { - permissionMode: "acceptEdits", - allowedTools: ["Read", "Write", "Edit", "Bash", "Glob", "Grep"], - systemPrompt: "You are in IMPLEMENTATION mode..." - } -}; -``` - -**2. Hooks for Fine-Grained Control:** -```typescript -const enforcePhaseHook: HookCallback = async (input, toolUseID, { signal }) => { - const { tool_name, tool_input } = input as PreToolUseHookInput; - const phase = getCurrentPhase(); // From app state - - if (phase !== "implement" && ["Write", "Edit"].includes(tool_name)) { - const filePath = (tool_input as any).file_path; - // Allow only plan.md/research.md in non-implement phases - if (!filePath.endsWith("plan.md") && !filePath.endsWith("research.md")) { - return { - hookSpecificOutput: { - hookEventName: "PreToolUse", - permissionDecision: "deny", - permissionDecisionReason: `Cannot modify ${filePath} in ${phase} phase` - } - }; - } - } - return {}; -}; -``` - -### Session Persistence - -**Option A: Use SDK's built-in session persistence** -- Sessions saved to disk automatically -- Store session ID in SQLite -- Resume with `options: { resume: sessionId }` -- Pro: Simpler, full context preserved -- Con: Less control over what's stored - -**Option B: Store messages in SQLite ourselves** -- Store each message in our database -- Reconstruct context when resuming -- Pro: Full control, searchable history -- Con: More complex, may lose SDK internal state - -**Recommendation:** Use **Option A** (SDK persistence) with session ID in SQLite. We can still store messages for display/search, but rely on SDK for actual context. -// REVIEW: option a - -### Artifact Management - -The blog workflow uses `research.md` and `plan.md` as persistent artifacts. - -**Options:** -1. **Store in SQLite** — Searchable, version history, but not editable externally -2. **Store as files in project** — Visible in git, editable in any editor -3. **Both** — Files as source of truth, sync to SQLite for search - -**Recommendation:** Store as **files in the project directory** (e.g., `.claude-flow/research.md`, `.claude-flow/plan.md`). This matches the blog workflow where the human edits the plan.md directly. -// REVIEW: recommendation is great - -### IPC Architecture - -Electron requires IPC for renderer ↔ main communication: - -```typescript -// preload.ts -import { contextBridge, ipcRenderer } from "electron"; - -contextBridge.exposeInMainWorld("api", { - // Projects - listProjects: () => ipcRenderer.invoke("projects:list"), - createProject: (data) => ipcRenderer.invoke("projects:create", data), - - // Sessions - listSessions: (projectId) => ipcRenderer.invoke("sessions:list", projectId), - createSession: (data) => ipcRenderer.invoke("sessions:create", data), - - // Claude - sendMessage: (sessionId, message) => ipcRenderer.invoke("claude:send", sessionId, message), - onMessage: (callback) => ipcRenderer.on("claude:message", callback), - setPhase: (sessionId, phase) => ipcRenderer.invoke("claude:setPhase", sessionId, phase), -}); -``` - ---- - -## Open Questions Resolved - -### 1. Claude Code SDK vs CLI - -**Answer:** Use the SDK (`@anthropic-ai/claude-agent-sdk`). It provides: -- Programmatic control via TypeScript -- Hooks for intercepting behavior -- Session management -- Streaming messages - -### 2. Artifact Storage - -**Answer:** Store as files in project directory (`.claude-flow/`) for: -- Editability in any editor (VSCode, etc.) -- Git visibility -- Matches the blog workflow - -### 3. Session Context / Compaction - -**Answer:** Use SDK's built-in session persistence: -- Store session ID in SQLite -- Resume with `options: { resume: sessionId }` -- SDK handles context compaction automatically - -### 4. Multi-file Editing - -**Answer:** The SDK handles this natively via the Edit/Write tools. The plan.md should list all files to be modified, and Claude executes them in order during implementation. - ---- - -## Dependencies to Add - -```json -{ - "dependencies": { - "@anthropic-ai/claude-agent-sdk": "latest", - "better-sqlite3": "12.2.0", - "react": "^19.1.1", - "react-dom": "^19.1.1", - "uuid": "^11.0.0" - }, - "devDependencies": { - "@types/uuid": "^10.0.0" - // ... existing devDeps - } -} -``` - ---- - -## Summary - -The Claude Agent SDK is well-suited for building Claude Flow: - -1. **Session management** — Built-in persistence, resume capability -2. **Permission modes** — `plan` mode prevents execution, `acceptEdits` for implementation -3. **Hooks** — Fine-grained control over what Claude can do -4. **Streaming** — Real-time message display in UI -5. **System prompts** — Customizable per phase - -The main work is: -- Building the Electron app shell (IPC, windows) -- SQLite layer for projects/sessions -- React UI for chat, artifacts, phase controls -- Wiring everything together with the SDK -- cgit v1.2.3