@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,472 @@
1
+ /**
2
+ * Agent Audit Tests (TDD)
3
+ * Collision detection, audit trails, conflict resolution
4
+ */
5
+
6
+ import { AgentAudit, AuditEntry, FileConflict } from '../../src/agent-audit';
7
+
8
+ describe('AgentAudit', () => {
9
+ let audit: AgentAudit;
10
+
11
+ beforeEach(() => {
12
+ audit = new AgentAudit();
13
+ });
14
+
15
+ describe('Commit Recording', () => {
16
+ test('should record commit from agent', () => {
17
+ const entry = {
18
+ commitId: 'commit-1',
19
+ agentId: 'agent-a',
20
+ agentName: 'Agent Alpha',
21
+ files: ['src/feature.ts'],
22
+ message: 'Add feature',
23
+ signature: 'sig-1',
24
+ };
25
+
26
+ audit.recordCommit(entry);
27
+ const history = audit.getAgentHistory('agent-a');
28
+
29
+ expect(history).toHaveLength(1);
30
+ expect(history[0].agentId).toBe('agent-a');
31
+ });
32
+
33
+ test('should track file ownership', () => {
34
+ audit.recordCommit({
35
+ commitId: 'commit-1',
36
+ agentId: 'agent-a',
37
+ agentName: 'Agent Alpha',
38
+ files: ['src/file.ts'],
39
+ message: 'Edit file',
40
+ signature: 'sig-1',
41
+ });
42
+
43
+ const fileHistory = audit.getFileHistory('src/file.ts');
44
+ expect(fileHistory).toHaveLength(1);
45
+ expect(fileHistory[0].agentId).toBe('agent-a');
46
+ });
47
+
48
+ test('should handle multiple commits from same agent', () => {
49
+ for (let i = 0; i < 5; i++) {
50
+ audit.recordCommit({
51
+ commitId: `commit-${i}`,
52
+ agentId: 'agent-a',
53
+ agentName: 'Agent Alpha',
54
+ files: [`src/file${i}.ts`],
55
+ message: `Edit ${i}`,
56
+ signature: `sig-${i}`,
57
+ });
58
+ }
59
+
60
+ const history = audit.getAgentHistory('agent-a');
61
+ expect(history).toHaveLength(5);
62
+ });
63
+ });
64
+
65
+ describe('Collision Detection', () => {
66
+ test('should detect collision when multiple agents edit same file', () => {
67
+ audit.recordCommit({
68
+ commitId: 'commit-1',
69
+ agentId: 'agent-a',
70
+ agentName: 'Agent Alpha',
71
+ files: ['src/shared.ts'],
72
+ message: 'Agent A edits',
73
+ signature: 'sig-1',
74
+ });
75
+
76
+ const collision = audit.detectCollisions('src/shared.ts', ['agent-a', 'agent-b']);
77
+
78
+ expect(collision).not.toBeNull();
79
+ expect(collision?.agents).toContain('agent-a');
80
+ expect(collision?.agents).toContain('agent-b');
81
+ });
82
+
83
+ test('should not report collision for single agent', () => {
84
+ audit.recordCommit({
85
+ commitId: 'commit-1',
86
+ agentId: 'agent-a',
87
+ agentName: 'Agent Alpha',
88
+ files: ['src/file.ts'],
89
+ message: 'Edit',
90
+ signature: 'sig-1',
91
+ });
92
+
93
+ const collision = audit.detectCollisions('src/file.ts', ['agent-a']);
94
+
95
+ expect(collision).toBeNull();
96
+ });
97
+
98
+ test('should track collision metadata', () => {
99
+ audit.recordCommit({
100
+ commitId: 'commit-1',
101
+ agentId: 'agent-a',
102
+ agentName: 'Agent Alpha',
103
+ files: ['shared.ts'],
104
+ message: 'Edit',
105
+ signature: 'sig-1',
106
+ });
107
+
108
+ const collision = audit.detectCollisions('shared.ts', ['agent-b', 'agent-c']);
109
+
110
+ expect(collision?.path).toBe('shared.ts');
111
+ expect(collision?.lastModifiedBy).toBe('agent-a');
112
+ expect(collision?.resolution).toBe('pending');
113
+ });
114
+ });
115
+
116
+ describe('Audit Trail', () => {
117
+ test('should show full history of file edits', () => {
118
+ const file = 'src/important.ts';
119
+
120
+ audit.recordCommit({
121
+ commitId: 'commit-1',
122
+ agentId: 'agent-a',
123
+ agentName: 'Agent Alpha',
124
+ files: [file],
125
+ message: 'Initial',
126
+ signature: 'sig-1',
127
+ });
128
+
129
+ audit.recordCommit({
130
+ commitId: 'commit-2',
131
+ agentId: 'agent-b',
132
+ agentName: 'Agent Beta',
133
+ files: [file],
134
+ message: 'Update',
135
+ signature: 'sig-2',
136
+ });
137
+
138
+ audit.recordCommit({
139
+ commitId: 'commit-3',
140
+ agentId: 'agent-a',
141
+ agentName: 'Agent Alpha',
142
+ files: [file],
143
+ message: 'Final',
144
+ signature: 'sig-3',
145
+ });
146
+
147
+ const history = audit.getFileHistory(file);
148
+
149
+ expect(history).toHaveLength(3);
150
+ expect(history[0].agentId).toBe('agent-a');
151
+ expect(history[1].agentId).toBe('agent-b');
152
+ expect(history[2].agentId).toBe('agent-a');
153
+ });
154
+
155
+ test('should identify last editor', () => {
156
+ audit.recordCommit({
157
+ commitId: 'c1',
158
+ agentId: 'agent-a',
159
+ agentName: 'A',
160
+ files: ['file.ts'],
161
+ message: 'm1',
162
+ signature: 's1',
163
+ });
164
+
165
+ audit.recordCommit({
166
+ commitId: 'c2',
167
+ agentId: 'agent-b',
168
+ agentName: 'B',
169
+ files: ['file.ts'],
170
+ message: 'm2',
171
+ signature: 's2',
172
+ });
173
+
174
+ const history = audit.getFileHistory('file.ts');
175
+ const lastEditor = history[history.length - 1].agentId;
176
+
177
+ expect(lastEditor).toBe('agent-b');
178
+ });
179
+ });
180
+
181
+ describe('Conflict Resolution', () => {
182
+ test('should resolve using timestamp priority', () => {
183
+ const file = 'conflict.ts';
184
+
185
+ audit.recordCommit({
186
+ commitId: 'c1',
187
+ agentId: 'agent-a',
188
+ agentName: 'A',
189
+ files: [file],
190
+ message: 'm',
191
+ signature: 's',
192
+ });
193
+
194
+ const resolution = audit.resolveConflict(
195
+ file,
196
+ 'agent-a',
197
+ 'agent-b',
198
+ 'timestamp-priority'
199
+ );
200
+
201
+ expect(resolution.result).toBe('resolved');
202
+ expect(resolution.strategy).toBe('timestamp-priority');
203
+ });
204
+
205
+ test('should resolve using agent priority', () => {
206
+ const resolution = audit.resolveConflict(
207
+ 'file.ts',
208
+ 'agent-z',
209
+ 'agent-a',
210
+ 'agent-priority'
211
+ );
212
+
213
+ expect(resolution.result).toBe('resolved');
214
+ expect(resolution.strategy).toBe('agent-priority');
215
+ });
216
+
217
+ test('should flag manual merge as requires-review', () => {
218
+ const resolution = audit.resolveConflict(
219
+ 'complex.ts',
220
+ 'agent-a',
221
+ 'agent-b',
222
+ 'manual-merge'
223
+ );
224
+
225
+ expect(resolution.result).toBe('requires-review');
226
+ });
227
+
228
+ test('should suggest merge strategy based on history', () => {
229
+ for (let i = 0; i < 5; i++) {
230
+ audit.recordCommit({
231
+ commitId: `c${i}`,
232
+ agentId: 'agent-a',
233
+ agentName: 'A',
234
+ files: ['file.ts'],
235
+ message: 'm',
236
+ signature: 's',
237
+ });
238
+ }
239
+
240
+ audit.recordCommit({
241
+ commitId: 'c6',
242
+ agentId: 'agent-b',
243
+ agentName: 'B',
244
+ files: ['file.ts'],
245
+ message: 'm',
246
+ signature: 's',
247
+ });
248
+
249
+ const suggested = audit.suggestMergeStrategy('file.ts', 'agent-a', 'agent-b');
250
+
251
+ expect(suggested).toBe('agent-priority');
252
+ });
253
+ });
254
+
255
+ describe('Audit Report', () => {
256
+ test('should generate comprehensive audit report', () => {
257
+ audit.recordCommit({
258
+ commitId: 'c1',
259
+ agentId: 'agent-a',
260
+ agentName: 'Alpha',
261
+ files: ['src/a.ts', 'src/b.ts'],
262
+ message: 'Two files',
263
+ signature: 's1',
264
+ });
265
+
266
+ audit.recordCommit({
267
+ commitId: 'c2',
268
+ agentId: 'agent-b',
269
+ agentName: 'Beta',
270
+ files: ['src/c.ts'],
271
+ message: 'One file',
272
+ signature: 's2',
273
+ });
274
+
275
+ const report = audit.generateAuditReport();
276
+
277
+ expect(report.totalCommits).toBe(2);
278
+ expect(report.agentCount).toBe(2);
279
+ expect((report.agents as any)['agent-a'].commits).toBe(1);
280
+ expect((report.agents as any)['agent-b'].commits).toBe(1);
281
+ });
282
+
283
+ test('should show files changed per agent', () => {
284
+ audit.recordCommit({
285
+ commitId: 'c1',
286
+ agentId: 'agent-a',
287
+ agentName: 'A',
288
+ files: ['f1.ts', 'f2.ts', 'f3.ts'],
289
+ message: 'm',
290
+ signature: 's',
291
+ });
292
+
293
+ const report = audit.generateAuditReport();
294
+ const agentStats = (report.agents as any)['agent-a'];
295
+
296
+ expect(agentStats.filesChanged).toHaveLength(3);
297
+ });
298
+ });
299
+
300
+ describe('File Locking', () => {
301
+ test('should allow locking new file', () => {
302
+ const canLock = audit.lockFile('new-file.ts', 'agent-a');
303
+
304
+ expect(canLock).toBe(true);
305
+ });
306
+
307
+ test('should prevent lock if recently edited', () => {
308
+ audit.recordCommit({
309
+ commitId: 'c1',
310
+ agentId: 'agent-a',
311
+ agentName: 'A',
312
+ files: ['file.ts'],
313
+ message: 'm',
314
+ signature: 's',
315
+ });
316
+
317
+ const canLock = audit.lockFile('file.ts', 'agent-b', 30000);
318
+
319
+ expect(canLock).toBe(false);
320
+ });
321
+
322
+ test('should allow lock after timeout', (done) => {
323
+ audit.recordCommit({
324
+ commitId: 'c1',
325
+ agentId: 'agent-a',
326
+ agentName: 'A',
327
+ files: ['file.ts'],
328
+ message: 'm',
329
+ signature: 's',
330
+ });
331
+
332
+ setTimeout(() => {
333
+ const canLock = audit.lockFile('file.ts', 'agent-b', 10); // 10ms timeout
334
+
335
+ expect(canLock).toBe(true);
336
+ done();
337
+ }, 50);
338
+ });
339
+ });
340
+
341
+ describe('Signature Verification', () => {
342
+ test('should verify valid signature', () => {
343
+ audit.recordCommit({
344
+ commitId: 'commit-1',
345
+ agentId: 'agent-a',
346
+ agentName: 'A',
347
+ files: ['file.ts'],
348
+ message: 'm',
349
+ signature: 'valid-sig',
350
+ });
351
+
352
+ const isValid = audit.verifySignature('commit-1', 'valid-sig', 'pubkey');
353
+
354
+ expect(isValid).toBe(true);
355
+ });
356
+
357
+ test('should reject invalid signature', () => {
358
+ audit.recordCommit({
359
+ commitId: 'commit-1',
360
+ agentId: 'agent-a',
361
+ agentName: 'A',
362
+ files: ['file.ts'],
363
+ message: 'm',
364
+ signature: 'valid-sig',
365
+ });
366
+
367
+ const isValid = audit.verifySignature('commit-1', 'wrong-sig', 'pubkey');
368
+
369
+ expect(isValid).toBe(false);
370
+ });
371
+
372
+ test('should reject unknown commit', () => {
373
+ const isValid = audit.verifySignature('unknown', 'sig', 'pubkey');
374
+
375
+ expect(isValid).toBe(false);
376
+ });
377
+ });
378
+
379
+ describe('Statistics', () => {
380
+ test('should calculate accurate statistics', () => {
381
+ for (let i = 0; i < 3; i++) {
382
+ audit.recordCommit({
383
+ commitId: `c${i}`,
384
+ agentId: `agent-${i % 2}`,
385
+ agentName: `Agent ${i % 2}`,
386
+ files: [`file${i}-1.ts`, `file${i}-2.ts`],
387
+ message: 'm',
388
+ signature: 's',
389
+ });
390
+ }
391
+
392
+ const stats = audit.getStats();
393
+
394
+ expect(stats.totalCommits).toBe(3);
395
+ expect(stats.uniqueAgents).toBe(2);
396
+ expect(stats.uniqueFiles).toBe(6);
397
+ });
398
+
399
+ test('should calculate average commit size', () => {
400
+ audit.recordCommit({
401
+ commitId: 'c1',
402
+ agentId: 'a',
403
+ agentName: 'A',
404
+ files: ['f1.ts', 'f2.ts'],
405
+ message: 'm',
406
+ signature: 's',
407
+ });
408
+
409
+ audit.recordCommit({
410
+ commitId: 'c2',
411
+ agentId: 'a',
412
+ agentName: 'A',
413
+ files: ['f3.ts', 'f4.ts', 'f5.ts'],
414
+ message: 'm',
415
+ signature: 's',
416
+ });
417
+
418
+ const stats = audit.getStats();
419
+
420
+ expect(stats.averageCommitSize).toBe(2.5);
421
+ });
422
+ });
423
+
424
+ describe('Multi-Agent Scenarios', () => {
425
+ test('should track parallel edits from multiple agents', () => {
426
+ const agents = ['agent-1', 'agent-2', 'agent-3'];
427
+
428
+ agents.forEach((agent, i) => {
429
+ audit.recordCommit({
430
+ commitId: `c${i}`,
431
+ agentId: agent,
432
+ agentName: `Agent ${i}`,
433
+ files: [`file${i}.ts`],
434
+ message: `Edit by ${agent}`,
435
+ signature: `sig${i}`,
436
+ });
437
+ });
438
+
439
+ const report = audit.generateAuditReport();
440
+
441
+ expect(report.agentCount).toBe(3);
442
+ expect(report.totalCommits).toBe(3);
443
+ });
444
+
445
+ test('should handle agent editing different files', () => {
446
+ audit.recordCommit({
447
+ commitId: 'c1',
448
+ agentId: 'agent-a',
449
+ agentName: 'A',
450
+ files: ['a.ts', 'b.ts'],
451
+ message: 'm',
452
+ signature: 's',
453
+ });
454
+
455
+ audit.recordCommit({
456
+ commitId: 'c2',
457
+ agentId: 'agent-b',
458
+ agentName: 'B',
459
+ files: ['c.ts', 'd.ts'],
460
+ message: 'm',
461
+ signature: 's',
462
+ });
463
+
464
+ const report = audit.generateAuditReport();
465
+ const aStats = (report.agents as any)['agent-a'];
466
+ const bStats = (report.agents as any)['agent-b'];
467
+
468
+ expect(aStats.filesChanged).toHaveLength(2);
469
+ expect(bStats.filesChanged).toHaveLength(2);
470
+ });
471
+ });
472
+ });