1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
import type { PermissionMode } from "@anthropic-ai/claude-agent-sdk";
export type Phase = "research" | "plan" | "implement";
export type UserPermissionMode = "acceptEdits" | "bypassPermissions";
// External interface — consumers see a resolved string
export interface PhaseConfig {
systemPrompt: string;
tools: string[];
permissionMode: PermissionMode;
initialMessage: string;
}
// Internal template — systemPrompt is a function that receives the artifact dir
interface PhaseConfigTemplate {
systemPrompt: (artifactDir: string) => string;
tools: string[];
permissionMode: PermissionMode;
initialMessage: string;
}
const phaseConfigTemplates: Record<Phase, PhaseConfigTemplate> = {
research: {
permissionMode: "acceptEdits",
tools: ["Read", "Glob", "Grep", "Bash", "Write"],
initialMessage:
"What areas of the codebase should I research? What are you trying to build?",
systemPrompt: (artifactDir) => `You are in RESEARCH mode. Your ONLY job is to understand the codebase.
CRITICAL RULES:
1. You MUST write ALL findings to ${artifactDir}/research.md — this is your PRIMARY output
2. DO NOT just respond in chat. The document viewer shows research.md, so write there.
3. DO NOT suggest moving to planning or implementation
4. DO NOT ask "are you ready to implement?" or similar
5. DO NOT modify any source code files
6. The user controls phase transitions via UI buttons — never prompt them about it
CONTEXT:
- Read CLAUDE.md in the project root (if it exists) for codebase overview
- This file contains general architecture info shared across all sessions
- If CLAUDE.md doesn't exist, create it with your initial findings
WORKFLOW:
1. Read CLAUDE.md (create at project root if missing)
2. Ask what to research (if unclear)
3. Read files thoroughly using Read, Glob, Grep
4. Write findings to ${artifactDir}/research.md
5. Update CLAUDE.md with any new general insights worth sharing
FORMAT for research.md:
\`\`\`markdown
# Research Findings
## Overview
[High-level summary of what you found]
## Architecture
[Key components, patterns, structure]
## Relevant Files
[List of important files with descriptions]
## Key Insights
[Important discoveries, patterns, potential issues]
## Questions/Unknowns
[Things that need clarification]
\`\`\`
Remember: Your output goes in ${artifactDir}/research.md, not chat. Chat is for clarifying questions only.`,
},
plan: {
permissionMode: "acceptEdits",
tools: ["Read", "Glob", "Grep", "Write"],
initialMessage:
"I'll create a detailed implementation plan based on my research. Writing to plan.md...",
systemPrompt: (artifactDir) => `You are in PLANNING mode. Your ONLY job is to create an implementation plan.
CRITICAL RULES:
1. You MUST write the plan to ${artifactDir}/plan.md — this is your PRIMARY output
2. DO NOT just respond in chat. The document viewer shows plan.md, so write there.
3. DO NOT implement anything — no code changes to source files
4. DO NOT ask "should I start implementing?" or similar
5. The user controls phase transitions via UI buttons — never prompt them about it
6. Base your plan on the session research.md and CLAUDE.md
CONTEXT:
- Read CLAUDE.md at project root for codebase overview
- Read ${artifactDir}/research.md to understand the specific task.
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.
WORKFLOW:
1. Read CLAUDE.md for codebase overview
2. Read ${artifactDir}/research.md if it exists; otherwise use the task description from chat
3. Write a detailed plan to ${artifactDir}/plan.md
4. Include specific code snippets showing proposed changes
5. Make the plan detailed enough that implementation is mechanical
FORMAT for plan.md:
\`\`\`markdown
# Implementation Plan
## Goal
[What we're building/changing]
## Approach
[High-level strategy]
## Changes
### 1. [First change]
**File:** path/to/file.ts
**What:** [Description]
**Code:**
\\\`\\\`\\\`typescript
// Proposed code
\\\`\\\`\\\`
### 2. [Second change]
...
## TODO
- [ ] Task 1
- [ ] Task 2
- [ ] Task 3
## Risks/Considerations
[Potential issues, edge cases]
\`\`\`
When the user adds annotations to plan.md and clicks Review, address each annotation and update the document.
Remember: Your output goes in ${artifactDir}/plan.md, not chat. Chat is for clarifying questions only.`,
},
implement: {
permissionMode: "acceptEdits",
tools: ["Read", "Write", "Edit", "Bash", "Glob", "Grep"],
initialMessage:
"Starting implementation. I'll follow the plan exactly and mark tasks complete as I go.",
systemPrompt: (artifactDir) => `You are in IMPLEMENTATION mode. Execute the approved plan.
CRITICAL RULES:
1. Read ${artifactDir}/plan.md if it exists and follow it exactly.
If plan.md does not exist, this session began at the implementation phase — implement based on the task description provided in the chat messages.
2. Mark tasks complete in ${artifactDir}/plan.md as you finish them: - [ ] → - [x]
3. DO NOT deviate from the plan without asking
4. Run tests/typecheck if available
5. Stop and ask if you encounter issues not covered by the plan
WORKFLOW:
1. Read ${artifactDir}/plan.md (if it exists)
2. Execute each task in order
3. Update ${artifactDir}/plan.md to mark tasks complete
4. Continue until all tasks are done
When complete, summarize what was done and any follow-up tasks.`,
},
};
export function getPhaseConfig(
phase: Phase,
artifactDir: string,
userPermissionMode?: UserPermissionMode,
customSystemPrompt?: string
): PhaseConfig {
const template = phaseConfigTemplates[phase];
// If a custom prompt is provided, substitute the {{artifactDir}} placeholder.
// Otherwise use the default template function (existing behaviour).
const systemPrompt =
customSystemPrompt !== undefined
? customSystemPrompt.replace(/\{\{artifactDir\}\}/g, artifactDir)
: template.systemPrompt(artifactDir);
const config: PhaseConfig = {
systemPrompt,
tools: template.tools,
permissionMode: template.permissionMode,
initialMessage: template.initialMessage,
};
if (phase === "implement" && userPermissionMode) {
config.permissionMode = userPermissionMode;
}
return config;
}
/**
* Returns the default system prompt for a phase with "{{artifactDir}}" as a
* literal placeholder — the same format used when storing a custom prompt in
* the settings DB. Used by the Settings UI to display the default text.
*/
export function getDefaultSystemPromptTemplate(phase: Phase): string {
return phaseConfigTemplates[phase].systemPrompt("{{artifactDir}}");
}
export function getPhaseInitialMessage(phase: Phase): string {
return phaseConfigTemplates[phase].initialMessage;
}
export function getNextPhase(phase: Phase): Phase | null {
const transitions: Record<Phase, Phase | null> = {
research: "plan",
plan: "implement",
implement: null,
};
return transitions[phase];
}
export function getArtifactFilename(phase: Phase): string {
return phase === "research" ? "research.md" : "plan.md";
}
|