diff options
| author | bndw <ben@bdw.to> | 2026-03-04 21:36:32 -0800 |
|---|---|---|
| committer | bndw <ben@bdw.to> | 2026-03-04 21:36:32 -0800 |
| commit | 73d2680b83ccbdbd8dfec2d319533e98b379b830 (patch) | |
| tree | 193eaf5157edcf12d06dde85fb44efaf3aae2004 /src/main | |
| parent | b6405dd6a4ba65fc5dc6746db7be7be7d0bb29f3 (diff) | |
feat: Thread optional `phase` param into `db/sessions.ts::cre… (+7 more)
- ✅ Thread optional `phase` param into `db/sessions.ts::createSession()`
- ✅ Thread optional `phase` param into `ipc/handlers.ts` sessions:create handler
- ✅ Thread optional `phase` param into `preload.ts` createSession API
- ✅ Update Plan phase system prompt to gracefully handle missing research.md
- ✅ Update Implement phase system prompt to gracefully handle missing plan.md
- ✅ Create `renderer/src/components/NewSessionModal.tsx`
- ✅ Update `App.tsx`: add modal state, split handler, add modal JSX
- ✅ Add modal CSS to `globals.css`
Diffstat (limited to 'src/main')
| -rw-r--r-- | src/main/claude/index.ts | 5 | ||||
| -rw-r--r-- | src/main/claude/phases.ts | 10 | ||||
| -rw-r--r-- | src/main/db/sessions.ts | 8 | ||||
| -rw-r--r-- | src/main/ipc/handlers.ts | 6 | ||||
| -rw-r--r-- | src/main/preload.ts | 6 |
5 files changed, 19 insertions, 16 deletions
diff --git a/src/main/claude/index.ts b/src/main/claude/index.ts index 8cf512c..9139f17 100644 --- a/src/main/claude/index.ts +++ b/src/main/claude/index.ts | |||
| @@ -48,8 +48,9 @@ export async function sendMessage({ | |||
| 48 | // Load any custom system prompt for this phase (null → use default) | 48 | // Load any custom system prompt for this phase (null → use default) |
| 49 | const customSystemPrompt = getSetting(`systemPrompt.${session.phase}`) ?? undefined; | 49 | const customSystemPrompt = getSetting(`systemPrompt.${session.phase}`) ?? undefined; |
| 50 | 50 | ||
| 51 | // Load global model override (empty string or null → let SDK use its default) | 51 | // Phase-specific model override takes precedence; falls back to global default. |
| 52 | const configuredModel = getSetting("model") || undefined; | 52 | const configuredModel = |
| 53 | getSetting(`model.${session.phase}`) || getSetting("model") || undefined; | ||
| 53 | 54 | ||
| 54 | // Load MCP servers config (JSON string → object, or undefined if not set) | 55 | // Load MCP servers config (JSON string → object, or undefined if not set) |
| 55 | const mcpServersJson = getSetting("mcpServers"); | 56 | const mcpServersJson = getSetting("mcpServers"); |
diff --git a/src/main/claude/phases.ts b/src/main/claude/phases.ts index a1cbba1..e8c16df 100644 --- a/src/main/claude/phases.ts +++ b/src/main/claude/phases.ts | |||
| @@ -87,11 +87,12 @@ CRITICAL RULES: | |||
| 87 | 87 | ||
| 88 | CONTEXT: | 88 | CONTEXT: |
| 89 | - Read CLAUDE.md at project root for codebase overview | 89 | - Read CLAUDE.md at project root for codebase overview |
| 90 | - Read ${artifactDir}/research.md to understand the specific task | 90 | - Read ${artifactDir}/research.md to understand the specific task. |
| 91 | If research.md does not exist, this session began at the planning phase — base your plan on the task description provided in the chat instead. | ||
| 91 | 92 | ||
| 92 | WORKFLOW: | 93 | WORKFLOW: |
| 93 | 1. Read CLAUDE.md for codebase overview | 94 | 1. Read CLAUDE.md for codebase overview |
| 94 | 2. Read ${artifactDir}/research.md to understand the specific task | 95 | 2. Read ${artifactDir}/research.md if it exists; otherwise use the task description from chat |
| 95 | 3. Write a detailed plan to ${artifactDir}/plan.md | 96 | 3. Write a detailed plan to ${artifactDir}/plan.md |
| 96 | 4. Include specific code snippets showing proposed changes | 97 | 4. Include specific code snippets showing proposed changes |
| 97 | 5. Make the plan detailed enough that implementation is mechanical | 98 | 5. Make the plan detailed enough that implementation is mechanical |
| @@ -141,14 +142,15 @@ Remember: Your output goes in ${artifactDir}/plan.md, not chat. Chat is for clar | |||
| 141 | systemPrompt: (artifactDir) => `You are in IMPLEMENTATION mode. Execute the approved plan. | 142 | systemPrompt: (artifactDir) => `You are in IMPLEMENTATION mode. Execute the approved plan. |
| 142 | 143 | ||
| 143 | CRITICAL RULES: | 144 | CRITICAL RULES: |
| 144 | 1. Read ${artifactDir}/plan.md and follow it exactly | 145 | 1. Read ${artifactDir}/plan.md if it exists and follow it exactly. |
| 146 | If plan.md does not exist, this session began at the implementation phase — implement based on the task description provided in the chat messages. | ||
| 145 | 2. Mark tasks complete in ${artifactDir}/plan.md as you finish them: - [ ] → - [x] | 147 | 2. Mark tasks complete in ${artifactDir}/plan.md as you finish them: - [ ] → - [x] |
| 146 | 3. DO NOT deviate from the plan without asking | 148 | 3. DO NOT deviate from the plan without asking |
| 147 | 4. Run tests/typecheck if available | 149 | 4. Run tests/typecheck if available |
| 148 | 5. Stop and ask if you encounter issues not covered by the plan | 150 | 5. Stop and ask if you encounter issues not covered by the plan |
| 149 | 151 | ||
| 150 | WORKFLOW: | 152 | WORKFLOW: |
| 151 | 1. Read ${artifactDir}/plan.md | 153 | 1. Read ${artifactDir}/plan.md (if it exists) |
| 152 | 2. Execute each task in order | 154 | 2. Execute each task in order |
| 153 | 3. Update ${artifactDir}/plan.md to mark tasks complete | 155 | 3. Update ${artifactDir}/plan.md to mark tasks complete |
| 154 | 4. Continue until all tasks are done | 156 | 4. Continue until all tasks are done |
diff --git a/src/main/db/sessions.ts b/src/main/db/sessions.ts index 3e6352c..bc22d15 100644 --- a/src/main/db/sessions.ts +++ b/src/main/db/sessions.ts | |||
| @@ -36,21 +36,21 @@ export function getSession(id: string): Session | undefined { | |||
| 36 | .get(id) as Session | undefined; | 36 | .get(id) as Session | undefined; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | export function createSession(projectId: string, name: string): Session { | 39 | export function createSession(projectId: string, name: string, phase: Phase = "research"): Session { |
| 40 | const db = getDb(); | 40 | const db = getDb(); |
| 41 | const id = uuid(); | 41 | const id = uuid(); |
| 42 | const now = Math.floor(Date.now() / 1000); | 42 | const now = Math.floor(Date.now() / 1000); |
| 43 | 43 | ||
| 44 | db.prepare( | 44 | db.prepare( |
| 45 | `INSERT INTO sessions (id, project_id, name, phase, permission_mode, created_at, updated_at) | 45 | `INSERT INTO sessions (id, project_id, name, phase, permission_mode, created_at, updated_at) |
| 46 | VALUES (?, ?, ?, 'research', 'acceptEdits', ?, ?)` | 46 | VALUES (?, ?, ?, ?, 'acceptEdits', ?, ?)` |
| 47 | ).run(id, projectId, name, now, now); | 47 | ).run(id, projectId, name, phase, now, now); |
| 48 | 48 | ||
| 49 | return { | 49 | return { |
| 50 | id, | 50 | id, |
| 51 | project_id: projectId, | 51 | project_id: projectId, |
| 52 | name, | 52 | name, |
| 53 | phase: "research", | 53 | phase, |
| 54 | claude_session_id: null, | 54 | claude_session_id: null, |
| 55 | permission_mode: "acceptEdits", | 55 | permission_mode: "acceptEdits", |
| 56 | git_branch: null, | 56 | git_branch: null, |
diff --git a/src/main/ipc/handlers.ts b/src/main/ipc/handlers.ts index 4894e1d..975ad01 100644 --- a/src/main/ipc/handlers.ts +++ b/src/main/ipc/handlers.ts | |||
| @@ -5,7 +5,7 @@ import * as claude from "../claude"; | |||
| 5 | import * as settingsDb from "../db/settings"; | 5 | import * as settingsDb from "../db/settings"; |
| 6 | import { createSessionBranch, ensureGitIgnore, ensureGitRepo, getCurrentBranch } from "../git"; | 6 | import { createSessionBranch, ensureGitIgnore, ensureGitRepo, getCurrentBranch } from "../git"; |
| 7 | import { discoverMcpTools } from "../mcp"; | 7 | import { discoverMcpTools } from "../mcp"; |
| 8 | import type { UserPermissionMode } from "../claude/phases"; | 8 | import type { UserPermissionMode, Phase } from "../claude/phases"; |
| 9 | import { getDefaultSystemPromptTemplate } from "../claude/phases"; | 9 | import { getDefaultSystemPromptTemplate } from "../claude/phases"; |
| 10 | 10 | ||
| 11 | export function registerIpcHandlers(mainWindow: BrowserWindow): void { | 11 | export function registerIpcHandlers(mainWindow: BrowserWindow): void { |
| @@ -23,11 +23,11 @@ export function registerIpcHandlers(mainWindow: BrowserWindow): void { | |||
| 23 | sessions.listSessions(projectId) | 23 | sessions.listSessions(projectId) |
| 24 | ); | 24 | ); |
| 25 | 25 | ||
| 26 | ipcMain.handle("sessions:create", (_, projectId: string, name: string) => { | 26 | ipcMain.handle("sessions:create", (_, projectId: string, name: string, phase?: Phase) => { |
| 27 | const project = projects.getProject(projectId); | 27 | const project = projects.getProject(projectId); |
| 28 | if (!project) throw new Error("Project not found"); | 28 | if (!project) throw new Error("Project not found"); |
| 29 | 29 | ||
| 30 | const session = sessions.createSession(projectId, name); | 30 | const session = sessions.createSession(projectId, name, phase); |
| 31 | 31 | ||
| 32 | // Ensure .claude-flow/ is gitignored from day one. | 32 | // Ensure .claude-flow/ is gitignored from day one. |
| 33 | // Branch creation is deferred until the session advances to implement. | 33 | // Branch creation is deferred until the session advances to implement. |
diff --git a/src/main/preload.ts b/src/main/preload.ts index e7ee0aa..fbdf871 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts | |||
| @@ -12,7 +12,7 @@ export interface ClaudeFlowAPI { | |||
| 12 | 12 | ||
| 13 | // Sessions | 13 | // Sessions |
| 14 | listSessions: (projectId: string) => Promise<Session[]>; | 14 | listSessions: (projectId: string) => Promise<Session[]>; |
| 15 | createSession: (projectId: string, name: string) => Promise<Session>; | 15 | createSession: (projectId: string, name: string, phase?: Phase) => Promise<Session>; |
| 16 | deleteSession: (id: string) => Promise<void>; | 16 | deleteSession: (id: string) => Promise<void>; |
| 17 | getSession: (id: string) => Promise<Session | undefined>; | 17 | getSession: (id: string) => Promise<Session | undefined>; |
| 18 | renameSession: (id: string, name: string) => Promise<void>; | 18 | renameSession: (id: string, name: string) => Promise<void>; |
| @@ -86,8 +86,8 @@ const api: ClaudeFlowAPI = { | |||
| 86 | 86 | ||
| 87 | // Sessions | 87 | // Sessions |
| 88 | listSessions: (projectId) => ipcRenderer.invoke("sessions:list", projectId), | 88 | listSessions: (projectId) => ipcRenderer.invoke("sessions:list", projectId), |
| 89 | createSession: (projectId, name) => | 89 | createSession: (projectId, name, phase) => |
| 90 | ipcRenderer.invoke("sessions:create", projectId, name), | 90 | ipcRenderer.invoke("sessions:create", projectId, name, phase), |
| 91 | deleteSession: (id) => ipcRenderer.invoke("sessions:delete", id), | 91 | deleteSession: (id) => ipcRenderer.invoke("sessions:delete", id), |
| 92 | getSession: (id) => ipcRenderer.invoke("sessions:get", id), | 92 | getSession: (id) => ipcRenderer.invoke("sessions:get", id), |
| 93 | renameSession: (id, name) => ipcRenderer.invoke("sessions:rename", id, name), | 93 | renameSession: (id, name) => ipcRenderer.invoke("sessions:rename", id, name), |
