@zoebuildsai/trace 1.5.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 (130) hide show
  1. package/.gitignore +115 -0
  2. package/.trace/progress.json +22 -0
  3. package/README.md +466 -0
  4. package/RELEASE-NOTES-1.5.0.md +410 -0
  5. package/STATUS.md +245 -0
  6. package/dist/auto-commit.d.ts +66 -0
  7. package/dist/auto-commit.d.ts.map +1 -0
  8. package/dist/auto-commit.js +180 -0
  9. package/dist/auto-commit.js.map +1 -0
  10. package/dist/cli.d.ts +7 -0
  11. package/dist/cli.d.ts.map +1 -0
  12. package/dist/cli.js +246 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/commands.d.ts +46 -0
  15. package/dist/commands.d.ts.map +1 -0
  16. package/dist/commands.js +256 -0
  17. package/dist/commands.js.map +1 -0
  18. package/dist/diff.d.ts +23 -0
  19. package/dist/diff.d.ts.map +1 -0
  20. package/dist/diff.js +106 -0
  21. package/dist/diff.js.map +1 -0
  22. package/dist/github.d.ts.map +1 -0
  23. package/dist/github.js.map +1 -0
  24. package/dist/index-cache.d.ts +35 -0
  25. package/dist/index-cache.d.ts.map +1 -0
  26. package/dist/index-cache.js +114 -0
  27. package/dist/index-cache.js.map +1 -0
  28. package/dist/index.d.ts +15 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +25 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/storage.d.ts +45 -0
  33. package/dist/storage.d.ts.map +1 -0
  34. package/dist/storage.js +151 -0
  35. package/dist/storage.js.map +1 -0
  36. package/dist/sync.d.ts +60 -0
  37. package/dist/sync.js +184 -0
  38. package/dist/tags.d.ts +85 -0
  39. package/dist/tags.d.ts.map +1 -0
  40. package/dist/tags.js +219 -0
  41. package/dist/tags.js.map +1 -0
  42. package/dist/types.d.ts +102 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +6 -0
  45. package/dist/types.js.map +1 -0
  46. package/docs/.nojekyll +0 -0
  47. package/docs/README.md +73 -0
  48. package/docs/_config.yml +2 -0
  49. package/docs/index.html +960 -0
  50. package/docs-website/package.json +20 -0
  51. package/jest.config.js +21 -0
  52. package/package.json +50 -0
  53. package/scripts/init.ts +290 -0
  54. package/src/agent-audit.ts +270 -0
  55. package/src/agent-checkout.ts +227 -0
  56. package/src/agent-coordination.ts +318 -0
  57. package/src/async-queue.ts +203 -0
  58. package/src/auto-branching.ts +279 -0
  59. package/src/auto-commit.ts +166 -0
  60. package/src/cherry-pick.ts +252 -0
  61. package/src/chunked-upload.ts +224 -0
  62. package/src/cli-v2.ts +335 -0
  63. package/src/cli.ts +318 -0
  64. package/src/cliff-detection.ts +232 -0
  65. package/src/commands.ts +267 -0
  66. package/src/commit-hash-system.ts +351 -0
  67. package/src/compression.ts +176 -0
  68. package/src/conflict-resolution-ui.ts +277 -0
  69. package/src/conflict-visualization.ts +238 -0
  70. package/src/diff-formatter.ts +184 -0
  71. package/src/diff.ts +124 -0
  72. package/src/distributed-coordination.ts +273 -0
  73. package/src/git-interop.ts +316 -0
  74. package/src/index-cache.ts +88 -0
  75. package/src/index.ts +38 -0
  76. package/src/merge-engine.ts +143 -0
  77. package/src/message-search.ts +370 -0
  78. package/src/performance-monitoring.ts +236 -0
  79. package/src/rebase.ts +327 -0
  80. package/src/rollback.ts +215 -0
  81. package/src/semantic-grouping.ts +245 -0
  82. package/src/stage-area.ts +324 -0
  83. package/src/stash.ts +278 -0
  84. package/src/storage.ts +131 -0
  85. package/src/sync.ts +205 -0
  86. package/src/tags.ts +244 -0
  87. package/src/types.ts +119 -0
  88. package/src/webhooks.ts +119 -0
  89. package/src/workspace-isolation.ts +298 -0
  90. package/tests/auto-commit.test.ts +308 -0
  91. package/tests/checkout.test.ts +136 -0
  92. package/tests/commit.test.ts +118 -0
  93. package/tests/diff.test.ts +191 -0
  94. package/tests/github.test.ts +94 -0
  95. package/tests/integration.test.ts +267 -0
  96. package/tests/log.test.ts +125 -0
  97. package/tests/phase2-integration.test.ts +370 -0
  98. package/tests/storage.test.ts +167 -0
  99. package/tests/tags.test.ts +477 -0
  100. package/tests/types.test.ts +75 -0
  101. package/tests/v1.1/agent-audit.test.ts +472 -0
  102. package/tests/v1.1/agent-coordination.test.ts +308 -0
  103. package/tests/v1.1/async-queue.test.ts +253 -0
  104. package/tests/v1.1/comprehensive.test.ts +521 -0
  105. package/tests/v1.1/diff-formatter.test.ts +238 -0
  106. package/tests/v1.1/integration.test.ts +389 -0
  107. package/tests/v1.1/onboarding.test.ts +365 -0
  108. package/tests/v1.1/rollback.test.ts +370 -0
  109. package/tests/v1.1/semantic-grouping.test.ts +230 -0
  110. package/tests/v1.2/chunked-upload.test.ts +301 -0
  111. package/tests/v1.2/cliff-detection.test.ts +272 -0
  112. package/tests/v1.2/commit-hash-system.test.ts +288 -0
  113. package/tests/v1.2/compression.test.ts +220 -0
  114. package/tests/v1.2/conflict-visualization.test.ts +263 -0
  115. package/tests/v1.2/distributed.test.ts +261 -0
  116. package/tests/v1.2/performance-monitoring.test.ts +328 -0
  117. package/tests/v1.3/auto-branching.test.ts +270 -0
  118. package/tests/v1.3/message-search.test.ts +264 -0
  119. package/tests/v1.3/stage-area.test.ts +330 -0
  120. package/tests/v1.3/stash-rebase-cherry-pick.test.ts +361 -0
  121. package/tests/v1.4/cli.test.ts +171 -0
  122. package/tests/v1.4/conflict-resolution-advanced.test.ts +429 -0
  123. package/tests/v1.4/conflict-resolution-ui.test.ts +286 -0
  124. package/tests/v1.4/workspace-isolation-advanced.test.ts +382 -0
  125. package/tests/v1.4/workspace-isolation.test.ts +268 -0
  126. package/tests/v1.5/agent-coordination.real.test.ts +401 -0
  127. package/tests/v1.5/cli-v2.test.ts +354 -0
  128. package/tests/v1.5/git-interop.real.test.ts +358 -0
  129. package/tests/v1.5/integration-testing.real.test.ts +440 -0
  130. package/tsconfig.json +26 -0
@@ -0,0 +1,440 @@
1
+ /**
2
+ * Real Integration Testing - Trace v1.5.0
3
+ * Testing actual workflows with real agent scenarios
4
+ * This validates end-to-end functionality
5
+ */
6
+
7
+ import { TraceCliv2 } from '../../src/cli-v2';
8
+ import { WorkspaceIsolation } from '../../src/workspace-isolation';
9
+ import { AgentCoordination } from '../../src/agent-coordination';
10
+ import { ConflictResolutionUI } from '../../src/conflict-resolution-ui';
11
+
12
+ describe('Trace v1.5.0 - Real Integration Testing', () => {
13
+ let cli: TraceCliv2;
14
+ let isolation: WorkspaceIsolation;
15
+ let coordination: AgentCoordination;
16
+
17
+ beforeEach(() => {
18
+ cli = new TraceCliv2();
19
+ isolation = new WorkspaceIsolation('/test/workspace', true);
20
+ coordination = new AgentCoordination({
21
+ allowParallel: true,
22
+ maxConcurrent: 10,
23
+ lockTimeout: 5000,
24
+ conflictStrategy: 'block',
25
+ });
26
+ });
27
+
28
+ describe('Real Agent Workflow 1: Simple Collaborative Edit', () => {
29
+ test('two agents edit different files in parallel', async () => {
30
+ // Agent A starts
31
+ const initResult = await cli.execute('trace init /workspace');
32
+ expect(initResult.success).toBe(true);
33
+
34
+ // Agent A edits file 1
35
+ const lockA = await cli.execute('trace lock src/api.ts');
36
+ expect(lockA.success).toBe(true);
37
+
38
+ const commitA = await cli.execute('trace commit -m "feat: add user endpoint"');
39
+ expect(commitA.success).toBe(true);
40
+
41
+ // Agent B edits different file in parallel
42
+ const lockB = await cli.execute('trace lock src/utils.ts');
43
+ expect(lockB.success).toBe(true);
44
+
45
+ const commitB = await cli.execute('trace commit -m "refactor: optimize helpers"');
46
+ expect(commitB.success).toBe(true);
47
+
48
+ // Both unlock
49
+ const unlockA = await cli.execute('trace unlock src/api.ts');
50
+ const unlockB = await cli.execute('trace unlock src/utils.ts');
51
+ expect(unlockA.success).toBe(true);
52
+ expect(unlockB.success).toBe(true);
53
+
54
+ // Both push
55
+ const pushA = await cli.execute('trace push origin main');
56
+ const pushB = await cli.execute('trace push origin main');
57
+ expect(pushA.success).toBe(true);
58
+ expect(pushB.success).toBe(true);
59
+ });
60
+ });
61
+
62
+ describe('Real Agent Workflow 2: Serialized File Editing', () => {
63
+ test('two agents queue for same file, second waits', async () => {
64
+ // Agent A locks shared file
65
+ const taskA = coordination.registerTask('agent-a', ['src/shared.ts'], 2);
66
+ expect(taskA.canStart).toBe(true);
67
+
68
+ // Agent A gets lock
69
+ const lockA = coordination.requestLock('src/shared.ts', 'agent-a');
70
+ expect(lockA.locked).toBe(true);
71
+
72
+ // Agent B tries same file, gets blocked
73
+ const taskB = coordination.registerTask('agent-b', ['src/shared.ts'], 1);
74
+ expect(taskB.canStart).toBe(false);
75
+ expect(taskB.blockedBy).toContain(taskA.taskId);
76
+
77
+ // Agent A completes
78
+ const unlockA = coordination.releaseLock('src/shared.ts', 'agent-a');
79
+ expect(unlockA).toBe(true);
80
+
81
+ coordination.completeTask(taskA.taskId);
82
+
83
+ // Now Agent B should be able to proceed
84
+ const lockB = coordination.requestLock('src/shared.ts', 'agent-b');
85
+ expect(lockB.locked).toBe(true);
86
+ });
87
+ });
88
+
89
+ describe('Real Agent Workflow 3: Conflict Detection & Resolution', () => {
90
+ test('detect conflict, resolve it, commit', async () => {
91
+ // Both agents try to edit same file
92
+ const taskA = coordination.registerTask('agent-a', ['src/main.ts', 'src/api.ts'], 2);
93
+ const taskB = coordination.registerTask('agent-b', ['src/main.ts', 'src/utils.ts'], 1);
94
+
95
+ // A can start
96
+ expect(taskA.canStart).toBe(true);
97
+
98
+ // B is blocked (conflict on main.ts)
99
+ expect(taskB.canStart).toBe(false);
100
+
101
+ // Detect collision
102
+ const collisions = coordination.getBlockedTasks();
103
+ expect(collisions.length).toBeGreaterThan(0);
104
+
105
+ // Show stats
106
+ const stats = coordination.getStats();
107
+ expect(stats.blocked).toBe(1);
108
+ expect(stats.executing).toBe(1);
109
+
110
+ // A completes
111
+ coordination.completeTask(taskA.taskId);
112
+
113
+ // B auto-unblocks
114
+ const unblocked = coordination.getBlockedTasks();
115
+ expect(unblocked.length).toBe(0);
116
+
117
+ // B can now proceed
118
+ const statusB = coordination.getTaskStatus(taskB.taskId);
119
+ expect(statusB?.status).toBe('executing');
120
+
121
+ // Resolve the conflict (if happened)
122
+ const resolveResult = await cli.execute('trace resolve src/main.ts --strategy ours');
123
+ expect(resolveResult.success).toBe(true);
124
+
125
+ // Commit after resolution
126
+ const commitResult = await cli.execute('trace commit -m "fix: resolved merge conflict"');
127
+ expect(commitResult.success).toBe(true);
128
+ });
129
+ });
130
+
131
+ describe('Real Agent Workflow 4: Security & Validation', () => {
132
+ test('prevent accidental .env commit, validate before push', async () => {
133
+ // Agent tries to commit .env (dangerous!)
134
+ const envCheck = isolation.isSafeToCommit('.env');
135
+ expect(envCheck.safe).toBe(false);
136
+ expect(envCheck.violations.length).toBeGreaterThan(0);
137
+
138
+ // Check the violation reason exists
139
+ expect(envCheck.violations[0].reason).toBeTruthy();
140
+ expect(envCheck.violations[0].reason.length).toBeGreaterThan(0);
141
+
142
+ // Try to commit safe file
143
+ const safeCheck = isolation.isSafeToCommit('src/api.ts');
144
+ expect(safeCheck.safe).toBe(true);
145
+ expect(safeCheck.violations.length).toBe(0);
146
+
147
+ // Validate multiple files before push
148
+ const files = ['src/api.ts', 'src/utils.ts', 'tests/api.test.ts'];
149
+ const pushValidation = isolation.validateGitPush(files);
150
+ expect(pushValidation.canPush).toBe(true);
151
+
152
+ // Try with dangerous files
153
+ const dangerousFiles = ['src/api.ts', '.env', 'secrets.json'];
154
+ const unsafeValidation = isolation.validateGitPush(dangerousFiles);
155
+ expect(unsafeValidation.canPush).toBe(false);
156
+ expect(unsafeValidation.violations.length).toBeGreaterThan(0);
157
+ });
158
+ });
159
+
160
+ describe('Real Agent Workflow 5: Complex Task Dependencies', () => {
161
+ test('three agents with task dependencies (A→B→C)', async () => {
162
+ // Agent A: works on types (Task 1)
163
+ const taskA = coordination.registerTask('agent-a', ['src/types.ts'], 3);
164
+ expect(taskA.canStart).toBe(true);
165
+
166
+ // Agent B: works on API, depends on types (Task 2)
167
+ const taskB = coordination.registerTask('agent-b', ['src/api.ts', 'src/types.ts'], 2);
168
+ expect(taskB.canStart).toBe(false); // Blocked by A
169
+ expect(taskB.blockedBy).toContain(taskA.taskId);
170
+
171
+ // Agent C: works on tests, depends on both (Task 3)
172
+ const taskC = coordination.registerTask('agent-c', ['src/types.ts', 'src/api.ts', 'tests/api.test.ts'], 1);
173
+ expect(taskC.canStart).toBe(false); // Blocked by A and B
174
+ expect(taskC.blockedBy?.length).toBeGreaterThanOrEqual(1);
175
+
176
+ // Get suggested order
177
+ const order = coordination.suggestOrder();
178
+ const aIdx = order.indexOf(taskA.taskId);
179
+ const bIdx = order.indexOf(taskB.taskId);
180
+ const cIdx = order.indexOf(taskC.taskId);
181
+
182
+ // A should come before B before C
183
+ expect(aIdx).toBeLessThan(bIdx);
184
+ expect(bIdx).toBeLessThan(cIdx);
185
+
186
+ // Complete A
187
+ const unblocked1 = coordination.completeTask(taskA.taskId);
188
+ expect(unblocked1.unblocked).toContain(taskB.taskId);
189
+
190
+ // Verify B is now executing
191
+ const statusB = coordination.getTaskStatus(taskB.taskId);
192
+ expect(statusB?.status).toBe('executing');
193
+
194
+ // Complete B
195
+ const unblocked2 = coordination.completeTask(taskB.taskId);
196
+ expect(unblocked2.unblocked).toContain(taskC.taskId);
197
+
198
+ // Now C is executing
199
+ const statusC = coordination.getTaskStatus(taskC.taskId);
200
+ expect(statusC?.status).toBe('executing');
201
+
202
+ // Complete C
203
+ const unblocked3 = coordination.completeTask(taskC.taskId);
204
+ expect(unblocked3.success).toBe(true);
205
+ });
206
+ });
207
+
208
+ describe('Real Agent Workflow 6: High Concurrency Scenario', () => {
209
+ test('10 agents working simultaneously on different files', async () => {
210
+ const agents = Array.from({ length: 10 }, (_, i) => `agent-${i}`);
211
+ const files = Array.from({ length: 10 }, (_, i) => `src/module${i}.ts`);
212
+
213
+ // All agents register tasks simultaneously
214
+ const tasks = agents.map((agent, i) => {
215
+ return coordination.registerTask(agent, [files[i]], 10 - i);
216
+ });
217
+
218
+ // All should start (no conflicts)
219
+ tasks.forEach(task => {
220
+ expect(task.canStart).toBe(true);
221
+ });
222
+
223
+ // All should get locks
224
+ files.forEach((file, i) => {
225
+ const lock = coordination.requestLock(file, agents[i]);
226
+ expect(lock.locked).toBe(true);
227
+ });
228
+
229
+ // Get stats
230
+ const stats = coordination.getStats();
231
+ expect(stats.executing).toBe(10);
232
+ expect(stats.blocked).toBe(0);
233
+ expect(stats.currentLocks).toBe(10);
234
+
235
+ // Complete all tasks
236
+ for (let i = 0; i < tasks.length; i++) {
237
+ const result = coordination.completeTask(tasks[i].taskId);
238
+ expect(result.success).toBe(true);
239
+ }
240
+
241
+ // All should be done
242
+ const finalStats = coordination.getStats();
243
+ expect(finalStats.completed).toBe(10);
244
+ expect(finalStats.executing).toBe(0);
245
+ });
246
+ });
247
+
248
+ describe('Real Agent Workflow 7: Conflict Resolution UI', () => {
249
+ test('render conflict and suggest resolution', async () => {
250
+ const ours = `export function getUserName(id: string) {
251
+ return db.query('SELECT name FROM users WHERE id = ?', [id]);
252
+ }`;
253
+
254
+ const theirs = `export async function getUserName(id: string): Promise<string> {
255
+ const result = await db.query('SELECT name FROM users WHERE id = ?', [id]);
256
+ return result[0].name;
257
+ }`;
258
+
259
+ const base = `export function getUserName(id: string) {
260
+ return db.query('SELECT name FROM users WHERE id = ?', [id]);
261
+ }`;
262
+
263
+ // Get suggestion
264
+ const suggestion = ConflictResolutionUI.suggestResolution(ours, theirs, base);
265
+ expect(suggestion.suggestion).toBeDefined();
266
+ expect(suggestion.confidence).toBeGreaterThan(0);
267
+ expect(suggestion.reason).toBeDefined();
268
+
269
+ // Render HTML UI
270
+ const html = ConflictResolutionUI.renderHTML('src/users.ts', ours, theirs, base);
271
+ expect(html).toContain('Conflict Resolution');
272
+ expect(html).toContain('getUserName');
273
+
274
+ // Render terminal UI
275
+ const terminal = ConflictResolutionUI.renderTerminal(
276
+ 'src/users.ts',
277
+ ours.split('\n'),
278
+ theirs.split('\n'),
279
+ base.split('\n')
280
+ );
281
+ expect(terminal).toContain('RESOLUTION OPTIONS');
282
+
283
+ // Parse conflict markers (real git format)
284
+ const conflicted = `<<<<<<< HEAD
285
+ export function getUserName(id: string) {
286
+ return db.query('SELECT name FROM users WHERE id = ?', [id]);
287
+ }
288
+ =======
289
+ export async function getUserName(id: string): Promise<string> {
290
+ const result = await db.query('SELECT name FROM users WHERE id = ?', [id]);
291
+ return result[0].name;
292
+ }
293
+ >>>>>>> feature/async-queries`;
294
+
295
+ const parsed = ConflictResolutionUI.parseConflictMarkers(conflicted);
296
+ expect(parsed.hasConflicts).toBe(true);
297
+ expect(parsed.markers.length).toBeGreaterThan(0);
298
+ });
299
+ });
300
+
301
+ describe('Real Agent Workflow 8: Multi-Agent Coordination State', () => {
302
+ test('complete workflow with coordination state display', async () => {
303
+ // Register 5 tasks with varying priorities
304
+ const task1 = coordination.registerTask('agent-1', ['file1.ts'], 5);
305
+ const task2 = coordination.registerTask('agent-2', ['file1.ts'], 4); // Blocks on 1
306
+ const task3 = coordination.registerTask('agent-3', ['file2.ts', 'file1.ts'], 3); // Blocks on 1&2
307
+ const task4 = coordination.registerTask('agent-4', ['file2.ts'], 2);
308
+ const task5 = coordination.registerTask('agent-5', ['file3.ts'], 1);
309
+
310
+ // Get current state
311
+ let state = coordination.formatState();
312
+ expect(state).toContain('AGENT COORDINATION STATE');
313
+ expect(state).toContain('BLOCKED TASKS');
314
+
315
+ // Get stats
316
+ let stats = coordination.getStats();
317
+ expect(stats.executing).toBeGreaterThan(0);
318
+ expect(stats.blocked).toBeGreaterThan(0);
319
+
320
+ // Complete task 1
321
+ coordination.completeTask(task1.taskId);
322
+ stats = coordination.getStats();
323
+ // Task 2 should unblock, so blocked count decreases
324
+ expect(stats.blocked).toBeLessThanOrEqual(2);
325
+
326
+ // Complete task 4
327
+ coordination.completeTask(task4.taskId);
328
+ stats = coordination.getStats();
329
+
330
+ // Complete remaining
331
+ coordination.completeTask(task2.taskId);
332
+ coordination.completeTask(task3.taskId);
333
+ coordination.completeTask(task5.taskId);
334
+
335
+ // All done
336
+ stats = coordination.getStats();
337
+ expect(stats.completed).toBe(5);
338
+ expect(stats.executing).toBe(0);
339
+ expect(stats.blocked).toBe(0);
340
+
341
+ // View final state
342
+ state = coordination.formatState();
343
+ expect(state).toContain('5 total');
344
+ });
345
+ });
346
+
347
+ describe('Performance Validation (Real Workloads)', () => {
348
+ test('process 100 tasks under 1 second', () => {
349
+ const start = Date.now();
350
+
351
+ for (let i = 0; i < 100; i++) {
352
+ const file = `file${i % 20}.ts`;
353
+ coordination.registerTask(`agent-${i % 10}`, [file], 100 - i);
354
+ }
355
+
356
+ const elapsed = Date.now() - start;
357
+ expect(elapsed).toBeLessThan(1000);
358
+ });
359
+
360
+ test('detect conflicts in 100 tasks under 100ms', () => {
361
+ const tasks = [];
362
+ for (let i = 0; i < 100; i++) {
363
+ tasks.push(coordination.registerTask(`agent-${i % 5}`, [`file${i % 10}.ts`], i));
364
+ }
365
+
366
+ const start = Date.now();
367
+ const blocked = coordination.getBlockedTasks();
368
+ const elapsed = Date.now() - start;
369
+
370
+ expect(elapsed).toBeLessThan(100);
371
+ // Check if there are blocked tasks (may be 0 if all different files)
372
+ expect(Array.isArray(blocked)).toBe(true);
373
+ });
374
+
375
+ test('file lock operations under 1ms each', () => {
376
+ const start = Date.now();
377
+
378
+ for (let i = 0; i < 1000; i++) {
379
+ const file = `file${i % 50}.ts`;
380
+ const agent = `agent-${i % 10}`;
381
+ coordination.requestLock(file, agent);
382
+ }
383
+
384
+ const elapsed = Date.now() - start;
385
+ expect(elapsed).toBeLessThan(100); // 1000 operations < 100ms
386
+ });
387
+ });
388
+
389
+ describe('End-to-End Sanity Checks', () => {
390
+ test('CLI commands respond immediately', async () => {
391
+ const commands = [
392
+ 'trace help',
393
+ 'trace status',
394
+ 'trace log',
395
+ 'trace audit',
396
+ 'trace validate',
397
+ ];
398
+
399
+ for (const cmd of commands) {
400
+ const start = Date.now();
401
+ const result = await cli.execute(cmd);
402
+ const elapsed = Date.now() - start;
403
+
404
+ expect(result.success).toBe(true);
405
+ expect(elapsed).toBeLessThan(100); // <100ms per command
406
+ }
407
+ });
408
+
409
+ test('security checks work', () => {
410
+ const dangerousFiles = ['.env', 'secrets.json', 'private.key', 'password.txt'];
411
+ const safeFiles = ['src/api.ts', 'tests/main.test.ts', 'docs/API.md'];
412
+
413
+ dangerousFiles.forEach(file => {
414
+ const result = isolation.isSafeToCommit(file);
415
+ expect(result.safe).toBe(false);
416
+ });
417
+
418
+ safeFiles.forEach(file => {
419
+ const result = isolation.isSafeToCommit(file);
420
+ expect(result.safe).toBe(true);
421
+ });
422
+ });
423
+
424
+ test('coordination prevents collisions', () => {
425
+ // Register A for file X
426
+ const a = coordination.registerTask('agent-a', ['shared.ts'], 2);
427
+ expect(a.canStart).toBe(true);
428
+
429
+ // Register B for same file
430
+ const b = coordination.registerTask('agent-b', ['shared.ts'], 1);
431
+ expect(b.canStart).toBe(false);
432
+
433
+ // Verify collision detected
434
+ expect(b.blockedBy).toContain(a.taskId);
435
+
436
+ // Cleanup
437
+ coordination.completeTask(a.taskId);
438
+ });
439
+ });
440
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "lib": ["ES2020"],
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true,
16
+ "noImplicitAny": true,
17
+ "strictNullChecks": true,
18
+ "strictFunctionTypes": true,
19
+ "strictBindCallApply": true,
20
+ "strictPropertyInitialization": true,
21
+ "noImplicitThis": true,
22
+ "alwaysStrict": true
23
+ },
24
+ "include": ["src/**/*"],
25
+ "exclude": ["node_modules", "dist", "tests"]
26
+ }