@claudetools/tools 0.3.9 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codedna/generators/base.d.ts +41 -0
- package/dist/codedna/generators/base.js +102 -0
- package/dist/codedna/generators/express-api.d.ts +12 -0
- package/dist/codedna/generators/express-api.js +61 -0
- package/dist/codedna/index.d.ts +4 -0
- package/dist/codedna/index.js +7 -0
- package/dist/codedna/parser.d.ts +80 -0
- package/dist/codedna/parser.js +176 -0
- package/dist/codedna/registry.d.ts +60 -0
- package/dist/codedna/registry.js +214 -0
- package/dist/codedna/template-engine.d.ts +17 -0
- package/dist/codedna/template-engine.js +149 -0
- package/dist/codedna/types.d.ts +64 -0
- package/dist/codedna/types.js +4 -0
- package/dist/handlers/codedna-handlers.d.ts +122 -0
- package/dist/handlers/codedna-handlers.js +167 -0
- package/dist/handlers/tool-handlers.js +593 -14
- package/dist/helpers/api-client.d.ts +37 -0
- package/dist/helpers/api-client.js +63 -0
- package/dist/helpers/library-detection.d.ts +26 -0
- package/dist/helpers/library-detection.js +145 -0
- package/dist/helpers/tasks-retry.d.ts +49 -0
- package/dist/helpers/tasks-retry.js +168 -0
- package/dist/helpers/tasks.d.ts +24 -1
- package/dist/helpers/tasks.js +146 -50
- package/dist/helpers/workers.d.ts +25 -0
- package/dist/helpers/workers.js +80 -0
- package/dist/templates/claude-md.d.ts +1 -1
- package/dist/templates/claude-md.js +16 -5
- package/dist/tools.js +314 -0
- package/package.json +3 -1
package/dist/helpers/tasks.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Task Management System
|
|
3
3
|
// =============================================================================
|
|
4
4
|
import { apiRequest } from './api-client.js';
|
|
5
|
-
import { matchTaskToWorker } from './workers.js';
|
|
5
|
+
import { matchTaskToWorker, buildWorkerPrompt } from './workers.js';
|
|
6
6
|
export function parseJsonArray(value) {
|
|
7
7
|
if (!value)
|
|
8
8
|
return [];
|
|
@@ -90,14 +90,57 @@ export async function heartbeatTask(userId, projectId, taskId, agentId, extendMi
|
|
|
90
90
|
// -----------------------------------------------------------------------------
|
|
91
91
|
// Orchestration Functions
|
|
92
92
|
// -----------------------------------------------------------------------------
|
|
93
|
+
// Configuration: Default maximum parallel tasks
|
|
94
|
+
export const DEFAULT_MAX_PARALLEL = 5;
|
|
95
|
+
/**
|
|
96
|
+
* Get count of currently active tasks
|
|
97
|
+
* Returns both in_progress and claimed (locked) task counts
|
|
98
|
+
*/
|
|
99
|
+
export async function getActiveTaskCount(userId, projectId, epicId) {
|
|
100
|
+
// Get all in_progress tasks
|
|
101
|
+
const inProgressResult = await listTasks(userId, projectId, {
|
|
102
|
+
status: 'in_progress',
|
|
103
|
+
parent_id: epicId,
|
|
104
|
+
limit: 100,
|
|
105
|
+
});
|
|
106
|
+
let inProgressCount = 0;
|
|
107
|
+
let claimedCount = 0;
|
|
108
|
+
if (inProgressResult.success && inProgressResult.data.length > 0) {
|
|
109
|
+
const now = new Date();
|
|
110
|
+
for (const task of inProgressResult.data) {
|
|
111
|
+
inProgressCount++;
|
|
112
|
+
// Check if task is also claimed (has valid lock)
|
|
113
|
+
if (task.assigned_to && task.lock_expires_at) {
|
|
114
|
+
const lockExpires = new Date(task.lock_expires_at);
|
|
115
|
+
if (lockExpires > now) {
|
|
116
|
+
claimedCount++;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
inProgress: inProgressCount,
|
|
123
|
+
claimed: claimedCount,
|
|
124
|
+
total: inProgressCount,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
93
127
|
/**
|
|
94
128
|
* Get all tasks ready for parallel dispatch
|
|
95
129
|
* - Filters for 'ready' status
|
|
96
130
|
* - Excludes already claimed tasks
|
|
97
131
|
* - Resolves dependencies (only returns unblocked tasks)
|
|
98
132
|
* - Matches each to appropriate expert worker
|
|
133
|
+
* - Respects max parallel limit by considering currently active tasks
|
|
99
134
|
*/
|
|
100
|
-
export async function getDispatchableTasks(userId, projectId, epicId, maxParallel =
|
|
135
|
+
export async function getDispatchableTasks(userId, projectId, epicId, maxParallel = DEFAULT_MAX_PARALLEL) {
|
|
136
|
+
// Get current active task count
|
|
137
|
+
const activeCount = await getActiveTaskCount(userId, projectId, epicId);
|
|
138
|
+
// Calculate remaining capacity
|
|
139
|
+
const remainingCapacity = maxParallel - activeCount.total;
|
|
140
|
+
if (remainingCapacity <= 0) {
|
|
141
|
+
// No capacity available, return empty array
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
101
144
|
// Get all tasks with 'ready' status
|
|
102
145
|
const result = await listTasks(userId, projectId, {
|
|
103
146
|
status: 'ready',
|
|
@@ -152,7 +195,8 @@ export async function getDispatchableTasks(userId, projectId, epicId, maxParalle
|
|
|
152
195
|
parentContext: taskData.parent,
|
|
153
196
|
dependencies: [],
|
|
154
197
|
});
|
|
155
|
-
|
|
198
|
+
// Only dispatch tasks that fit within remaining capacity
|
|
199
|
+
if (dispatchable.length >= remainingCapacity) {
|
|
156
200
|
break;
|
|
157
201
|
}
|
|
158
202
|
}
|
|
@@ -184,46 +228,29 @@ export async function getExecutionContext(userId, projectId, taskId) {
|
|
|
184
228
|
siblingTasks = siblingResult.data.filter(t => t.id !== taskId);
|
|
185
229
|
}
|
|
186
230
|
}
|
|
187
|
-
// Build system prompt
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
// Add attached context
|
|
212
|
-
if (taskData.context.length > 0) {
|
|
213
|
-
systemPrompt += `## Attached Context\n`;
|
|
214
|
-
for (const ctx of taskData.context) {
|
|
215
|
-
systemPrompt += `### ${ctx.context_type.toUpperCase()}${ctx.source ? ` (${ctx.source})` : ''}\n`;
|
|
216
|
-
systemPrompt += `${ctx.content}\n\n`;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
// Add sibling task awareness
|
|
220
|
-
if (siblingTasks && siblingTasks.length > 0) {
|
|
221
|
-
systemPrompt += `## Related Tasks (for awareness)\n`;
|
|
222
|
-
for (const sibling of siblingTasks.slice(0, 5)) {
|
|
223
|
-
systemPrompt += `- ${sibling.title} [${sibling.status}]\n`;
|
|
224
|
-
}
|
|
225
|
-
systemPrompt += '\n';
|
|
226
|
-
}
|
|
231
|
+
// Build structured system prompt using the template system
|
|
232
|
+
const systemPrompt = buildWorkerPrompt({
|
|
233
|
+
task: {
|
|
234
|
+
id: task.id,
|
|
235
|
+
title: task.title,
|
|
236
|
+
description: task.description || undefined,
|
|
237
|
+
acceptance_criteria: task.acceptance_criteria,
|
|
238
|
+
},
|
|
239
|
+
worker,
|
|
240
|
+
epicContext: taskData.parent ? {
|
|
241
|
+
title: taskData.parent.title,
|
|
242
|
+
description: taskData.parent.description || undefined,
|
|
243
|
+
} : undefined,
|
|
244
|
+
attachedContext: taskData.context.map(ctx => ({
|
|
245
|
+
type: ctx.context_type,
|
|
246
|
+
content: ctx.content,
|
|
247
|
+
source: ctx.source || undefined,
|
|
248
|
+
})),
|
|
249
|
+
siblingTasks: siblingTasks?.slice(0, 5).map(s => ({
|
|
250
|
+
title: s.title,
|
|
251
|
+
status: s.status,
|
|
252
|
+
})),
|
|
253
|
+
});
|
|
227
254
|
return {
|
|
228
255
|
task,
|
|
229
256
|
worker,
|
|
@@ -234,20 +261,20 @@ export async function getExecutionContext(userId, projectId, taskId) {
|
|
|
234
261
|
};
|
|
235
262
|
}
|
|
236
263
|
/**
|
|
237
|
-
* Find newly unblocked tasks after a completion
|
|
264
|
+
* Find newly unblocked tasks after a completion and update their status to ready
|
|
238
265
|
*/
|
|
239
266
|
export async function resolveTaskDependencies(userId, projectId, completedTaskId, epicId) {
|
|
240
|
-
// Get all tasks that might be
|
|
241
|
-
const
|
|
242
|
-
status: '
|
|
267
|
+
// Get all blocked tasks that might be unblocked by the completed task
|
|
268
|
+
const blockedResult = await listTasks(userId, projectId, {
|
|
269
|
+
status: 'blocked',
|
|
243
270
|
parent_id: epicId,
|
|
244
271
|
limit: 50,
|
|
245
272
|
});
|
|
246
|
-
if (!
|
|
273
|
+
if (!blockedResult.success) {
|
|
247
274
|
return [];
|
|
248
275
|
}
|
|
249
276
|
const newlyUnblocked = [];
|
|
250
|
-
for (const task of
|
|
277
|
+
for (const task of blockedResult.data) {
|
|
251
278
|
const blockedBy = parseJsonArray(task.blocked_by);
|
|
252
279
|
// Check if this task was blocked by the completed task
|
|
253
280
|
if (blockedBy.includes(completedTaskId)) {
|
|
@@ -265,10 +292,79 @@ export async function resolveTaskDependencies(userId, projectId, completedTaskId
|
|
|
265
292
|
}
|
|
266
293
|
}
|
|
267
294
|
}
|
|
295
|
+
// If all blockers are complete, update task status to ready
|
|
268
296
|
if (allBlockersComplete) {
|
|
269
|
-
|
|
297
|
+
const updateResult = await updateTaskStatus(userId, projectId, task.id, 'ready');
|
|
298
|
+
if (updateResult.success) {
|
|
299
|
+
newlyUnblocked.push(updateResult.data);
|
|
300
|
+
}
|
|
270
301
|
}
|
|
271
302
|
}
|
|
272
303
|
}
|
|
273
304
|
return newlyUnblocked;
|
|
274
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* Get epic status with progress tracking
|
|
308
|
+
* Auto-completes epic if all child tasks are done
|
|
309
|
+
*/
|
|
310
|
+
export async function getEpicStatus(userId, projectId, epicId) {
|
|
311
|
+
// Get the epic
|
|
312
|
+
const epicResult = await getTask(userId, projectId, epicId);
|
|
313
|
+
if (!epicResult.success) {
|
|
314
|
+
throw new Error(`Epic not found: ${epicId}`);
|
|
315
|
+
}
|
|
316
|
+
const epic = epicResult.data;
|
|
317
|
+
// Verify it's an epic
|
|
318
|
+
if (epic.type !== 'epic') {
|
|
319
|
+
throw new Error(`Task ${epicId} is not an epic (type: ${epic.type})`);
|
|
320
|
+
}
|
|
321
|
+
// Get all child tasks
|
|
322
|
+
const tasksResult = await listTasks(userId, projectId, {
|
|
323
|
+
parent_id: epicId,
|
|
324
|
+
limit: 100,
|
|
325
|
+
});
|
|
326
|
+
if (!tasksResult.success) {
|
|
327
|
+
return {
|
|
328
|
+
epic,
|
|
329
|
+
totalTasks: 0,
|
|
330
|
+
byStatus: {},
|
|
331
|
+
percentComplete: 0,
|
|
332
|
+
allComplete: false,
|
|
333
|
+
autoCompleted: false,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
const tasks = tasksResult.data;
|
|
337
|
+
const totalTasks = tasks.length;
|
|
338
|
+
// Count by status
|
|
339
|
+
const byStatus = {
|
|
340
|
+
backlog: 0,
|
|
341
|
+
ready: 0,
|
|
342
|
+
in_progress: 0,
|
|
343
|
+
blocked: 0,
|
|
344
|
+
review: 0,
|
|
345
|
+
done: 0,
|
|
346
|
+
cancelled: 0,
|
|
347
|
+
};
|
|
348
|
+
for (const task of tasks) {
|
|
349
|
+
byStatus[task.status] = (byStatus[task.status] || 0) + 1;
|
|
350
|
+
}
|
|
351
|
+
// Calculate progress
|
|
352
|
+
const doneCount = byStatus.done || 0;
|
|
353
|
+
const percentComplete = totalTasks > 0 ? Math.round((doneCount / totalTasks) * 100) : 0;
|
|
354
|
+
const allComplete = totalTasks > 0 && doneCount === totalTasks;
|
|
355
|
+
// Auto-complete epic if all tasks done and epic not already done
|
|
356
|
+
let autoCompleted = false;
|
|
357
|
+
if (allComplete && epic.status !== 'done') {
|
|
358
|
+
await updateTaskStatus(userId, projectId, epicId, 'done', 'system:auto-complete');
|
|
359
|
+
epic.status = 'done';
|
|
360
|
+
autoCompleted = true;
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
epic,
|
|
364
|
+
totalTasks,
|
|
365
|
+
byStatus,
|
|
366
|
+
percentComplete,
|
|
367
|
+
allComplete,
|
|
368
|
+
autoCompleted,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
@@ -7,6 +7,31 @@ export interface ExpertWorker {
|
|
|
7
7
|
promptTemplate: string;
|
|
8
8
|
}
|
|
9
9
|
export declare const EXPERT_WORKERS: Record<string, ExpertWorker>;
|
|
10
|
+
/**
|
|
11
|
+
* Build a structured worker prompt that includes task context, protocol, error handling
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildWorkerPrompt(params: {
|
|
14
|
+
task: {
|
|
15
|
+
id: string;
|
|
16
|
+
title: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
acceptance_criteria?: string | string[];
|
|
19
|
+
};
|
|
20
|
+
worker: ExpertWorker;
|
|
21
|
+
epicContext?: {
|
|
22
|
+
title: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
};
|
|
25
|
+
attachedContext?: Array<{
|
|
26
|
+
type: string;
|
|
27
|
+
content: string;
|
|
28
|
+
source?: string;
|
|
29
|
+
}>;
|
|
30
|
+
siblingTasks?: Array<{
|
|
31
|
+
title: string;
|
|
32
|
+
status: string;
|
|
33
|
+
}>;
|
|
34
|
+
}): string;
|
|
10
35
|
/**
|
|
11
36
|
* Match a task to the best expert worker based on domain patterns
|
|
12
37
|
*/
|
package/dist/helpers/workers.js
CHANGED
|
@@ -92,6 +92,86 @@ When complete, provide a concise summary of integrations configured.`,
|
|
|
92
92
|
When complete, provide a concise summary of work done.`,
|
|
93
93
|
},
|
|
94
94
|
};
|
|
95
|
+
/**
|
|
96
|
+
* Build a structured worker prompt that includes task context, protocol, error handling
|
|
97
|
+
*/
|
|
98
|
+
export function buildWorkerPrompt(params) {
|
|
99
|
+
const { task, worker, epicContext, attachedContext, siblingTasks } = params;
|
|
100
|
+
let prompt = '';
|
|
101
|
+
// Worker domain introduction
|
|
102
|
+
prompt += `${worker.promptTemplate}\n\n`;
|
|
103
|
+
prompt += `---\n\n`;
|
|
104
|
+
// Task header
|
|
105
|
+
prompt += `## Task: ${task.title}\n`;
|
|
106
|
+
prompt += `**Task ID:** ${task.id}\n\n`;
|
|
107
|
+
// Task description
|
|
108
|
+
if (task.description) {
|
|
109
|
+
prompt += `## Description\n${task.description}\n\n`;
|
|
110
|
+
}
|
|
111
|
+
// Acceptance criteria
|
|
112
|
+
const criteria = Array.isArray(task.acceptance_criteria)
|
|
113
|
+
? task.acceptance_criteria
|
|
114
|
+
: (task.acceptance_criteria ? [task.acceptance_criteria] : []);
|
|
115
|
+
if (criteria.length > 0) {
|
|
116
|
+
prompt += `## Acceptance Criteria\n`;
|
|
117
|
+
criteria.forEach((criterion, index) => {
|
|
118
|
+
prompt += `${index + 1}. ${criterion}\n`;
|
|
119
|
+
});
|
|
120
|
+
prompt += '\n';
|
|
121
|
+
}
|
|
122
|
+
// Epic context
|
|
123
|
+
if (epicContext) {
|
|
124
|
+
prompt += `## Epic Context\n`;
|
|
125
|
+
prompt += `**Epic:** ${epicContext.title}\n`;
|
|
126
|
+
if (epicContext.description) {
|
|
127
|
+
prompt += `**Goal:** ${epicContext.description}\n`;
|
|
128
|
+
}
|
|
129
|
+
prompt += '\n';
|
|
130
|
+
}
|
|
131
|
+
// Attached context
|
|
132
|
+
if (attachedContext && attachedContext.length > 0) {
|
|
133
|
+
prompt += `## Attached Context\n`;
|
|
134
|
+
for (const ctx of attachedContext) {
|
|
135
|
+
prompt += `### ${ctx.type.toUpperCase()}${ctx.source ? ` (${ctx.source})` : ''}\n`;
|
|
136
|
+
prompt += `${ctx.content}\n\n`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Related tasks
|
|
140
|
+
if (siblingTasks && siblingTasks.length > 0) {
|
|
141
|
+
prompt += `## Related Tasks (for awareness)\n`;
|
|
142
|
+
for (const sibling of siblingTasks.slice(0, 5)) {
|
|
143
|
+
prompt += `- ${sibling.title} [${sibling.status}]\n`;
|
|
144
|
+
}
|
|
145
|
+
prompt += '\n';
|
|
146
|
+
}
|
|
147
|
+
// Protocol instructions
|
|
148
|
+
prompt += `## Protocol\n`;
|
|
149
|
+
prompt += `You MUST follow this protocol:\n\n`;
|
|
150
|
+
prompt += `1. **Start the task:** Call \`task_start(task_id="${task.id}", agent_id="<your-agent-id>")\` to claim this task\n`;
|
|
151
|
+
prompt += `2. **Complete the work:** Implement the requirements described above\n`;
|
|
152
|
+
prompt += `3. **Complete the task:** Call \`task_complete(task_id="${task.id}", summary="<detailed-summary>")\` with:\n`;
|
|
153
|
+
prompt += ` - What you implemented\n`;
|
|
154
|
+
prompt += ` - Files modified or created\n`;
|
|
155
|
+
prompt += ` - Any important decisions made\n`;
|
|
156
|
+
prompt += ` - Testing performed (if applicable)\n\n`;
|
|
157
|
+
// Error handling
|
|
158
|
+
prompt += `## Error Handling\n`;
|
|
159
|
+
prompt += `If you encounter blocking errors or issues:\n\n`;
|
|
160
|
+
prompt += `1. **Log the error:** Call \`task_add_context(task_id="${task.id}", context_type="work_log", content="ERROR: <description>", added_by="<your-agent-id>")\`\n`;
|
|
161
|
+
prompt += `2. **Release the task:** Call \`task_release(task_id="${task.id}", agent_id="<your-agent-id>", new_status="blocked", work_log="<summary-of-issue>")\`\n`;
|
|
162
|
+
prompt += `3. **Do NOT mark the task as complete** if the work is not finished\n\n`;
|
|
163
|
+
// Result format
|
|
164
|
+
prompt += `## Result Format\n`;
|
|
165
|
+
prompt += `When calling task_complete, your summary should include:\n\n`;
|
|
166
|
+
prompt += `- **Implementation:** What you built/changed\n`;
|
|
167
|
+
prompt += `- **Files:** List of modified files with paths\n`;
|
|
168
|
+
prompt += `- **Decisions:** Any architectural or design choices\n`;
|
|
169
|
+
prompt += `- **Testing:** How the changes were verified\n`;
|
|
170
|
+
prompt += `- **Notes:** Any caveats, limitations, or follow-up needed\n\n`;
|
|
171
|
+
prompt += `---\n\n`;
|
|
172
|
+
prompt += `**Begin work now. Remember to call task_start first!**\n`;
|
|
173
|
+
return prompt;
|
|
174
|
+
}
|
|
95
175
|
/**
|
|
96
176
|
* Match a task to the best expert worker based on domain patterns
|
|
97
177
|
*/
|
|
@@ -5,7 +5,7 @@ export declare const PROJECT_SECTION_END = "<!-- CLAUDETOOLS:PROJECT:END -->";
|
|
|
5
5
|
/**
|
|
6
6
|
* Global CLAUDE.md content - added to ~/.claude/CLAUDE.md
|
|
7
7
|
*/
|
|
8
|
-
export declare const GLOBAL_TEMPLATE = "\n<!-- CLAUDETOOLS:START -->\n# ClaudeTools Memory System\n\nYou have access to a persistent memory system via the `claudetools_memory` MCP server. Use it to remember context across sessions.\n\n## Memory Tools\n\n### Searching Memory\n```\nmemory_search(query: \"authentication patterns\")\n```\nSearch for relevant facts, entities, and past context. Use this when:\n- Starting work on a feature to recall past decisions\n- Looking for patterns or conventions used before\n- Finding related code or architectural context\n\n### Storing Facts\n```\nmemory_store_fact(\n entity1: \"UserService\",\n relationship: \"USES\",\n entity2: \"bcrypt\",\n context: \"Password hashing uses bcrypt with 12 rounds\"\n)\n```\nStore important facts as relationships between entities. Use for:\n- Architectural decisions\n- Code patterns and conventions\n- Dependencies and relationships\n- User preferences learned during conversation\n\n### Context Injection\nContext is automatically injected at the start of each session based on the current project. Check `~/.claudetools/session-context.md` for project-specific context.\n\n## Task Management\n\n### Creating Work Plans\n```\ntask_plan(\n goal: \"Add user authentication\",\n epic_title: \"User Auth System\",\n tasks: [...]\n)\n```\nBreak down complex work into tracked tasks.\n\n###
|
|
8
|
+
export declare const GLOBAL_TEMPLATE = "\n<!-- CLAUDETOOLS:START -->\n# ClaudeTools Memory System\n\nYou have access to a persistent memory system via the `claudetools_memory` MCP server. Use it to remember context across sessions.\n\n## Memory Tools\n\n### Searching Memory\n```\nmemory_search(query: \"authentication patterns\")\n```\nSearch for relevant facts, entities, and past context. Use this when:\n- Starting work on a feature to recall past decisions\n- Looking for patterns or conventions used before\n- Finding related code or architectural context\n\n### Storing Facts\n```\nmemory_store_fact(\n entity1: \"UserService\",\n relationship: \"USES\",\n entity2: \"bcrypt\",\n context: \"Password hashing uses bcrypt with 12 rounds\"\n)\n```\nStore important facts as relationships between entities. Use for:\n- Architectural decisions\n- Code patterns and conventions\n- Dependencies and relationships\n- User preferences learned during conversation\n\n### Context Injection\nContext is automatically injected at the start of each session based on the current project. Check `~/.claudetools/session-context.md` for project-specific context.\n\n## Task Management\n\n### Creating Work Plans with Auto-Dispatch\n```\ntask_plan(\n goal: \"Add user authentication\",\n epic_title: \"User Auth System\",\n tasks: [...]\n)\n```\nBreak down complex work into tracked tasks. **Tasks are automatically set to `ready` status.**\n\nAfter `task_plan` completes, you will receive Task tool invocations to spawn parallel agents.\n**Execute ALL Task tool calls in a SINGLE message** to enable parallel execution.\n\n### Parallel Agent Workflow\n1. User describes work needed\n2. Call `task_plan_draft` to present the plan\n3. User says \"go\" to approve\n4. Call `task_plan` - tasks created in `ready` status\n5. Execute the provided Task tool calls in ONE message\n6. Agents work in parallel, each calling `task_complete` when done\n\n### Manual Task Start (Sequential)\n```\ntask_start(task_id: \"task_xxx\")\n```\nClaim a task before working on it. Use for sequential execution.\n\n### Completing Tasks\n```\ntask_complete(task_id: \"task_xxx\", summary: \"Implemented JWT auth with refresh tokens\")\n```\nMark tasks done with a summary of work completed. **Always call this when a task is finished.**\n\n## Codebase Intelligence\n\n### Finding Code\n```\ncodebase_map() # Get overview of project structure\ncodebase_find(\"UserService\") # Find symbols/files\ncodebase_context(\"src/auth.ts\") # Get file dependencies\n```\n\n### Impact Analysis\n```\nanalyze_impact(function_name: \"validateToken\")\n```\nSee what would be affected by changing a function.\n\n## Best Practices\n\n1. **Search before implementing** - Check memory for existing patterns\n2. **Store decisions** - Save architectural choices as facts\n3. **Use task tracking** - Break complex work into tasks\n4. **Complete tasks** - Always mark tasks done with summaries\n<!-- CLAUDETOOLS:END -->\n";
|
|
9
9
|
/**
|
|
10
10
|
* Project-level CLAUDE.md content - added to .claude/CLAUDE.md
|
|
11
11
|
*/
|
|
@@ -47,7 +47,7 @@ Context is automatically injected at the start of each session based on the curr
|
|
|
47
47
|
|
|
48
48
|
## Task Management
|
|
49
49
|
|
|
50
|
-
### Creating Work Plans
|
|
50
|
+
### Creating Work Plans with Auto-Dispatch
|
|
51
51
|
\`\`\`
|
|
52
52
|
task_plan(
|
|
53
53
|
goal: "Add user authentication",
|
|
@@ -55,19 +55,30 @@ task_plan(
|
|
|
55
55
|
tasks: [...]
|
|
56
56
|
)
|
|
57
57
|
\`\`\`
|
|
58
|
-
Break down complex work into tracked tasks.
|
|
58
|
+
Break down complex work into tracked tasks. **Tasks are automatically set to \`ready\` status.**
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
After \`task_plan\` completes, you will receive Task tool invocations to spawn parallel agents.
|
|
61
|
+
**Execute ALL Task tool calls in a SINGLE message** to enable parallel execution.
|
|
62
|
+
|
|
63
|
+
### Parallel Agent Workflow
|
|
64
|
+
1. User describes work needed
|
|
65
|
+
2. Call \`task_plan_draft\` to present the plan
|
|
66
|
+
3. User says "go" to approve
|
|
67
|
+
4. Call \`task_plan\` - tasks created in \`ready\` status
|
|
68
|
+
5. Execute the provided Task tool calls in ONE message
|
|
69
|
+
6. Agents work in parallel, each calling \`task_complete\` when done
|
|
70
|
+
|
|
71
|
+
### Manual Task Start (Sequential)
|
|
61
72
|
\`\`\`
|
|
62
73
|
task_start(task_id: "task_xxx")
|
|
63
74
|
\`\`\`
|
|
64
|
-
Claim a task before working on it.
|
|
75
|
+
Claim a task before working on it. Use for sequential execution.
|
|
65
76
|
|
|
66
77
|
### Completing Tasks
|
|
67
78
|
\`\`\`
|
|
68
79
|
task_complete(task_id: "task_xxx", summary: "Implemented JWT auth with refresh tokens")
|
|
69
80
|
\`\`\`
|
|
70
|
-
Mark tasks done with a summary of work completed.
|
|
81
|
+
Mark tasks done with a summary of work completed. **Always call this when a task is finished.**
|
|
71
82
|
|
|
72
83
|
## Codebase Intelligence
|
|
73
84
|
|