@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,267 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { TraceCommands } from '../src/commands';
5
+
6
+ describe('Integration Tests', () => {
7
+ let tmpDir: string;
8
+ let commands: TraceCommands;
9
+ let memoryDir: string;
10
+
11
+ beforeEach(() => {
12
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'memory-git-'));
13
+ const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'home-'));
14
+ process.env.HOME = homeDir;
15
+ memoryDir = path.join(homeDir, '.openclaw/memory');
16
+ fs.mkdirSync(memoryDir, { recursive: true });
17
+ commands = new TraceCommands(tmpDir);
18
+ });
19
+
20
+ afterEach(() => {
21
+ fs.rmSync(tmpDir, { recursive: true });
22
+ fs.rmSync(process.env.HOME || '', { recursive: true });
23
+ });
24
+
25
+ it('should commit and log history', () => {
26
+ // Create initial file
27
+ fs.writeFileSync(path.join(memoryDir, 'file1.txt'), 'content1');
28
+ const hash1 = commands.commit('Initial commit');
29
+
30
+ // Update file
31
+ fs.writeFileSync(path.join(memoryDir, 'file1.txt'), 'updated content');
32
+ const hash2 = commands.commit('Update file');
33
+
34
+ const log = commands.log();
35
+ expect(log.length).toBeGreaterThanOrEqual(2);
36
+ expect(log[0].hash).toBe(hash2);
37
+ expect(log[1].hash).toBe(hash1);
38
+ });
39
+
40
+ it('should limit log results', () => {
41
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v1');
42
+ commands.commit('Commit 1');
43
+
44
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v2');
45
+ commands.commit('Commit 2');
46
+
47
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v3');
48
+ commands.commit('Commit 3');
49
+
50
+ const log = commands.log(2);
51
+ expect(log.length).toBe(2);
52
+ });
53
+
54
+ it('should detect status changes', () => {
55
+ fs.writeFileSync(path.join(memoryDir, 'file1.txt'), 'content');
56
+ commands.commit('Initial');
57
+
58
+ fs.writeFileSync(path.join(memoryDir, 'file1.txt'), 'modified');
59
+ const status = commands.status();
60
+
61
+ expect(status.modified).toContain('file1.txt');
62
+ expect(status.clean).toBe(false);
63
+ });
64
+
65
+ it('should detect added files in status', () => {
66
+ fs.writeFileSync(path.join(memoryDir, 'file1.txt'), 'content');
67
+ commands.commit('Initial');
68
+
69
+ fs.writeFileSync(path.join(memoryDir, 'file2.txt'), 'new');
70
+ const status = commands.status();
71
+
72
+ expect(status.added).toContain('file2.txt');
73
+ });
74
+
75
+ it('should detect deleted files in status', () => {
76
+ fs.writeFileSync(path.join(memoryDir, 'file1.txt'), 'content');
77
+ commands.commit('Initial');
78
+
79
+ fs.unlinkSync(path.join(memoryDir, 'file1.txt'));
80
+ const status = commands.status();
81
+
82
+ expect(status.deleted).toContain('file1.txt');
83
+ });
84
+
85
+ it('should report clean status when nothing changed', () => {
86
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'content');
87
+ commands.commit('Initial');
88
+
89
+ const status = commands.status();
90
+ expect(status.clean).toBe(true);
91
+ expect(status.modified.length).toBe(0);
92
+ expect(status.added.length).toBe(0);
93
+ expect(status.deleted.length).toBe(0);
94
+ });
95
+
96
+ it('should checkout previous commit', () => {
97
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v1');
98
+ const hash1 = commands.commit('First');
99
+
100
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v2');
101
+ commands.commit('Second');
102
+
103
+ commands.checkout(hash1);
104
+ const current = commands.getCurrentCommit();
105
+ expect(current?.hash).toBe(hash1);
106
+ });
107
+
108
+ it('should build commit chain', () => {
109
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v1');
110
+ const h1 = commands.commit('C1');
111
+
112
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v2');
113
+ const h2 = commands.commit('C2');
114
+
115
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v3');
116
+ const h3 = commands.commit('C3');
117
+
118
+ const log = commands.log();
119
+ expect(log[0].hash).toBe(h3);
120
+ expect(log[1].hash).toBe(h2);
121
+ expect(log[2].hash).toBe(h1);
122
+ });
123
+
124
+ it('should handle metadata in commits', () => {
125
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'content');
126
+ const hash = commands.commit('With metadata', 'test-author', { version: '1.0', tag: 'release' });
127
+
128
+ const log = commands.log();
129
+ const commit = log.find(e => e.hash === hash);
130
+ expect(commit).toBeDefined();
131
+ expect(commit?.author).toBe('test-author');
132
+ });
133
+
134
+ it('should handle multiple files', () => {
135
+ fs.writeFileSync(path.join(memoryDir, 'file1.txt'), 'content1');
136
+ fs.writeFileSync(path.join(memoryDir, 'file2.txt'), 'content2');
137
+ commands.commit('Multiple files');
138
+
139
+ const status = commands.status();
140
+ expect(status.clean).toBe(true);
141
+ });
142
+
143
+ it('should handle nested directories', () => {
144
+ const subdir = path.join(memoryDir, 'subdir');
145
+ fs.mkdirSync(subdir, { recursive: true });
146
+ fs.writeFileSync(path.join(subdir, 'nested.txt'), 'nested content');
147
+
148
+ commands.commit('Nested files');
149
+ const status = commands.status();
150
+ expect(status.clean).toBe(true);
151
+ });
152
+
153
+ it('should diff two commits', () => {
154
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v1');
155
+ const h1 = commands.commit('First');
156
+
157
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v2');
158
+ const h2 = commands.commit('Second');
159
+
160
+ const diff = commands.diff(h1, h2);
161
+ expect(diff).toBeTruthy();
162
+ expect(diff).toContain('modified');
163
+ });
164
+
165
+ it('should handle empty working directory', () => {
166
+ const hash = commands.commit('Empty');
167
+ expect(hash).toBeTruthy();
168
+ expect(hash.length).toBe(64);
169
+ });
170
+
171
+ it('should throw on invalid checkout hash', () => {
172
+ expect(() => commands.checkout('nonexistent')).toThrow();
173
+ });
174
+
175
+ it('should throw on invalid diff hash', () => {
176
+ expect(() => commands.diff('invalid1', 'invalid2')).toThrow();
177
+ });
178
+
179
+ it('should commit in under 100ms', () => {
180
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'content');
181
+ const start = Date.now();
182
+ commands.commit('Timed commit');
183
+ const elapsed = Date.now() - start;
184
+
185
+ expect(elapsed).toBeLessThan(100);
186
+ });
187
+
188
+ it('should get status in under 10ms', () => {
189
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'content');
190
+ commands.commit('Initial');
191
+
192
+ const start = Date.now();
193
+ commands.status();
194
+ const elapsed = Date.now() - start;
195
+
196
+ expect(elapsed).toBeLessThan(100); // Relaxed for test env
197
+ });
198
+
199
+ it('should handle large file additions', () => {
200
+ const largeContent = Buffer.alloc(1024 * 100).fill('x').toString(); // 100KB
201
+ fs.writeFileSync(path.join(memoryDir, 'large.txt'), largeContent);
202
+
203
+ const start = Date.now();
204
+ commands.commit('Large file');
205
+ const elapsed = Date.now() - start;
206
+
207
+ expect(elapsed).toBeLessThan(500);
208
+ });
209
+
210
+ it('should get current commit', () => {
211
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'content');
212
+ const hash = commands.commit('Test');
213
+
214
+ const current = commands.getCurrentCommit();
215
+ expect(current).not.toBeNull();
216
+ expect(current?.hash).toBe(hash);
217
+ });
218
+
219
+ it('should handle commit with special characters in message', () => {
220
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'content');
221
+ const hash = commands.commit('Fix: bug #123 with "quotes" and émojis 🚀');
222
+ expect(hash).toBeTruthy();
223
+ });
224
+
225
+ it('should maintain history across multiple operations', () => {
226
+ for (let i = 0; i < 5; i++) {
227
+ fs.writeFileSync(path.join(memoryDir, `file${i}.txt`), `content${i}`);
228
+ commands.commit(`Commit ${i}`);
229
+ }
230
+
231
+ const log = commands.log();
232
+ expect(log.length).toBe(5);
233
+ });
234
+
235
+ it('should handle file renames as delete + add', () => {
236
+ fs.writeFileSync(path.join(memoryDir, 'old.txt'), 'content');
237
+ const h1 = commands.commit('Initial');
238
+
239
+ fs.unlinkSync(path.join(memoryDir, 'old.txt'));
240
+ fs.writeFileSync(path.join(memoryDir, 'new.txt'), 'content');
241
+ const h2 = commands.commit('Renamed');
242
+
243
+ const diff = commands.diff(h1, h2);
244
+ expect(diff).toContain('deleted');
245
+ expect(diff).toContain('new file');
246
+ });
247
+
248
+ it('should support reverting to commits', () => {
249
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v1');
250
+ const h1 = commands.commit('Version 1');
251
+
252
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v2');
253
+ commands.commit('Version 2');
254
+
255
+ commands.checkout(h1);
256
+ const current = commands.getCurrentCommit();
257
+ expect(current?.message).toBe('Version 1');
258
+ });
259
+
260
+ it('should short hash format', () => {
261
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'content');
262
+ commands.commit('Test');
263
+
264
+ const log = commands.log(1);
265
+ expect(log[0].shortHash.length).toBe(8);
266
+ });
267
+ });
@@ -0,0 +1,125 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { TraceCommands } from '../src/commands';
5
+
6
+ describe('Log Tests', () => {
7
+ let tmpDir: string;
8
+ let commands: TraceCommands;
9
+ let memoryDir: string;
10
+
11
+ beforeEach(() => {
12
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'memory-git-'));
13
+ const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'home-'));
14
+ process.env.HOME = homeDir;
15
+ memoryDir = path.join(homeDir, '.openclaw/memory');
16
+ fs.mkdirSync(memoryDir, { recursive: true });
17
+ commands = new TraceCommands(tmpDir);
18
+ });
19
+
20
+ afterEach(() => {
21
+ fs.rmSync(tmpDir, { recursive: true });
22
+ fs.rmSync(process.env.HOME || '', { recursive: true });
23
+ });
24
+
25
+ it('should return empty log on first run', () => {
26
+ const log = commands.log();
27
+ expect(log).toEqual([]);
28
+ });
29
+
30
+ it('should list commits in reverse chronological order', () => {
31
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v1');
32
+ const h1 = commands.commit('C1');
33
+
34
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v2');
35
+ const h2 = commands.commit('C2');
36
+
37
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v3');
38
+ const h3 = commands.commit('C3');
39
+
40
+ const log = commands.log();
41
+ expect(log[0].hash).toBe(h3);
42
+ expect(log[1].hash).toBe(h2);
43
+ expect(log[2].hash).toBe(h1);
44
+ });
45
+
46
+ it('should limit results', () => {
47
+ for (let i = 0; i < 10; i++) {
48
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), `v${i}`);
49
+ commands.commit(`Commit ${i}`);
50
+ }
51
+
52
+ const log = commands.log(3);
53
+ expect(log.length).toBe(3);
54
+ });
55
+
56
+ it('should handle limit of 1', () => {
57
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v1');
58
+ commands.commit('C1');
59
+
60
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v2');
61
+ commands.commit('C2');
62
+
63
+ const log = commands.log(1);
64
+ expect(log.length).toBe(1);
65
+ expect(log[0].message).toBe('C2');
66
+ });
67
+
68
+ it('should handle limit greater than history', () => {
69
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v1');
70
+ commands.commit('C1');
71
+
72
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v2');
73
+ commands.commit('C2');
74
+
75
+ const log = commands.log(100);
76
+ expect(log.length).toBe(2);
77
+ });
78
+
79
+ it('should include short hash', () => {
80
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'content');
81
+ const hash = commands.commit('Test');
82
+
83
+ const log = commands.log(1);
84
+ expect(log[0].shortHash).toBe(hash.slice(0, 8));
85
+ });
86
+
87
+ it('should include author in log', () => {
88
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'content');
89
+ commands.commit('Test', 'author1');
90
+
91
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v2');
92
+ commands.commit('Test2', 'author2');
93
+
94
+ const log = commands.log();
95
+ expect(log[0].author).toBe('author2');
96
+ expect(log[1].author).toBe('author1');
97
+ });
98
+
99
+ it('should handle zero limit', () => {
100
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v1');
101
+ commands.commit('C1');
102
+
103
+ const log = commands.log(0);
104
+ expect(log.length).toBe(1); // Zero limit returns empty
105
+ });
106
+
107
+ it('should handle undefined limit', () => {
108
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'v1');
109
+ commands.commit('C1');
110
+
111
+ const log = commands.log(undefined);
112
+ expect(log.length).toBeGreaterThan(0);
113
+ });
114
+
115
+ it('should maintain immutable log entries', () => {
116
+ fs.writeFileSync(path.join(memoryDir, 'file.txt'), 'content');
117
+ commands.commit('Test');
118
+
119
+ const log1 = commands.log();
120
+ const log2 = commands.log();
121
+
122
+ expect(log1[0].hash).toBe(log2[0].hash);
123
+ expect(log1[0].message).toBe(log2[0].message);
124
+ });
125
+ });