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,381 @@
1
+ /**
2
+ * Tests for Explorer Mode Spawning
3
+ * Validates probability calculations and target selection
4
+ */
5
+
6
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
7
+ import * as fs from 'fs';
8
+ import {
9
+ shouldSpawnExplorer,
10
+ selectExplorerTarget,
11
+ calculateExplorerProbability,
12
+ shouldSpawnExplorerForFile,
13
+ getExplorerConfig,
14
+ formatExplorerInstructions,
15
+ } from '../../src/quarantine/explorer.js';
16
+ import { addToQuarantine } from '../../src/quarantine/manager.js';
17
+ import type { Gradient } from '../../src/types/index.js';
18
+ import type { TraceEvent } from '../../src/trace/trace-event.js';
19
+
20
+ describe('Explorer Mode', () => {
21
+ let TEST_DIR: string;
22
+
23
+ beforeEach(() => {
24
+ // Create unique test directory for each test
25
+ TEST_DIR = `.agent-meta-test-${Date.now()}-${Math.random().toString(36).slice(2)}`;
26
+
27
+ if (!fs.existsSync(TEST_DIR)) {
28
+ fs.mkdirSync(TEST_DIR, { recursive: true });
29
+ }
30
+
31
+ process.env.TEST_META_DIR = TEST_DIR;
32
+ });
33
+
34
+ afterEach(() => {
35
+ // Cleanup test files
36
+ if (fs.existsSync(TEST_DIR)) {
37
+ fs.rmSync(TEST_DIR, { recursive: true, force: true });
38
+ }
39
+ // Clean up environment
40
+ delete process.env.TEST_META_DIR;
41
+ });
42
+
43
+ const createMockTrace = (efficiency: number): TraceEvent => ({
44
+ id: `trace-${Date.now()}-${Math.random()}`,
45
+ timestamp: new Date().toISOString(),
46
+ agent_id: 'test-agent',
47
+ file_path: 'test.ts',
48
+ mode: 'error_reducer',
49
+ gradient_before: 0.5,
50
+ gradient_after: 0.48,
51
+ gradient_delta: 0.02,
52
+ changes_made: [],
53
+ tokens_used: 1000,
54
+ cost_usd: 0.01,
55
+ duration_ms: 1000,
56
+ success: true,
57
+ efficiency,
58
+ ci_passed: true,
59
+ changes: {
60
+ additions: 1,
61
+ deletions: 1,
62
+ files_touched: ['test.ts'],
63
+ },
64
+ cost: {
65
+ tokens_in: 500,
66
+ tokens_out: 500,
67
+ model: 'claude-sonnet-4',
68
+ estimated_usd: 0.01,
69
+ },
70
+ });
71
+
72
+ describe('calculateExplorerProbability', () => {
73
+ it('should calculate 10% probability for centrality 0.0', () => {
74
+ const prob = calculateExplorerProbability(0.0);
75
+ expect(prob).toBeCloseTo(0.1, 3);
76
+ });
77
+
78
+ it('should calculate 15% probability for centrality 0.5', () => {
79
+ const prob = calculateExplorerProbability(0.5);
80
+ expect(prob).toBeCloseTo(0.15, 3);
81
+ });
82
+
83
+ it('should calculate 20% probability for centrality 1.0', () => {
84
+ const prob = calculateExplorerProbability(1.0);
85
+ expect(prob).toBeCloseTo(0.2, 3);
86
+ });
87
+
88
+ it('should follow formula: 0.1 × (1 + centrality)', () => {
89
+ const centrality = 0.75;
90
+ const expected = 0.1 * (1 + centrality);
91
+ const actual = calculateExplorerProbability(centrality);
92
+ expect(actual).toBeCloseTo(expected, 5);
93
+ });
94
+ });
95
+
96
+ describe('shouldSpawnExplorer', () => {
97
+ it('should return false with insufficient data (<10 traces)', async () => {
98
+ const getRecentTraces = async (limit: number) => {
99
+ return Array(5)
100
+ .fill(0)
101
+ .map(() => createMockTrace(0.1));
102
+ };
103
+
104
+ const result = await shouldSpawnExplorer(getRecentTraces);
105
+ expect(result).toBe(false);
106
+ });
107
+
108
+ it('should have low probability with high efficiency (>=0.3)', async () => {
109
+ const getRecentTraces = async (limit: number) => {
110
+ return Array(20)
111
+ .fill(0)
112
+ .map(() => createMockTrace(0.35)); // High efficiency
113
+ };
114
+
115
+ // Run multiple times to check probability
116
+ let spawnCount = 0;
117
+ const iterations = 100;
118
+
119
+ for (let i = 0; i < iterations; i++) {
120
+ if (await shouldSpawnExplorer(getRecentTraces)) {
121
+ spawnCount++;
122
+ }
123
+ }
124
+
125
+ const probability = spawnCount / iterations;
126
+ // Should be around 5% (base probability)
127
+ expect(probability).toBeLessThan(0.15); // Allow some variance
128
+ });
129
+
130
+ it('should have medium probability with medium efficiency (0.15)', async () => {
131
+ const getRecentTraces = async (limit: number) => {
132
+ return Array(20)
133
+ .fill(0)
134
+ .map(() => createMockTrace(0.15)); // Medium efficiency
135
+ };
136
+
137
+ // Run multiple times to check probability
138
+ let spawnCount = 0;
139
+ const iterations = 200;
140
+
141
+ for (let i = 0; i < iterations; i++) {
142
+ if (await shouldSpawnExplorer(getRecentTraces)) {
143
+ spawnCount++;
144
+ }
145
+ }
146
+
147
+ const probability = spawnCount / iterations;
148
+ // Should be around 15% (halfway to max)
149
+ expect(probability).toBeGreaterThan(0.08); // Lower bound
150
+ expect(probability).toBeLessThan(0.22); // Upper bound
151
+ });
152
+
153
+ it('should have high probability with low efficiency (0.0)', async () => {
154
+ const getRecentTraces = async (limit: number) => {
155
+ return Array(20)
156
+ .fill(0)
157
+ .map(() => createMockTrace(0.0)); // Zero efficiency
158
+ };
159
+
160
+ // Run multiple times to check probability
161
+ let spawnCount = 0;
162
+ const iterations = 200;
163
+
164
+ for (let i = 0; i < iterations; i++) {
165
+ if (await shouldSpawnExplorer(getRecentTraces)) {
166
+ spawnCount++;
167
+ }
168
+ }
169
+
170
+ const probability = spawnCount / iterations;
171
+ // Should be around 25% (max probability)
172
+ expect(probability).toBeGreaterThan(0.18); // Lower bound
173
+ expect(probability).toBeLessThan(0.32); // Upper bound
174
+ });
175
+ });
176
+
177
+ describe('selectExplorerTarget', () => {
178
+ const mockIsFileLocked = async (file: string) => false;
179
+
180
+ it('should prioritize quarantined files with attempts remaining', async () => {
181
+ // Add quarantined file
182
+ await addToQuarantine({
183
+ file: 'quarantined.ts',
184
+ quarantined_at: new Date().toISOString(),
185
+ reason: 'Test',
186
+ attempts_before_quarantine: 10,
187
+ explorer_attempts: 0,
188
+ max_explorer_attempts: 3,
189
+ });
190
+
191
+ const gradients: Gradient[] = [
192
+ {
193
+ file: 'high-gradient.ts',
194
+ score: 0.9,
195
+ baseScore: 0.9,
196
+ impactMultiplier: 1.0,
197
+ efficiencyPenalty: 1.0,
198
+ dominantSignal: 'complexity',
199
+ },
200
+ {
201
+ file: 'quarantined.ts',
202
+ score: 0.5,
203
+ baseScore: 0.5,
204
+ impactMultiplier: 1.0,
205
+ efficiencyPenalty: 1.0,
206
+ dominantSignal: 'error_rate',
207
+ },
208
+ ];
209
+
210
+ const target = await selectExplorerTarget(gradients, mockIsFileLocked);
211
+
212
+ // Should pick quarantined file even though high-gradient.ts has higher score
213
+ expect(target).toBe('quarantined.ts');
214
+ });
215
+
216
+ it('should skip quarantined files with exhausted attempts', async () => {
217
+ // Add quarantined file with exhausted attempts
218
+ await addToQuarantine({
219
+ file: 'exhausted.ts',
220
+ quarantined_at: new Date().toISOString(),
221
+ reason: 'Test',
222
+ attempts_before_quarantine: 10,
223
+ explorer_attempts: 3, // Exhausted
224
+ max_explorer_attempts: 3,
225
+ });
226
+
227
+ const gradients: Gradient[] = [
228
+ {
229
+ file: 'high-gradient.ts',
230
+ score: 0.9,
231
+ baseScore: 0.9,
232
+ impactMultiplier: 1.0,
233
+ efficiencyPenalty: 1.0,
234
+ dominantSignal: 'complexity',
235
+ },
236
+ {
237
+ file: 'exhausted.ts',
238
+ score: 0.8,
239
+ baseScore: 0.8,
240
+ impactMultiplier: 1.0,
241
+ efficiencyPenalty: 1.0,
242
+ dominantSignal: 'error_rate',
243
+ },
244
+ ];
245
+
246
+ const target = await selectExplorerTarget(gradients, mockIsFileLocked);
247
+
248
+ // Should pick high-gradient file since quarantined one is exhausted
249
+ expect(target).toBe('high-gradient.ts');
250
+ });
251
+
252
+ it('should pick highest gradient among non-quarantined files', async () => {
253
+ const gradients: Gradient[] = [
254
+ {
255
+ file: 'low.ts',
256
+ score: 0.3,
257
+ baseScore: 0.3,
258
+ impactMultiplier: 1.0,
259
+ efficiencyPenalty: 1.0,
260
+ dominantSignal: 'churn',
261
+ },
262
+ {
263
+ file: 'high.ts',
264
+ score: 0.9,
265
+ baseScore: 0.9,
266
+ impactMultiplier: 1.0,
267
+ efficiencyPenalty: 1.0,
268
+ dominantSignal: 'complexity',
269
+ },
270
+ {
271
+ file: 'medium.ts',
272
+ score: 0.6,
273
+ baseScore: 0.6,
274
+ impactMultiplier: 1.0,
275
+ efficiencyPenalty: 1.0,
276
+ dominantSignal: 'debt',
277
+ },
278
+ ];
279
+
280
+ const target = await selectExplorerTarget(gradients, mockIsFileLocked);
281
+ expect(target).toBe('high.ts');
282
+ });
283
+
284
+ it('should skip locked files', async () => {
285
+ const mockIsFileLockedSelective = async (file: string) => file === 'locked.ts';
286
+
287
+ const gradients: Gradient[] = [
288
+ {
289
+ file: 'locked.ts',
290
+ score: 0.9,
291
+ baseScore: 0.9,
292
+ impactMultiplier: 1.0,
293
+ efficiencyPenalty: 1.0,
294
+ dominantSignal: 'complexity',
295
+ },
296
+ {
297
+ file: 'unlocked.ts',
298
+ score: 0.7,
299
+ baseScore: 0.7,
300
+ impactMultiplier: 1.0,
301
+ efficiencyPenalty: 1.0,
302
+ dominantSignal: 'error_rate',
303
+ },
304
+ ];
305
+
306
+ const target = await selectExplorerTarget(gradients, mockIsFileLockedSelective);
307
+ expect(target).toBe('unlocked.ts');
308
+ });
309
+
310
+ it('should return null if no valid targets', async () => {
311
+ const mockAllLocked = async (file: string) => true;
312
+
313
+ const gradients: Gradient[] = [
314
+ {
315
+ file: 'locked1.ts',
316
+ score: 0.9,
317
+ baseScore: 0.9,
318
+ impactMultiplier: 1.0,
319
+ efficiencyPenalty: 1.0,
320
+ dominantSignal: 'complexity',
321
+ },
322
+ ];
323
+
324
+ const target = await selectExplorerTarget(gradients, mockAllLocked);
325
+ expect(target).toBeNull();
326
+ });
327
+ });
328
+
329
+ describe('shouldSpawnExplorerForFile', () => {
330
+ it('should be probabilistic based on centrality', () => {
331
+ // Run many times to verify probability distribution
332
+ const centrality = 0.5; // Should give ~15% probability
333
+ let spawnCount = 0;
334
+ const iterations = 1000;
335
+
336
+ for (let i = 0; i < iterations; i++) {
337
+ if (shouldSpawnExplorerForFile(centrality)) {
338
+ spawnCount++;
339
+ }
340
+ }
341
+
342
+ const probability = spawnCount / iterations;
343
+ expect(probability).toBeGreaterThan(0.10); // Lower bound
344
+ expect(probability).toBeLessThan(0.20); // Upper bound
345
+ });
346
+ });
347
+
348
+ describe('getExplorerConfig', () => {
349
+ it('should return explorer configuration', () => {
350
+ const config = getExplorerConfig();
351
+
352
+ expect(config.temperature).toBeGreaterThan(0);
353
+ expect(config.systemPromptAddition).toContain('EXPLORER');
354
+ expect(config.systemPromptAddition).toContain('creative');
355
+ });
356
+
357
+ it('should have higher temperature than normal modes', () => {
358
+ const config = getExplorerConfig();
359
+ // Normal modes typically use 0.3-0.5, explorer should be higher
360
+ expect(config.temperature).toBeGreaterThanOrEqual(0.7);
361
+ });
362
+ });
363
+
364
+ describe('formatExplorerInstructions', () => {
365
+ it('should format instructions for quarantined file', () => {
366
+ const instructions = formatExplorerInstructions('test.ts', true, 2);
367
+
368
+ expect(instructions).toContain('QUARANTINED');
369
+ expect(instructions).toContain('test.ts');
370
+ expect(instructions).toContain('multiple');
371
+ });
372
+
373
+ it('should format instructions for non-quarantined file', () => {
374
+ const instructions = formatExplorerInstructions('test.ts', false, 0);
375
+
376
+ expect(instructions).toContain('Creative Exploration');
377
+ expect(instructions).toContain('test.ts');
378
+ expect(instructions).not.toContain('QUARANTINED');
379
+ });
380
+ });
381
+ });