claude-mycelium 2.0.0 → 2.2.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.
Files changed (208) hide show
  1. package/.agent-meta/_inhibitors.ndjson +1287 -0
  2. package/.agent-meta/_quarantine.json +45 -0
  3. package/.agent-meta/config.json +9 -0
  4. package/.agent-meta/tasks/_active.json +4 -0
  5. package/.agent-meta/tasks/task_0657b028-05a0-4b0c-b0b9-a4eae3d66cd9.json +168 -0
  6. package/.claude/memory.db +0 -0
  7. package/.claude/settings.local.json +4 -1
  8. package/README.md +85 -233
  9. package/SECURITY.md +145 -0
  10. package/dist/agent/task-worker.d.ts +11 -0
  11. package/dist/agent/task-worker.d.ts.map +1 -0
  12. package/dist/agent/task-worker.js +173 -0
  13. package/dist/agent/task-worker.js.map +1 -0
  14. package/dist/agent/worker.d.ts +8 -0
  15. package/dist/agent/worker.d.ts.map +1 -0
  16. package/dist/agent/worker.js +97 -0
  17. package/dist/agent/worker.js.map +1 -0
  18. package/dist/bin.d.ts +7 -0
  19. package/dist/bin.d.ts.map +1 -0
  20. package/dist/bin.js +11 -0
  21. package/dist/bin.js.map +1 -0
  22. package/dist/cli/cost.d.ts +10 -0
  23. package/dist/cli/cost.d.ts.map +1 -0
  24. package/dist/cli/cost.js +163 -0
  25. package/dist/cli/cost.js.map +1 -0
  26. package/dist/cli/gc.d.ts +10 -0
  27. package/dist/cli/gc.d.ts.map +1 -0
  28. package/dist/cli/gc.js +108 -0
  29. package/dist/cli/gc.js.map +1 -0
  30. package/dist/cli/gradients.d.ts +10 -0
  31. package/dist/cli/gradients.d.ts.map +1 -0
  32. package/dist/cli/gradients.js +70 -0
  33. package/dist/cli/gradients.js.map +1 -0
  34. package/dist/cli/grow.d.ts +17 -0
  35. package/dist/cli/grow.d.ts.map +1 -0
  36. package/dist/cli/grow.js +373 -0
  37. package/dist/cli/grow.js.map +1 -0
  38. package/dist/cli/index.d.ts +17 -0
  39. package/dist/cli/index.d.ts.map +1 -0
  40. package/dist/cli/index.js +74 -0
  41. package/dist/cli/index.js.map +1 -0
  42. package/dist/cli/init.d.ts +11 -0
  43. package/dist/cli/init.d.ts.map +1 -0
  44. package/dist/cli/init.js +97 -0
  45. package/dist/cli/init.js.map +1 -0
  46. package/dist/cli/status.d.ts +10 -0
  47. package/dist/cli/status.d.ts.map +1 -0
  48. package/dist/cli/status.js +191 -0
  49. package/dist/cli/status.js.map +1 -0
  50. package/dist/coordination/file-locks.d.ts +42 -0
  51. package/dist/coordination/file-locks.d.ts.map +1 -0
  52. package/dist/coordination/file-locks.js +269 -0
  53. package/dist/coordination/file-locks.js.map +1 -0
  54. package/dist/coordination/index.d.ts +4 -0
  55. package/dist/coordination/index.d.ts.map +1 -1
  56. package/dist/coordination/index.js +4 -0
  57. package/dist/coordination/index.js.map +1 -1
  58. package/dist/coordination/inhibitors.d.ts +84 -0
  59. package/dist/coordination/inhibitors.d.ts.map +1 -0
  60. package/dist/coordination/inhibitors.js +290 -0
  61. package/dist/coordination/inhibitors.js.map +1 -0
  62. package/dist/coordination/process-manager.d.ts +73 -0
  63. package/dist/coordination/process-manager.d.ts.map +1 -0
  64. package/dist/coordination/process-manager.js +144 -0
  65. package/dist/coordination/process-manager.js.map +1 -0
  66. package/dist/core/agent-executor.d.ts +4 -1
  67. package/dist/core/agent-executor.d.ts.map +1 -1
  68. package/dist/core/agent-executor.js +38 -12
  69. package/dist/core/agent-executor.js.map +1 -1
  70. package/dist/core/change-applier.d.ts +29 -5
  71. package/dist/core/change-applier.d.ts.map +1 -1
  72. package/dist/core/change-applier.js +254 -24
  73. package/dist/core/change-applier.js.map +1 -1
  74. package/dist/core/signals/churn.d.ts.map +1 -1
  75. package/dist/core/signals/churn.js +6 -4
  76. package/dist/core/signals/churn.js.map +1 -1
  77. package/dist/core/signals/debt.d.ts.map +1 -1
  78. package/dist/core/signals/debt.js +4 -3
  79. package/dist/core/signals/debt.js.map +1 -1
  80. package/dist/cost/cost-tracker.d.ts.map +1 -1
  81. package/dist/cost/cost-tracker.js +2 -0
  82. package/dist/cost/cost-tracker.js.map +1 -1
  83. package/dist/gc/index.d.ts +17 -0
  84. package/dist/gc/index.d.ts.map +1 -0
  85. package/dist/gc/index.js +17 -0
  86. package/dist/gc/index.js.map +1 -0
  87. package/dist/gc/runner.d.ts +39 -0
  88. package/dist/gc/runner.d.ts.map +1 -0
  89. package/dist/gc/runner.js +277 -0
  90. package/dist/gc/runner.js.map +1 -0
  91. package/dist/gc/trace-compactor.d.ts +31 -0
  92. package/dist/gc/trace-compactor.d.ts.map +1 -0
  93. package/dist/gc/trace-compactor.js +162 -0
  94. package/dist/gc/trace-compactor.js.map +1 -0
  95. package/dist/index.d.ts +5 -1
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +6 -1
  98. package/dist/index.js.map +1 -1
  99. package/dist/prompts/index.d.ts +2 -1
  100. package/dist/prompts/index.d.ts.map +1 -1
  101. package/dist/prompts/index.js.map +1 -1
  102. package/dist/quarantine/explorer.d.ts +65 -0
  103. package/dist/quarantine/explorer.d.ts.map +1 -0
  104. package/dist/quarantine/explorer.js +175 -0
  105. package/dist/quarantine/explorer.js.map +1 -0
  106. package/dist/quarantine/index.d.ts +7 -0
  107. package/dist/quarantine/index.d.ts.map +1 -0
  108. package/dist/quarantine/index.js +7 -0
  109. package/dist/quarantine/index.js.map +1 -0
  110. package/dist/quarantine/manager.d.ts +75 -0
  111. package/dist/quarantine/manager.d.ts.map +1 -0
  112. package/dist/quarantine/manager.js +275 -0
  113. package/dist/quarantine/manager.js.map +1 -0
  114. package/dist/task/acceptance.d.ts +29 -0
  115. package/dist/task/acceptance.d.ts.map +1 -0
  116. package/dist/task/acceptance.js +228 -0
  117. package/dist/task/acceptance.js.map +1 -0
  118. package/dist/task/agent-coordinator.d.ts +40 -0
  119. package/dist/task/agent-coordinator.d.ts.map +1 -0
  120. package/dist/task/agent-coordinator.js +168 -0
  121. package/dist/task/agent-coordinator.js.map +1 -0
  122. package/dist/task/executor.d.ts +37 -0
  123. package/dist/task/executor.d.ts.map +1 -0
  124. package/dist/task/executor.js +462 -0
  125. package/dist/task/executor.js.map +1 -0
  126. package/dist/task/index.d.ts +12 -0
  127. package/dist/task/index.d.ts.map +1 -0
  128. package/dist/task/index.js +12 -0
  129. package/dist/task/index.js.map +1 -0
  130. package/dist/task/planner.d.ts +21 -0
  131. package/dist/task/planner.d.ts.map +1 -0
  132. package/dist/task/planner.js +253 -0
  133. package/dist/task/planner.js.map +1 -0
  134. package/dist/task/storage.d.ts +46 -0
  135. package/dist/task/storage.d.ts.map +1 -0
  136. package/dist/task/storage.js +266 -0
  137. package/dist/task/storage.js.map +1 -0
  138. package/dist/trace/trace-event.d.ts +2 -18
  139. package/dist/trace/trace-event.d.ts.map +1 -1
  140. package/dist/trace/trace-event.js +6 -6
  141. package/dist/trace/trace-event.js.map +1 -1
  142. package/dist/utils/file-utils.d.ts.map +1 -1
  143. package/dist/utils/file-utils.js +54 -15
  144. package/dist/utils/file-utils.js.map +1 -1
  145. package/docs/PHASE5_IMPLEMENTATION.md +237 -0
  146. package/docs/PHASES-3-7-COMPLETE.md +177 -0
  147. package/docs/PHASE_4_COMPLETE.md +135 -0
  148. package/docs/PHASE_7_DELIVERABLES.md +295 -0
  149. package/docs/PHASE_7_IMPLEMENTATION.md +306 -0
  150. package/docs/PHASE_7_SUMMARY.txt +195 -0
  151. package/docs/RELEASE-NOTES-v2.1.md +213 -0
  152. package/docs/ROADMAP.md +194 -107
  153. package/docs/SECURITY-AUDIT.md +387 -0
  154. package/docs/SNAPSHOT.md +59 -32
  155. package/docs/implementation/phase3-summary.md +220 -0
  156. package/package.json +27 -11
  157. package/src/agent/task-worker.ts +196 -0
  158. package/src/agent/worker.ts +111 -0
  159. package/src/bin.ts +13 -0
  160. package/src/cli/cost.ts +210 -0
  161. package/src/cli/gc.ts +138 -0
  162. package/src/cli/gradients.ts +97 -0
  163. package/src/cli/grow.ts +416 -0
  164. package/src/cli/index.ts +81 -0
  165. package/src/cli/init.ts +139 -0
  166. package/src/cli/status.ts +218 -0
  167. package/src/coordination/file-locks.ts +300 -0
  168. package/src/coordination/index.ts +4 -0
  169. package/src/coordination/inhibitors.ts +345 -0
  170. package/src/coordination/process-manager.ts +199 -0
  171. package/src/core/agent-executor.ts +37 -8
  172. package/src/core/signals/churn.ts +8 -5
  173. package/src/core/signals/debt.ts +4 -3
  174. package/src/cost/cost-tracker.ts +2 -0
  175. package/src/gc/index.ts +17 -0
  176. package/src/gc/runner.ts +314 -0
  177. package/src/gc/trace-compactor.ts +187 -0
  178. package/src/index.ts +7 -1
  179. package/src/prompts/index.ts +2 -1
  180. package/src/quarantine/explorer.ts +234 -0
  181. package/src/quarantine/index.ts +7 -0
  182. package/src/quarantine/manager.ts +336 -0
  183. package/src/task/acceptance.ts +267 -0
  184. package/src/task/agent-coordinator.ts +220 -0
  185. package/src/task/executor.ts +543 -0
  186. package/src/task/index.ts +38 -0
  187. package/src/task/planner.ts +294 -0
  188. package/src/task/storage.ts +332 -0
  189. package/src/trace/trace-event.ts +7 -26
  190. package/src/utils/file-utils.ts +61 -15
  191. package/tests/cli/gc.test.ts +206 -0
  192. package/tests/cli/init.test.ts +181 -0
  193. package/tests/cli/status.test.ts +282 -0
  194. package/tests/coordination/file-locks.test.ts +196 -0
  195. package/tests/coordination/inhibitors.test.ts +459 -0
  196. package/tests/coordination/integration.test.ts +195 -0
  197. package/tests/coordination/process-manager.test.ts +165 -0
  198. package/tests/gc/trace-compactor.test.ts +245 -0
  199. package/tests/integration/phase-7.test.ts +145 -0
  200. package/tests/quarantine/explorer.test.ts +381 -0
  201. package/tests/quarantine/manager.test.ts +399 -0
  202. package/tests/security/command-injection.test.ts +88 -0
  203. package/tests/security/path-traversal.test.ts +103 -0
  204. package/tests/task/acceptance.test.ts +411 -0
  205. package/tests/task/executor.test.ts +421 -0
  206. package/tests/task/planner.test.ts +359 -0
  207. package/tests/trace/trace-event.test.ts +62 -20
  208. package/tsconfig.json +2 -2
@@ -0,0 +1,543 @@
1
+ /**
2
+ * Task Execution Implementation
3
+ * Per second-spec §12.2: Task Step Execution
4
+ *
5
+ * Executes task steps using the mycelium multi-agent system.
6
+ * Each step spawns an independent agent process that uses file locks,
7
+ * inhibitors, and the full RALPH-style executeAgent() cycle.
8
+ *
9
+ * This is TRUE multi-agent coordination as per ADR-004.
10
+ */
11
+
12
+ import { Task, TaskStep } from '../types/index.js';
13
+ import { logDebug, logError, logInfo } from '../utils/logger.js';
14
+ import {
15
+ executeWaveWithAgents,
16
+ getParallelizableSteps,
17
+ type AgentResult,
18
+ } from './agent-coordinator.js';
19
+
20
+ /**
21
+ * Execute a complete task by running all steps in dependency order
22
+ *
23
+ * This spawns independent agent processes for each step, coordinated
24
+ * via file locks. Multiple agents can work in parallel on different
25
+ * files, implementing true RALPH-style multi-agent coordination.
26
+ */
27
+ export async function executeTask(task: Task): Promise<Task> {
28
+ logInfo('Executing task with multi-agent coordination', {
29
+ taskId: task.id,
30
+ steps: task.plan?.steps.length,
31
+ });
32
+
33
+ if (!task.plan) {
34
+ throw new Error('Cannot execute task without a plan');
35
+ }
36
+
37
+ const waves = getParallelizableSteps(task.plan.steps);
38
+
39
+ logInfo('Task execution plan', {
40
+ taskId: task.id,
41
+ totalSteps: task.plan.steps.length,
42
+ waves: waves.length,
43
+ waveSizes: waves.map(w => w.length),
44
+ });
45
+
46
+ for (let waveIndex = 0; waveIndex < waves.length; waveIndex++) {
47
+ const wave = waves[waveIndex];
48
+ logInfo('Executing wave', {
49
+ taskId: task.id,
50
+ wave: waveIndex + 1,
51
+ totalWaves: waves.length,
52
+ stepsInWave: wave.length,
53
+ });
54
+
55
+ // Execute all steps in this wave using agent processes
56
+ // Each agent runs in its own process with file locks
57
+ const results: AgentResult[] = await executeWaveWithAgents(task, wave);
58
+
59
+ // Check for failures
60
+ const failed = results.find(r => !r.success);
61
+ if (failed) {
62
+ task.status = 'failed';
63
+ task.error = failed.error || 'Agent execution failed';
64
+ logError('Task wave failed', new Error(task.error), {
65
+ taskId: task.id,
66
+ wave: waveIndex + 1,
67
+ failedStep: failed.stepOrder,
68
+ });
69
+ return task;
70
+ }
71
+
72
+ // Update completed steps
73
+ for (let i = 0; i < wave.length; i++) {
74
+ const result = results.find(r => r.stepOrder === wave[i].order);
75
+ if (result && result.success) {
76
+ wave[i].completed = true;
77
+ wave[i].trace_id = result.traceId;
78
+ task.steps_completed++;
79
+
80
+ // Track file changes
81
+ if (wave[i].mode === 'create') {
82
+ task.files_created.push(wave[i].target_file);
83
+ } else {
84
+ if (!task.files_modified.includes(wave[i].target_file)) {
85
+ task.files_modified.push(wave[i].target_file);
86
+ }
87
+ }
88
+
89
+ if (result.traceId) {
90
+ task.traces.push(result.traceId);
91
+ }
92
+ }
93
+ }
94
+
95
+ logInfo('Wave complete', {
96
+ taskId: task.id,
97
+ wave: waveIndex + 1,
98
+ successCount: results.filter(r => r.success).length,
99
+ failureCount: results.filter(r => !r.success).length,
100
+ });
101
+ }
102
+
103
+ task.status = 'completed';
104
+ logInfo('Task execution completed', {
105
+ taskId: task.id,
106
+ stepsCompleted: task.steps_completed,
107
+ filesCreated: task.files_created.length,
108
+ filesModified: task.files_modified.length,
109
+ });
110
+
111
+ return task;
112
+ }
113
+
114
+
115
+ /**
116
+ * Track progress of task execution
117
+ */
118
+ export function trackProgress(task: Task): {
119
+ percentage: number;
120
+ completed: number;
121
+ total: number;
122
+ status: string;
123
+ } {
124
+ const percentage = task.steps_total > 0
125
+ ? Math.round((task.steps_completed / task.steps_total) * 100)
126
+ : 0;
127
+
128
+ return {
129
+ percentage,
130
+ completed: task.steps_completed,
131
+ total: task.steps_total,
132
+ status: task.status,
133
+ };
134
+ }
135
+
136
+ task: Task,
137
+ step: TaskStep
138
+ ): Promise<{ success: boolean; trace_id?: string; error?: string }> {
139
+ // Check if file already exists
140
+ if (fileExists(step.target_file)) {
141
+ return {
142
+ success: false,
143
+ error: `Cannot create file ${step.target_file} - already exists`,
144
+ };
145
+ }
146
+
147
+ // Build prompt for file creation
148
+ const systemPrompt = buildCreateSystemPrompt();
149
+ const userPrompt = buildCreateUserPrompt(task, step);
150
+
151
+ // Call LLM to generate file content
152
+ const response = await callLLM({
153
+ prompt: userPrompt,
154
+ systemPrompt,
155
+ temperature: 0.5,
156
+ maxTokens: 4000,
157
+ });
158
+
159
+ // Extract code from response
160
+ const fileContent = extractCodeFromResponse(response.content);
161
+ if (!fileContent) {
162
+ return {
163
+ success: false,
164
+ error: 'Failed to extract code from LLM response',
165
+ };
166
+ }
167
+
168
+ // Write the file
169
+ writeFile(step.target_file, fileContent);
170
+
171
+ // Run CI to validate
172
+ const ciResult = await ciProvider.run({
173
+ additions: fileContent.split('\n').length,
174
+ deletions: 0,
175
+ files_touched: [step.target_file],
176
+ });
177
+
178
+ if (!ciResult.passed) {
179
+ // Revert - delete the file
180
+ try {
181
+ const fs = await import('fs');
182
+ fs.unlinkSync(step.target_file);
183
+ } catch {}
184
+ return {
185
+ success: false,
186
+ error: `CI failed: ${ciResult.output}`,
187
+ };
188
+ }
189
+
190
+ // Record trace
191
+ const traceId = await recordCreateTrace(
192
+ step.target_file,
193
+ fileContent,
194
+ response.usage,
195
+ response.model,
196
+ task.id
197
+ );
198
+
199
+ logDebug('Create step completed', {
200
+ file: step.target_file,
201
+ lines: fileContent.split('\n').length,
202
+ traceId,
203
+ });
204
+
205
+ return { success: true, trace_id: traceId };
206
+ }
207
+
208
+ /**
209
+ * Execute a modify mode step (existing file)
210
+ */
211
+ async function executeModifyStep(
212
+ task: Task,
213
+ step: TaskStep
214
+ ): Promise<{ success: boolean; trace_id?: string; error?: string }> {
215
+ if (!fileExists(step.target_file)) {
216
+ return {
217
+ success: false,
218
+ error: `Cannot modify file ${step.target_file} - does not exist`,
219
+ };
220
+ }
221
+
222
+ const originalContent = readFile(step.target_file);
223
+ const gradientBefore = await calculateGradient(step.target_file);
224
+
225
+ // Build prompt for modification
226
+ const systemPrompt = buildModifySystemPrompt(step.mode as Mode);
227
+ const userPrompt = buildModifyUserPrompt(task, step, originalContent);
228
+
229
+ // Call LLM to generate changes
230
+ const response = await callLLM({
231
+ prompt: userPrompt,
232
+ systemPrompt,
233
+ temperature: 0.5,
234
+ maxTokens: 4000,
235
+ });
236
+
237
+ // Extract modified content
238
+ const modifiedContent = extractCodeFromResponse(response.content);
239
+ if (!modifiedContent) {
240
+ return {
241
+ success: false,
242
+ error: 'Failed to extract modified code from LLM response',
243
+ };
244
+ }
245
+
246
+ // Apply changes
247
+ writeFile(step.target_file, modifiedContent);
248
+
249
+ // Calculate change stats
250
+ const changeSet = calculateChanges(originalContent, modifiedContent, step.target_file);
251
+
252
+ // Run CI
253
+ const ciResult = await ciProvider.run(changeSet);
254
+ if (!ciResult.passed) {
255
+ // Revert changes
256
+ writeFile(step.target_file, originalContent);
257
+ return {
258
+ success: false,
259
+ error: `CI failed: ${ciResult.output}`,
260
+ };
261
+ }
262
+
263
+ // Calculate metrics after
264
+ const gradientAfter = await calculateGradient(step.target_file);
265
+
266
+ // Record trace
267
+ const traceId = await recordModifyTrace(
268
+ step.target_file,
269
+ step.mode as Mode,
270
+ gradientBefore,
271
+ gradientAfter,
272
+ changeSet,
273
+ response.usage,
274
+ response.model,
275
+ task.id
276
+ );
277
+
278
+ logDebug('Modify step completed', {
279
+ file: step.target_file,
280
+ mode: step.mode,
281
+ gradientDelta: gradientBefore.score - gradientAfter.score,
282
+ traceId,
283
+ });
284
+
285
+ return { success: true, trace_id: traceId };
286
+ }
287
+
288
+ /**
289
+ * Helper to calculate file metrics (not used in current implementation)
290
+ */
291
+ /*
292
+ async function calculateFileMetrics(filePath: string, allFiles: string[]): Promise<FileMetrics> {
293
+ const [complexity, churn, errorRate, debt, centrality] = await Promise.all([
294
+ calculateComplexity(filePath),
295
+ calculateChurn(filePath),
296
+ calculateErrorRate(filePath),
297
+ calculateDebt(filePath),
298
+ calculateCentrality(filePath),
299
+ ]);
300
+
301
+ return {
302
+ path: filePath,
303
+ complexity: complexity.normalized,
304
+ churn: churn.normalized,
305
+ error_rate: errorRate.normalized,
306
+ debt: debt.normalized,
307
+ centrality: centrality.normalized,
308
+ loc: getLineCount(filePath),
309
+ };
310
+ }
311
+ */
312
+
313
+ /**
314
+ * Get steps grouped by waves (parallelizable groups)
315
+ */
316
+ function getParallelizableSteps(steps: TaskStep[]): TaskStep[][] {
317
+ const waves: TaskStep[][] = [];
318
+ const completed = new Set<number>();
319
+
320
+ while (completed.size < steps.length) {
321
+ // Find steps whose dependencies are all completed
322
+ const ready = steps.filter(
323
+ step =>
324
+ !completed.has(step.order) &&
325
+ step.depends_on.every(dep => completed.has(dep))
326
+ );
327
+
328
+ if (ready.length === 0) {
329
+ throw new Error('Circular dependency detected in task steps');
330
+ }
331
+
332
+ waves.push(ready);
333
+ ready.forEach(step => completed.add(step.order));
334
+ }
335
+
336
+ return waves;
337
+ }
338
+
339
+ /**
340
+ * Build system prompt for create mode
341
+ */
342
+ function buildCreateSystemPrompt(): string {
343
+ return `You are creating a new file as part of a larger task.
344
+
345
+ Output the complete file content wrapped in triple backticks with the language identifier.
346
+
347
+ Example:
348
+ \`\`\`typescript
349
+ // File content here
350
+ \`\`\`
351
+
352
+ Requirements:
353
+ - Include all necessary imports
354
+ - Add appropriate error handling
355
+ - Include JSDoc comments for exported functions
356
+ - Follow TypeScript best practices`;
357
+ }
358
+
359
+ /**
360
+ * Build user prompt for create mode
361
+ */
362
+ function buildCreateUserPrompt(task: Task, step: TaskStep): string {
363
+ return `## Overall Task
364
+ ${task.description}
365
+
366
+ ## This Step
367
+ ${step.description}
368
+
369
+ ## File to Create
370
+ ${step.target_file}
371
+
372
+ ## Requirements
373
+ - Create a working implementation
374
+ - Include basic error handling
375
+ - Add type annotations
376
+ - Follow existing project patterns
377
+
378
+ Generate the complete file content.`;
379
+ }
380
+
381
+ /**
382
+ * Build system prompt for modify mode
383
+ */
384
+ function buildModifySystemPrompt(mode: Mode): string {
385
+ const modeInstructions: Record<Mode, string> = {
386
+ error_reducer: 'Focus on fixing bugs and adding error handling. Do not refactor for style.',
387
+ complexity_reducer: 'Focus on simplifying code structure. Extract functions, reduce nesting.',
388
+ debt_payer: 'Focus on fixing lint issues and improving types. Do not change logic.',
389
+ stabilizer: 'Focus on adding tests and documentation. Do not change implementation.',
390
+ explorer: 'You may challenge assumptions and propose larger changes within constraints.',
391
+ };
392
+
393
+ return `You are modifying an existing file in ${mode} mode.
394
+
395
+ ${modeInstructions[mode]}
396
+
397
+ Output the complete modified file content wrapped in triple backticks.`;
398
+ }
399
+
400
+ /**
401
+ * Build user prompt for modify mode
402
+ */
403
+ function buildModifyUserPrompt(task: Task, step: TaskStep, currentContent: string): string {
404
+ return `## Overall Task
405
+ ${task.description}
406
+
407
+ ## This Step
408
+ ${step.description}
409
+
410
+ ## Current File Content
411
+ \`\`\`typescript
412
+ ${currentContent}
413
+ \`\`\`
414
+
415
+ Modify the file according to the step description and mode constraints.
416
+ Output the complete modified file.`;
417
+ }
418
+
419
+ /**
420
+ * Extract code from LLM response (handle markdown code blocks)
421
+ */
422
+ function extractCodeFromResponse(content: string): string | null {
423
+ // Try to find code in triple backticks
424
+ const codeBlockMatch = content.match(/```(?:typescript|ts|javascript|js)?\n([\s\S]*?)\n```/);
425
+ if (codeBlockMatch) {
426
+ return codeBlockMatch[1];
427
+ }
428
+
429
+ // If no code block found, check if entire content looks like code
430
+ if (content.includes('import') || content.includes('export') || content.includes('function')) {
431
+ return content.trim();
432
+ }
433
+
434
+ return null;
435
+ }
436
+
437
+ /**
438
+ * Calculate changes between original and modified content
439
+ */
440
+ function calculateChanges(
441
+ original: string,
442
+ modified: string,
443
+ filePath: string
444
+ ): ChangeSet {
445
+ const originalLines = original.split('\n');
446
+ const modifiedLines = modified.split('\n');
447
+
448
+ // Simple diff: count added and removed lines
449
+ const additions = modifiedLines.length > originalLines.length
450
+ ? modifiedLines.length - originalLines.length
451
+ : 0;
452
+ const deletions = originalLines.length > modifiedLines.length
453
+ ? originalLines.length - modifiedLines.length
454
+ : 0;
455
+
456
+ return {
457
+ additions,
458
+ deletions,
459
+ files_touched: [filePath],
460
+ };
461
+ }
462
+
463
+ /**
464
+ * Record trace for create step
465
+ */
466
+ async function recordCreateTrace(
467
+ filePath: string,
468
+ content: string,
469
+ usage: { inputTokens: number; outputTokens: number },
470
+ model: string,
471
+ taskId: string
472
+ ): Promise<string> {
473
+ const cost: CostRecord = {
474
+ tokens_in: usage.inputTokens,
475
+ tokens_out: usage.outputTokens,
476
+ model,
477
+ estimated_usd: calculateCost(model, usage.inputTokens, usage.outputTokens),
478
+ };
479
+
480
+ // For create mode, gradient goes from 0 to 0 (no improvement measured)
481
+ const trace = createTraceEvent({
482
+ filePath,
483
+ mode: 'debt_payer', // Create is treated as debt_payer for metrics
484
+ gradientBefore: 0,
485
+ gradientAfter: 0,
486
+ metabolicCost: cost.estimated_usd * 100, // Normalize
487
+ efficiency: 0,
488
+ ciPassed: true,
489
+ changes: {
490
+ additions: content.split('\n').length,
491
+ deletions: 0,
492
+ files_touched: [filePath],
493
+ },
494
+ costRecord: cost,
495
+ notes: ['File created as part of task'],
496
+ taskId,
497
+ });
498
+
499
+ await recordTraceEvent(trace);
500
+ return trace.id;
501
+ }
502
+
503
+ /**
504
+ * Record trace for modify step
505
+ */
506
+ async function recordModifyTrace(
507
+ filePath: string,
508
+ mode: Mode,
509
+ gradientBefore: { score: number },
510
+ gradientAfter: { score: number },
511
+ changes: ChangeSet,
512
+ usage: { inputTokens: number; outputTokens: number },
513
+ model: string,
514
+ taskId: string
515
+ ): Promise<string> {
516
+ const cost: CostRecord = {
517
+ tokens_in: usage.inputTokens,
518
+ tokens_out: usage.outputTokens,
519
+ model,
520
+ estimated_usd: calculateCost(model, usage.inputTokens, usage.outputTokens),
521
+ };
522
+
523
+ const gradientDelta = gradientBefore.score - gradientAfter.score;
524
+ const metabolicCost = cost.estimated_usd * 100; // Normalize
525
+ const efficiency = metabolicCost > 0 ? gradientDelta / metabolicCost : 0;
526
+
527
+ const trace = createTraceEvent({
528
+ filePath,
529
+ mode,
530
+ gradientBefore: gradientBefore.score,
531
+ gradientAfter: gradientAfter.score,
532
+ metabolicCost,
533
+ efficiency,
534
+ ciPassed: true,
535
+ changes,
536
+ costRecord: cost,
537
+ notes: ['Modified as part of task'],
538
+ taskId,
539
+ });
540
+
541
+ await recordTraceEvent(trace);
542
+ return trace.id;
543
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Task System Module
3
+ * Phase 5: Task Planning & Execution
4
+ *
5
+ * Exports all task-related functionality for LLM-based task decomposition,
6
+ * execution tracking, and acceptance criteria validation.
7
+ */
8
+
9
+ export {
10
+ planTask,
11
+ analyzeDependencies,
12
+ identifyRisks,
13
+ } from './planner.js';
14
+
15
+ export {
16
+ executeTask,
17
+ executeStep,
18
+ trackProgress,
19
+ } from './executor.js';
20
+
21
+ export {
22
+ validateAcceptance,
23
+ checkFileExists,
24
+ runTests,
25
+ generateDefaultCriteria,
26
+ canCompleteTask,
27
+ } from './acceptance.js';
28
+
29
+ export {
30
+ storeTask,
31
+ loadTask,
32
+ listTasks,
33
+ listActiveTasks,
34
+ deleteTask,
35
+ updateTaskStatus,
36
+ getTaskHistoryForFile,
37
+ getTaskStatistics,
38
+ } from './storage.js';