claude-mycelium 2.0.0 → 2.1.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 (189) 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/.claude/memory.db +0 -0
  5. package/.claude/settings.local.json +4 -1
  6. package/README.md +81 -235
  7. package/SECURITY.md +145 -0
  8. package/dist/agent/worker.d.ts +8 -0
  9. package/dist/agent/worker.d.ts.map +1 -0
  10. package/dist/agent/worker.js +97 -0
  11. package/dist/agent/worker.js.map +1 -0
  12. package/dist/bin.d.ts +7 -0
  13. package/dist/bin.d.ts.map +1 -0
  14. package/dist/bin.js +11 -0
  15. package/dist/bin.js.map +1 -0
  16. package/dist/cli/cost.d.ts +10 -0
  17. package/dist/cli/cost.d.ts.map +1 -0
  18. package/dist/cli/cost.js +163 -0
  19. package/dist/cli/cost.js.map +1 -0
  20. package/dist/cli/gc.d.ts +10 -0
  21. package/dist/cli/gc.d.ts.map +1 -0
  22. package/dist/cli/gc.js +108 -0
  23. package/dist/cli/gc.js.map +1 -0
  24. package/dist/cli/gradients.d.ts +10 -0
  25. package/dist/cli/gradients.d.ts.map +1 -0
  26. package/dist/cli/gradients.js +69 -0
  27. package/dist/cli/gradients.js.map +1 -0
  28. package/dist/cli/index.d.ts +17 -0
  29. package/dist/cli/index.d.ts.map +1 -0
  30. package/dist/cli/index.js +72 -0
  31. package/dist/cli/index.js.map +1 -0
  32. package/dist/cli/init.d.ts +11 -0
  33. package/dist/cli/init.d.ts.map +1 -0
  34. package/dist/cli/init.js +97 -0
  35. package/dist/cli/init.js.map +1 -0
  36. package/dist/cli/status.d.ts +10 -0
  37. package/dist/cli/status.d.ts.map +1 -0
  38. package/dist/cli/status.js +191 -0
  39. package/dist/cli/status.js.map +1 -0
  40. package/dist/coordination/file-locks.d.ts +42 -0
  41. package/dist/coordination/file-locks.d.ts.map +1 -0
  42. package/dist/coordination/file-locks.js +269 -0
  43. package/dist/coordination/file-locks.js.map +1 -0
  44. package/dist/coordination/index.d.ts +4 -0
  45. package/dist/coordination/index.d.ts.map +1 -1
  46. package/dist/coordination/index.js +4 -0
  47. package/dist/coordination/index.js.map +1 -1
  48. package/dist/coordination/inhibitors.d.ts +84 -0
  49. package/dist/coordination/inhibitors.d.ts.map +1 -0
  50. package/dist/coordination/inhibitors.js +290 -0
  51. package/dist/coordination/inhibitors.js.map +1 -0
  52. package/dist/coordination/process-manager.d.ts +73 -0
  53. package/dist/coordination/process-manager.d.ts.map +1 -0
  54. package/dist/coordination/process-manager.js +144 -0
  55. package/dist/coordination/process-manager.js.map +1 -0
  56. package/dist/core/agent-executor.d.ts.map +1 -1
  57. package/dist/core/agent-executor.js +28 -10
  58. package/dist/core/agent-executor.js.map +1 -1
  59. package/dist/core/change-applier.d.ts +29 -5
  60. package/dist/core/change-applier.d.ts.map +1 -1
  61. package/dist/core/change-applier.js +254 -24
  62. package/dist/core/change-applier.js.map +1 -1
  63. package/dist/core/signals/churn.d.ts.map +1 -1
  64. package/dist/core/signals/churn.js +6 -4
  65. package/dist/core/signals/churn.js.map +1 -1
  66. package/dist/core/signals/debt.d.ts.map +1 -1
  67. package/dist/core/signals/debt.js +4 -3
  68. package/dist/core/signals/debt.js.map +1 -1
  69. package/dist/cost/cost-tracker.d.ts.map +1 -1
  70. package/dist/cost/cost-tracker.js +2 -0
  71. package/dist/cost/cost-tracker.js.map +1 -1
  72. package/dist/gc/index.d.ts +17 -0
  73. package/dist/gc/index.d.ts.map +1 -0
  74. package/dist/gc/index.js +17 -0
  75. package/dist/gc/index.js.map +1 -0
  76. package/dist/gc/runner.d.ts +39 -0
  77. package/dist/gc/runner.d.ts.map +1 -0
  78. package/dist/gc/runner.js +277 -0
  79. package/dist/gc/runner.js.map +1 -0
  80. package/dist/gc/trace-compactor.d.ts +31 -0
  81. package/dist/gc/trace-compactor.d.ts.map +1 -0
  82. package/dist/gc/trace-compactor.js +162 -0
  83. package/dist/gc/trace-compactor.js.map +1 -0
  84. package/dist/index.d.ts +5 -1
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +6 -1
  87. package/dist/index.js.map +1 -1
  88. package/dist/prompts/index.d.ts +2 -1
  89. package/dist/prompts/index.d.ts.map +1 -1
  90. package/dist/prompts/index.js.map +1 -1
  91. package/dist/quarantine/explorer.d.ts +65 -0
  92. package/dist/quarantine/explorer.d.ts.map +1 -0
  93. package/dist/quarantine/explorer.js +175 -0
  94. package/dist/quarantine/explorer.js.map +1 -0
  95. package/dist/quarantine/index.d.ts +7 -0
  96. package/dist/quarantine/index.d.ts.map +1 -0
  97. package/dist/quarantine/index.js +7 -0
  98. package/dist/quarantine/index.js.map +1 -0
  99. package/dist/quarantine/manager.d.ts +75 -0
  100. package/dist/quarantine/manager.d.ts.map +1 -0
  101. package/dist/quarantine/manager.js +275 -0
  102. package/dist/quarantine/manager.js.map +1 -0
  103. package/dist/task/acceptance.d.ts +29 -0
  104. package/dist/task/acceptance.d.ts.map +1 -0
  105. package/dist/task/acceptance.js +228 -0
  106. package/dist/task/acceptance.js.map +1 -0
  107. package/dist/task/executor.d.ts +30 -0
  108. package/dist/task/executor.d.ts.map +1 -0
  109. package/dist/task/executor.js +429 -0
  110. package/dist/task/executor.js.map +1 -0
  111. package/dist/task/index.d.ts +12 -0
  112. package/dist/task/index.d.ts.map +1 -0
  113. package/dist/task/index.js +12 -0
  114. package/dist/task/index.js.map +1 -0
  115. package/dist/task/planner.d.ts +21 -0
  116. package/dist/task/planner.d.ts.map +1 -0
  117. package/dist/task/planner.js +253 -0
  118. package/dist/task/planner.js.map +1 -0
  119. package/dist/task/storage.d.ts +46 -0
  120. package/dist/task/storage.d.ts.map +1 -0
  121. package/dist/task/storage.js +266 -0
  122. package/dist/task/storage.js.map +1 -0
  123. package/dist/trace/trace-event.d.ts +2 -18
  124. package/dist/trace/trace-event.d.ts.map +1 -1
  125. package/dist/trace/trace-event.js +6 -6
  126. package/dist/trace/trace-event.js.map +1 -1
  127. package/dist/utils/file-utils.d.ts.map +1 -1
  128. package/dist/utils/file-utils.js +54 -15
  129. package/dist/utils/file-utils.js.map +1 -1
  130. package/docs/PHASE5_IMPLEMENTATION.md +237 -0
  131. package/docs/PHASES-3-7-COMPLETE.md +177 -0
  132. package/docs/PHASE_4_COMPLETE.md +135 -0
  133. package/docs/PHASE_7_DELIVERABLES.md +295 -0
  134. package/docs/PHASE_7_IMPLEMENTATION.md +306 -0
  135. package/docs/PHASE_7_SUMMARY.txt +195 -0
  136. package/docs/RELEASE-NOTES-v2.1.md +213 -0
  137. package/docs/ROADMAP.md +64 -57
  138. package/docs/SECURITY-AUDIT.md +387 -0
  139. package/docs/SNAPSHOT.md +59 -32
  140. package/docs/implementation/phase3-summary.md +220 -0
  141. package/package.json +19 -11
  142. package/src/agent/worker.ts +111 -0
  143. package/src/bin.ts +13 -0
  144. package/src/cli/cost.ts +210 -0
  145. package/src/cli/gc.ts +138 -0
  146. package/src/cli/gradients.ts +95 -0
  147. package/src/cli/index.ts +79 -0
  148. package/src/cli/init.ts +139 -0
  149. package/src/cli/status.ts +218 -0
  150. package/src/coordination/file-locks.ts +300 -0
  151. package/src/coordination/index.ts +4 -0
  152. package/src/coordination/inhibitors.ts +345 -0
  153. package/src/coordination/process-manager.ts +199 -0
  154. package/src/core/agent-executor.ts +20 -4
  155. package/src/core/signals/churn.ts +8 -5
  156. package/src/core/signals/debt.ts +4 -3
  157. package/src/cost/cost-tracker.ts +2 -0
  158. package/src/gc/index.ts +17 -0
  159. package/src/gc/runner.ts +314 -0
  160. package/src/gc/trace-compactor.ts +187 -0
  161. package/src/index.ts +7 -1
  162. package/src/prompts/index.ts +2 -1
  163. package/src/quarantine/explorer.ts +234 -0
  164. package/src/quarantine/index.ts +7 -0
  165. package/src/quarantine/manager.ts +336 -0
  166. package/src/task/acceptance.ts +267 -0
  167. package/src/task/executor.ts +538 -0
  168. package/src/task/index.ts +38 -0
  169. package/src/task/planner.ts +294 -0
  170. package/src/task/storage.ts +332 -0
  171. package/src/trace/trace-event.ts +7 -26
  172. package/src/utils/file-utils.ts +61 -15
  173. package/tests/cli/gc.test.ts +206 -0
  174. package/tests/cli/init.test.ts +181 -0
  175. package/tests/cli/status.test.ts +282 -0
  176. package/tests/coordination/file-locks.test.ts +196 -0
  177. package/tests/coordination/inhibitors.test.ts +459 -0
  178. package/tests/coordination/integration.test.ts +195 -0
  179. package/tests/coordination/process-manager.test.ts +165 -0
  180. package/tests/gc/trace-compactor.test.ts +245 -0
  181. package/tests/integration/phase-7.test.ts +145 -0
  182. package/tests/quarantine/explorer.test.ts +381 -0
  183. package/tests/quarantine/manager.test.ts +399 -0
  184. package/tests/security/command-injection.test.ts +88 -0
  185. package/tests/security/path-traversal.test.ts +103 -0
  186. package/tests/task/acceptance.test.ts +411 -0
  187. package/tests/task/executor.test.ts +421 -0
  188. package/tests/task/planner.test.ts +359 -0
  189. package/tsconfig.json +2 -2
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Acceptance Criteria Validation
3
+ * Per ROADMAP §Phase 5 Week 6 Day 5-6: Acceptance Criteria
4
+ *
5
+ * Validates task completion against acceptance criteria including
6
+ * file existence, test execution, lint checks, and custom validation.
7
+ */
8
+
9
+ import { Task, AcceptanceCriterion } from '../types/index.js';
10
+ import { fileExists } from '../utils/file-utils.js';
11
+ import { logDebug, logError } from '../utils/logger.js';
12
+ import { exec } from 'child_process';
13
+ import { promisify } from 'util';
14
+
15
+ const execAsync = promisify(exec);
16
+
17
+ /**
18
+ * Validate all acceptance criteria for a task
19
+ */
20
+ export async function validateAcceptance(task: Task): Promise<boolean> {
21
+ logDebug('Validating acceptance criteria', {
22
+ taskId: task.id,
23
+ criteriaCount: task.acceptance_criteria.length,
24
+ });
25
+
26
+ let allMet = true;
27
+
28
+ for (const criterion of task.acceptance_criteria) {
29
+ const met = await validateCriterion(criterion);
30
+ criterion.met = met;
31
+
32
+ if (!met) {
33
+ allMet = false;
34
+ logDebug('Acceptance criterion not met', {
35
+ taskId: task.id,
36
+ type: criterion.type,
37
+ description: criterion.description,
38
+ });
39
+ }
40
+ }
41
+
42
+ logDebug('Acceptance validation complete', {
43
+ taskId: task.id,
44
+ allMet,
45
+ metCount: task.acceptance_criteria.filter(c => c.met).length,
46
+ });
47
+
48
+ return allMet;
49
+ }
50
+
51
+ /**
52
+ * Validate a single acceptance criterion
53
+ */
54
+ async function validateCriterion(criterion: AcceptanceCriterion): Promise<boolean> {
55
+ try {
56
+ switch (criterion.type) {
57
+ case 'file_exists':
58
+ return await checkFileExists(criterion.check);
59
+
60
+ case 'test_passes':
61
+ return await runTests(criterion.check);
62
+
63
+ case 'no_lint_errors':
64
+ return await checkLintErrors(criterion.check);
65
+
66
+ case 'custom':
67
+ return await runCustomValidation(criterion.check);
68
+
69
+ default:
70
+ logError('Unknown criterion type', new Error('Invalid type'), {
71
+ type: criterion.type,
72
+ });
73
+ return false;
74
+ }
75
+ } catch (error) {
76
+ const errorObj = error instanceof Error ? error : new Error(String(error));
77
+ logError('Criterion validation failed', errorObj, {
78
+ type: criterion.type,
79
+ check: criterion.check,
80
+ });
81
+ return false;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Check if a file exists
87
+ */
88
+ export async function checkFileExists(filePath: string): Promise<boolean> {
89
+ const exists = fileExists(filePath);
90
+ logDebug('File existence check', { filePath, exists });
91
+ return exists;
92
+ }
93
+
94
+ /**
95
+ * Run specific tests and check if they pass
96
+ */
97
+ export async function runTests(testPattern: string): Promise<boolean> {
98
+ logDebug('Running tests', { pattern: testPattern });
99
+
100
+ try {
101
+ // Run vitest with specific pattern
102
+ const command = `npm test -- --run ${testPattern}`;
103
+ const { stdout, stderr } = await execAsync(command, {
104
+ timeout: 60000, // 60 second timeout
105
+ });
106
+
107
+ // Check for test failures in output
108
+ const output = stdout + stderr;
109
+ const hasFailed = output.includes('FAILED') ||
110
+ output.includes('failed') ||
111
+ output.includes('Error:');
112
+
113
+ logDebug('Test execution result', {
114
+ pattern: testPattern,
115
+ passed: !hasFailed,
116
+ });
117
+
118
+ return !hasFailed;
119
+ } catch (error) {
120
+ // exec throws on non-zero exit code
121
+ const errorObj = error instanceof Error ? error : new Error(String(error));
122
+ logError('Test execution failed', errorObj, { pattern: testPattern });
123
+ return false;
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Check if file has lint errors
129
+ */
130
+ async function checkLintErrors(filePath: string): Promise<boolean> {
131
+ logDebug('Checking lint errors', { filePath });
132
+
133
+ try {
134
+ // Run eslint on specific file
135
+ const command = `npx eslint ${filePath} --format json`;
136
+ const { stdout } = await execAsync(command, {
137
+ timeout: 30000, // 30 second timeout
138
+ });
139
+
140
+ // Parse eslint JSON output
141
+ const results = JSON.parse(stdout);
142
+
143
+ // Check if there are any errors
144
+ const totalErrors = results.reduce(
145
+ (sum: number, result: any) => sum + result.errorCount,
146
+ 0
147
+ );
148
+
149
+ const noErrors = totalErrors === 0;
150
+ logDebug('Lint check result', {
151
+ filePath,
152
+ errors: totalErrors,
153
+ passed: noErrors,
154
+ });
155
+
156
+ return noErrors;
157
+ } catch (error) {
158
+ // eslint returns non-zero exit code when errors found
159
+ // Try to parse the output to get error count
160
+ if (error instanceof Error && 'stdout' in error) {
161
+ try {
162
+ const results = JSON.parse((error as any).stdout);
163
+ const totalErrors = results.reduce(
164
+ (sum: number, result: any) => sum + result.errorCount,
165
+ 0
166
+ );
167
+ return totalErrors === 0;
168
+ } catch {
169
+ // Failed to parse, assume errors
170
+ return false;
171
+ }
172
+ }
173
+
174
+ const errorObj = error instanceof Error ? error : new Error(String(error));
175
+ logError('Lint check failed', errorObj, { filePath });
176
+ return false;
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Run custom validation command
182
+ */
183
+ async function runCustomValidation(command: string): Promise<boolean> {
184
+ logDebug('Running custom validation', { command });
185
+
186
+ try {
187
+ await execAsync(command, {
188
+ timeout: 60000, // 60 second timeout
189
+ });
190
+
191
+ logDebug('Custom validation passed', { command });
192
+ return true;
193
+ } catch (error) {
194
+ const errorObj = error instanceof Error ? error : new Error(String(error));
195
+ logError('Custom validation failed', errorObj, { command });
196
+ return false;
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Generate default acceptance criteria for a task
202
+ */
203
+ export function generateDefaultCriteria(task: Task): AcceptanceCriterion[] {
204
+ const criteria: AcceptanceCriterion[] = [];
205
+
206
+ // If task plan exists, generate criteria based on files
207
+ if (task.plan) {
208
+ // Check that all created files exist
209
+ const createSteps = task.plan.steps.filter(s => s.mode === 'create');
210
+ for (const step of createSteps) {
211
+ criteria.push({
212
+ description: `File ${step.target_file} exists`,
213
+ type: 'file_exists',
214
+ check: step.target_file,
215
+ met: false,
216
+ });
217
+
218
+ // If it's a test file, add a test_passes criterion
219
+ if (step.target_file.includes('.test.')) {
220
+ criteria.push({
221
+ description: `Tests in ${step.target_file} pass`,
222
+ type: 'test_passes',
223
+ check: step.target_file,
224
+ met: false,
225
+ });
226
+ }
227
+ }
228
+
229
+ // Add lint check for all touched files
230
+ const allFiles = new Set([
231
+ ...createSteps.map(s => s.target_file),
232
+ ...task.plan.steps.filter(s => s.mode !== 'create').map(s => s.target_file),
233
+ ]);
234
+
235
+ for (const file of allFiles) {
236
+ // Only check non-test files for lint
237
+ if (!file.includes('.test.')) {
238
+ criteria.push({
239
+ description: `No lint errors in ${file}`,
240
+ type: 'no_lint_errors',
241
+ check: file,
242
+ met: false,
243
+ });
244
+ }
245
+ }
246
+ }
247
+
248
+ return criteria;
249
+ }
250
+
251
+ /**
252
+ * Check if task can be marked as completed
253
+ */
254
+ export function canCompleteTask(task: Task): boolean {
255
+ // All steps must be completed
256
+ if (task.steps_completed < task.steps_total) {
257
+ return false;
258
+ }
259
+
260
+ // All acceptance criteria must be met
261
+ if (task.acceptance_criteria.length > 0) {
262
+ return task.acceptance_criteria.every(c => c.met);
263
+ }
264
+
265
+ // If no criteria defined, task is complete when all steps done
266
+ return true;
267
+ }