@ddtcorex/dsh-maestro-memory 1.0.1

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 (109) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/LICENSE +21 -0
  3. package/README.md +448 -0
  4. package/cordis.patch.yml +13 -0
  5. package/lib/client.js +756 -0
  6. package/lib/index.d.ts +10 -0
  7. package/lib/index.d.ts.map +1 -0
  8. package/lib/index.js +627 -0
  9. package/lib/index.js.map +1 -0
  10. package/lib/memory/batch.d.ts +44 -0
  11. package/lib/memory/batch.d.ts.map +1 -0
  12. package/lib/memory/batch.js +75 -0
  13. package/lib/memory/batch.js.map +1 -0
  14. package/lib/memory/feedback.d.ts +18 -0
  15. package/lib/memory/feedback.d.ts.map +1 -0
  16. package/lib/memory/feedback.js +29 -0
  17. package/lib/memory/feedback.js.map +1 -0
  18. package/lib/memory/store.d.ts +154 -0
  19. package/lib/memory/store.d.ts.map +1 -0
  20. package/lib/memory/store.js +606 -0
  21. package/lib/memory/store.js.map +1 -0
  22. package/lib/migration/cli.d.ts +18 -0
  23. package/lib/migration/cli.d.ts.map +1 -0
  24. package/lib/migration/cli.js +143 -0
  25. package/lib/migration/cli.js.map +1 -0
  26. package/lib/migration/fixture.d.ts +45 -0
  27. package/lib/migration/fixture.d.ts.map +1 -0
  28. package/lib/migration/fixture.js +177 -0
  29. package/lib/migration/fixture.js.map +1 -0
  30. package/lib/migration/service.d.ts +75 -0
  31. package/lib/migration/service.d.ts.map +1 -0
  32. package/lib/migration/service.js +713 -0
  33. package/lib/migration/service.js.map +1 -0
  34. package/lib/prompt/snapshot.d.ts +26 -0
  35. package/lib/prompt/snapshot.d.ts.map +1 -0
  36. package/lib/prompt/snapshot.js +74 -0
  37. package/lib/prompt/snapshot.js.map +1 -0
  38. package/lib/review/queue.d.ts +72 -0
  39. package/lib/review/queue.d.ts.map +1 -0
  40. package/lib/review/queue.js +306 -0
  41. package/lib/review/queue.js.map +1 -0
  42. package/lib/skills-browser.d.ts +67 -0
  43. package/lib/skills-browser.d.ts.map +1 -0
  44. package/lib/skills-browser.js +185 -0
  45. package/lib/skills-browser.js.map +1 -0
  46. package/lib/storage/atomic-store.d.ts +211 -0
  47. package/lib/storage/atomic-store.d.ts.map +1 -0
  48. package/lib/storage/atomic-store.js +582 -0
  49. package/lib/storage/atomic-store.js.map +1 -0
  50. package/lib/storage/layout.d.ts +81 -0
  51. package/lib/storage/layout.d.ts.map +1 -0
  52. package/lib/storage/layout.js +162 -0
  53. package/lib/storage/layout.js.map +1 -0
  54. package/lib/storage/legacy-format.d.ts +104 -0
  55. package/lib/storage/legacy-format.d.ts.map +1 -0
  56. package/lib/storage/legacy-format.js +262 -0
  57. package/lib/storage/legacy-format.js.map +1 -0
  58. package/lib/sync/config.d.ts +22 -0
  59. package/lib/sync/config.d.ts.map +1 -0
  60. package/lib/sync/config.js +57 -0
  61. package/lib/sync/config.js.map +1 -0
  62. package/lib/sync/git.d.ts +97 -0
  63. package/lib/sync/git.d.ts.map +1 -0
  64. package/lib/sync/git.js +282 -0
  65. package/lib/sync/git.js.map +1 -0
  66. package/lib/sync/index.d.ts +6 -0
  67. package/lib/sync/index.d.ts.map +1 -0
  68. package/lib/sync/index.js +6 -0
  69. package/lib/sync/index.js.map +1 -0
  70. package/lib/sync/layout.d.ts +15 -0
  71. package/lib/sync/layout.d.ts.map +1 -0
  72. package/lib/sync/layout.js +33 -0
  73. package/lib/sync/layout.js.map +1 -0
  74. package/lib/sync/merge.d.ts +42 -0
  75. package/lib/sync/merge.d.ts.map +1 -0
  76. package/lib/sync/merge.js +159 -0
  77. package/lib/sync/merge.js.map +1 -0
  78. package/lib/sync/service.d.ts +70 -0
  79. package/lib/sync/service.d.ts.map +1 -0
  80. package/lib/sync/service.js +508 -0
  81. package/lib/sync/service.js.map +1 -0
  82. package/lib/todo/store.d.ts +142 -0
  83. package/lib/todo/store.d.ts.map +1 -0
  84. package/lib/todo/store.js +452 -0
  85. package/lib/todo/store.js.map +1 -0
  86. package/lib/types/client/index.d.ts +7 -0
  87. package/lib/types/client/index.d.ts.map +1 -0
  88. package/package.json +63 -0
  89. package/src/client/index.tsx +994 -0
  90. package/src/host/index.ts +591 -0
  91. package/src/host/memory/batch.ts +107 -0
  92. package/src/host/memory/feedback.ts +36 -0
  93. package/src/host/memory/store.ts +650 -0
  94. package/src/host/migration/cli.ts +139 -0
  95. package/src/host/migration/fixture.ts +218 -0
  96. package/src/host/migration/service.ts +786 -0
  97. package/src/host/prompt/snapshot.ts +95 -0
  98. package/src/host/review/queue.ts +325 -0
  99. package/src/host/skills-browser.ts +191 -0
  100. package/src/host/storage/atomic-store.ts +605 -0
  101. package/src/host/storage/layout.ts +191 -0
  102. package/src/host/storage/legacy-format.ts +308 -0
  103. package/src/host/sync/config.ts +67 -0
  104. package/src/host/sync/git.ts +280 -0
  105. package/src/host/sync/index.ts +5 -0
  106. package/src/host/sync/layout.ts +39 -0
  107. package/src/host/sync/merge.ts +188 -0
  108. package/src/host/sync/service.ts +494 -0
  109. package/src/host/todo/store.ts +480 -0
@@ -0,0 +1,97 @@
1
+ /**
2
+ * git.ts — Git adapter abstraction. Disabled => zero spawn.
3
+ * Real adapter uses child_process git with file:// remotes via --git-dir show.
4
+ * Mock adapter is in-memory for tests.
5
+ */
6
+ export interface GitAdapter {
7
+ /** Fetch remote branch, return ok/error */
8
+ fetch(remoteUrl: string, branch: string): Promise<{
9
+ ok: true;
10
+ } | {
11
+ ok: false;
12
+ error: string;
13
+ }>;
14
+ /** Push files to remote branch (commit & push). files keys are branch-root paths e.g. KEY.md */
15
+ push(remoteUrl: string, branch: string, files: Record<string, string>, message: string): Promise<{
16
+ ok: true;
17
+ } | {
18
+ ok: false;
19
+ error: string;
20
+ }>;
21
+ /** Get remote branch files (read). */
22
+ getRemoteFiles(remoteUrl: string, branch: string): Promise<{
23
+ ok: true;
24
+ files: Record<string, string>;
25
+ } | {
26
+ ok: false;
27
+ error: string;
28
+ }>;
29
+ }
30
+ /**
31
+ * MockGitAdapter — in-memory remote, tracks calls for disabled assertions.
32
+ */
33
+ export declare class MockGitAdapter implements GitAdapter {
34
+ remotes: Map<string, Map<string, Record<string, string>>>;
35
+ calls: Array<{
36
+ method: string;
37
+ remoteUrl: string;
38
+ branch: string;
39
+ }>;
40
+ failNextFetch: string | null;
41
+ failNextPush: string | null;
42
+ failNextGet: string | null;
43
+ fetch(remoteUrl: string, branch: string): Promise<{
44
+ ok: true;
45
+ } | {
46
+ ok: false;
47
+ error: string;
48
+ }>;
49
+ push(remoteUrl: string, branch: string, files: Record<string, string>, message: string): Promise<{
50
+ ok: true;
51
+ } | {
52
+ ok: false;
53
+ error: string;
54
+ }>;
55
+ getRemoteFiles(remoteUrl: string, branch: string): Promise<{
56
+ ok: true;
57
+ files: Record<string, string>;
58
+ } | {
59
+ ok: false;
60
+ error: string;
61
+ }>;
62
+ setRemoteFiles(remoteUrl: string, branch: string, files: Record<string, string>): void;
63
+ getRemoteFilesSync(remoteUrl: string, branch: string): Record<string, string> | undefined;
64
+ reset(): void;
65
+ }
66
+ /**
67
+ * RealGitAdapter — uses git CLI for file:// remotes.
68
+ * For http/ssh remotes it delegates to git fetch/push via temp clone.
69
+ * Minimal implementation sufficient for integration tests with file:// bare remotes.
70
+ */
71
+ export declare class RealGitAdapter implements GitAdapter {
72
+ fetch(remoteUrl: string, branch: string): Promise<{
73
+ ok: true;
74
+ } | {
75
+ ok: false;
76
+ error: string;
77
+ }>;
78
+ getRemoteFiles(remoteUrl: string, branch: string): Promise<{
79
+ ok: true;
80
+ files: Record<string, string>;
81
+ } | {
82
+ ok: false;
83
+ error: string;
84
+ }>;
85
+ push(remoteUrl: string, branch: string, files: Record<string, string>, message: string): Promise<{
86
+ ok: true;
87
+ } | {
88
+ ok: false;
89
+ error: string;
90
+ }>;
91
+ private resolveFileUrl;
92
+ private getFilesFromBare;
93
+ private pushToBare;
94
+ private getFilesViaClone;
95
+ private pushViaClone;
96
+ }
97
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/host/sync/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,282 @@
1
+ /**
2
+ * git.ts — Git adapter abstraction. Disabled => zero spawn.
3
+ * Real adapter uses child_process git with file:// remotes via --git-dir show.
4
+ * Mock adapter is in-memory for tests.
5
+ */
6
+ import { spawnSync } from 'node:child_process';
7
+ import { mkdtempSync, rmSync, readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+ import { tmpdir } from 'node:os';
10
+ /**
11
+ * MockGitAdapter — in-memory remote, tracks calls for disabled assertions.
12
+ */
13
+ export class MockGitAdapter {
14
+ // remoteUrl -> branch -> files
15
+ remotes = new Map();
16
+ calls = [];
17
+ failNextFetch = null;
18
+ failNextPush = null;
19
+ failNextGet = null;
20
+ async fetch(remoteUrl, branch) {
21
+ this.calls.push({ method: 'fetch', remoteUrl, branch });
22
+ if (this.failNextFetch) {
23
+ const e = this.failNextFetch;
24
+ this.failNextFetch = null;
25
+ return { ok: false, error: e };
26
+ }
27
+ return { ok: true };
28
+ }
29
+ async push(remoteUrl, branch, files, message) {
30
+ this.calls.push({ method: 'push', remoteUrl, branch });
31
+ if (this.failNextPush) {
32
+ const e = this.failNextPush;
33
+ this.failNextPush = null;
34
+ return { ok: false, error: e };
35
+ }
36
+ let br = this.remotes.get(remoteUrl);
37
+ if (!br) {
38
+ br = new Map();
39
+ this.remotes.set(remoteUrl, br);
40
+ }
41
+ br.set(branch, { ...files, '.meta.json': JSON.stringify({ message, at: new Date().toISOString() }) });
42
+ return { ok: true };
43
+ }
44
+ async getRemoteFiles(remoteUrl, branch) {
45
+ this.calls.push({ method: 'getRemoteFiles', remoteUrl, branch });
46
+ if (this.failNextGet) {
47
+ const e = this.failNextGet;
48
+ this.failNextGet = null;
49
+ return { ok: false, error: e };
50
+ }
51
+ const br = this.remotes.get(remoteUrl)?.get(branch);
52
+ if (!br)
53
+ return { ok: true, files: {} };
54
+ // strip meta
55
+ const { '.meta.json': _m, ...files } = br;
56
+ return { ok: true, files };
57
+ }
58
+ // helper to directly set remote files (simulate other machine push)
59
+ setRemoteFiles(remoteUrl, branch, files) {
60
+ let br = this.remotes.get(remoteUrl);
61
+ if (!br) {
62
+ br = new Map();
63
+ this.remotes.set(remoteUrl, br);
64
+ }
65
+ br.set(branch, { ...files });
66
+ }
67
+ getRemoteFilesSync(remoteUrl, branch) {
68
+ return this.remotes.get(remoteUrl)?.get(branch);
69
+ }
70
+ reset() {
71
+ this.calls = [];
72
+ this.failNextFetch = null;
73
+ this.failNextPush = null;
74
+ this.failNextGet = null;
75
+ }
76
+ }
77
+ /**
78
+ * RealGitAdapter — uses git CLI for file:// remotes.
79
+ * For http/ssh remotes it delegates to git fetch/push via temp clone.
80
+ * Minimal implementation sufficient for integration tests with file:// bare remotes.
81
+ */
82
+ export class RealGitAdapter {
83
+ async fetch(remoteUrl, branch) {
84
+ // For file:// bare remote, check existence via ls-remote; no real fetch needed.
85
+ // We treat fetch as ls-remote to validate connectivity.
86
+ const res = spawnSync('git', ['ls-remote', remoteUrl, `refs/heads/${branch}`], { encoding: 'utf8', timeout: 5000, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
87
+ if (res.error)
88
+ return { ok: false, error: res.error.message ?? String(res.error) };
89
+ if (res.status !== 0) {
90
+ const stderr = String(res.stderr ?? '');
91
+ const lower = stderr.toLowerCase();
92
+ // Only a reachable repo where this exact branch/ref does not exist yet is
93
+ // acceptable (means "first push"). Everything else — unreachable remote,
94
+ // not a repo, or an auth/connectivity failure — is a hard error so we
95
+ // never silently treat an offline remote as "no data".
96
+ if (lower.includes("couldn't find remote ref") || lower.includes('no such ref') || lower.includes('unknown revision')) {
97
+ return { ok: true };
98
+ }
99
+ return { ok: false, error: stderr.trim() || `ls-remote failed (status ${res.status})` };
100
+ }
101
+ return { ok: true };
102
+ }
103
+ async getRemoteFiles(remoteUrl, branch) {
104
+ // Use git --git-dir=<remote> show branch:file if remote is file:// path
105
+ const filePath = this.resolveFileUrl(remoteUrl);
106
+ if (filePath) {
107
+ // file:// bare remote
108
+ return this.getFilesFromBare(filePath, branch);
109
+ }
110
+ // For non-file remotes, clone to temp and read
111
+ return this.getFilesViaClone(remoteUrl, branch);
112
+ }
113
+ async push(remoteUrl, branch, files, message) {
114
+ const filePath = this.resolveFileUrl(remoteUrl);
115
+ if (filePath) {
116
+ return this.pushToBare(filePath, branch, files, message);
117
+ }
118
+ return this.pushViaClone(remoteUrl, branch, files, message);
119
+ }
120
+ resolveFileUrl(url) {
121
+ if (url.startsWith('file://'))
122
+ return url.slice('file://'.length);
123
+ if (url.startsWith('/tmp/') || url.startsWith('/')) {
124
+ // Treat absolute path as file remote for tests (implicit file://)
125
+ if (existsSync(url))
126
+ return url;
127
+ // also allow /tmp/xxx without existence check
128
+ if (url.startsWith('/tmp/'))
129
+ return url;
130
+ }
131
+ return null;
132
+ }
133
+ getFilesFromBare(barePath, branch) {
134
+ return new Promise((resolve) => {
135
+ const expected = ['KEY.md', 'MEMORY.md', 'KEY-archive.md', 'TODOS.md'];
136
+ const files = {};
137
+ for (const f of expected) {
138
+ const res = spawnSync('git', ['--git-dir', barePath, 'show', `${branch}:${f}`], { encoding: 'utf8', timeout: 5000 });
139
+ if (res.status === 0) {
140
+ files[f] = res.stdout;
141
+ }
142
+ else {
143
+ // file not on branch or branch missing -> treat as missing
144
+ // if branch missing, files empty
145
+ const stderr = String(res.stderr ?? '');
146
+ if (stderr.includes('not found') || stderr.includes('does not exist') || stderr.includes('invalid object')) {
147
+ continue;
148
+ }
149
+ // other error -> treat as empty for now
150
+ continue;
151
+ }
152
+ }
153
+ // Check if branch exists at all: if no files and branch missing, return empty (not error)
154
+ const ls = spawnSync('git', ['--git-dir', barePath, 'rev-parse', '--verify', `refs/heads/${branch}`], { encoding: 'utf8' });
155
+ if (ls.status !== 0 && Object.keys(files).length === 0) {
156
+ // branch not existent yet
157
+ resolve({ ok: true, files: {} });
158
+ return;
159
+ }
160
+ resolve({ ok: true, files });
161
+ });
162
+ }
163
+ pushToBare(barePath, branch, files, message) {
164
+ return new Promise((resolve) => {
165
+ const tmp = mkdtempSync(join(tmpdir(), 'maestro-sync-'));
166
+ try {
167
+ // init temp repo
168
+ let r = spawnSync('git', ['init'], { cwd: tmp, encoding: 'utf8' });
169
+ if (r.status !== 0)
170
+ return resolve({ ok: false, error: r.stderr?.toString() ?? 'init failed' });
171
+ r = spawnSync('git', ['remote', 'add', 'origin', barePath], { cwd: tmp, encoding: 'utf8' });
172
+ if (r.status !== 0)
173
+ return resolve({ ok: false, error: r.stderr?.toString() ?? 'remote add failed' });
174
+ // try fetch existing branch
175
+ spawnSync('git', ['fetch', 'origin', branch], { cwd: tmp, encoding: 'utf8', env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
176
+ // Check out the branch ON TOP of the fetched remote tip (FETCH_HEAD) so a
177
+ // subsequent commit is a descendant of the remote history and can be
178
+ // pushed as a fast-forward. On the first push FETCH_HEAD is absent, so
179
+ // checkout falls through to the orphan branch path below.
180
+ const checkout = spawnSync('git', ['checkout', '-B', branch, 'FETCH_HEAD'], { cwd: tmp, encoding: 'utf8' });
181
+ if (checkout.status !== 0) {
182
+ // try orphan
183
+ spawnSync('git', ['checkout', '--orphan', branch], { cwd: tmp, encoding: 'utf8' });
184
+ spawnSync('git', ['rm', '-rf', '.'], { cwd: tmp, encoding: 'utf8' });
185
+ }
186
+ // write files
187
+ for (const [name, content] of Object.entries(files)) {
188
+ const p = join(tmp, name);
189
+ mkdirSync(join(p, '..'), { recursive: true });
190
+ writeFileSync(p, content, 'utf8');
191
+ }
192
+ spawnSync('git', ['add', '.'], { cwd: tmp, encoding: 'utf8' });
193
+ // need user identity
194
+ const env = { ...process.env, GIT_AUTHOR_NAME: 'maestro', GIT_AUTHOR_EMAIL: 'maestro@local', GIT_COMMITTER_NAME: 'maestro', GIT_COMMITTER_EMAIL: 'maestro@local' };
195
+ const commit = spawnSync('git', ['commit', '-m', message, '--allow-empty'], { cwd: tmp, encoding: 'utf8', env });
196
+ if (commit.status !== 0)
197
+ return resolve({ ok: false, error: commit.stderr?.toString() ?? 'commit failed' });
198
+ const push = spawnSync('git', ['push', 'origin', `${branch}:${branch}`], { cwd: tmp, encoding: 'utf8', env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
199
+ if (push.status !== 0)
200
+ return resolve({ ok: false, error: push.stderr?.toString() ?? 'push failed' });
201
+ resolve({ ok: true });
202
+ }
203
+ finally {
204
+ try {
205
+ rmSync(tmp, { recursive: true, force: true });
206
+ }
207
+ catch { }
208
+ }
209
+ });
210
+ }
211
+ getFilesViaClone(remoteUrl, branch) {
212
+ return new Promise((resolve) => {
213
+ const tmp = mkdtempSync(join(tmpdir(), 'maestro-sync-clone-'));
214
+ try {
215
+ const clone = spawnSync('git', ['clone', '--branch', branch, '--single-branch', remoteUrl, tmp + '/repo'], { encoding: 'utf8', timeout: 10000, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
216
+ if (clone.status !== 0) {
217
+ // branch may not exist yet
218
+ resolve({ ok: true, files: {} });
219
+ return;
220
+ }
221
+ const repo = join(tmp, 'repo');
222
+ const files = {};
223
+ for (const f of ['KEY.md', 'MEMORY.md', 'KEY-archive.md', 'TODOS.md']) {
224
+ const p = join(repo, f);
225
+ if (existsSync(p))
226
+ files[f] = readFileSync(p, 'utf8');
227
+ }
228
+ resolve({ ok: true, files });
229
+ }
230
+ finally {
231
+ try {
232
+ rmSync(tmp, { recursive: true, force: true });
233
+ }
234
+ catch { }
235
+ }
236
+ });
237
+ }
238
+ pushViaClone(remoteUrl, branch, files, message) {
239
+ return new Promise((resolve) => {
240
+ const tmp = mkdtempSync(join(tmpdir(), 'maestro-sync-push-'));
241
+ try {
242
+ // shallow clone or init
243
+ let repo = join(tmp, 'repo');
244
+ mkdirSync(repo, { recursive: true });
245
+ let r = spawnSync('git', ['init'], { cwd: repo, encoding: 'utf8' });
246
+ if (r.status !== 0)
247
+ return resolve({ ok: false, error: r.stderr?.toString() ?? 'init failed' });
248
+ r = spawnSync('git', ['remote', 'add', 'origin', remoteUrl], { cwd: repo, encoding: 'utf8' });
249
+ if (r.status !== 0)
250
+ return resolve({ ok: false, error: r.stderr?.toString() ?? 'remote add failed' });
251
+ spawnSync('git', ['fetch', 'origin', branch], { cwd: repo, encoding: 'utf8', env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
252
+ // Base the branch on the remote tip (FETCH_HEAD) so we fast-forward
253
+ // instead of producing an orphan root commit that the second push
254
+ // rejects as non-fast-forward.
255
+ const checkout = spawnSync('git', ['checkout', '-B', branch, 'FETCH_HEAD'], { cwd: repo, encoding: 'utf8' });
256
+ if (checkout.status !== 0) {
257
+ spawnSync('git', ['checkout', '--orphan', branch], { cwd: repo, encoding: 'utf8' });
258
+ spawnSync('git', ['rm', '-rf', '.'], { cwd: repo, encoding: 'utf8' });
259
+ }
260
+ for (const [name, content] of Object.entries(files)) {
261
+ writeFileSync(join(repo, name), content, 'utf8');
262
+ }
263
+ spawnSync('git', ['add', '.'], { cwd: repo, encoding: 'utf8' });
264
+ const env = { ...process.env, GIT_AUTHOR_NAME: 'maestro', GIT_AUTHOR_EMAIL: 'maestro@local', GIT_COMMITTER_NAME: 'maestro', GIT_COMMITTER_EMAIL: 'maestro@local' };
265
+ const commit = spawnSync('git', ['commit', '-m', message, '--allow-empty'], { cwd: repo, encoding: 'utf8', env });
266
+ if (commit.status !== 0)
267
+ return resolve({ ok: false, error: commit.stderr?.toString() ?? 'commit failed' });
268
+ const push = spawnSync('git', ['push', 'origin', `${branch}:${branch}`], { cwd: repo, encoding: 'utf8', env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
269
+ if (push.status !== 0)
270
+ return resolve({ ok: false, error: push.stderr?.toString() ?? 'push failed' });
271
+ resolve({ ok: true });
272
+ }
273
+ finally {
274
+ try {
275
+ rmSync(tmp, { recursive: true, force: true });
276
+ }
277
+ catch { }
278
+ }
279
+ });
280
+ }
281
+ }
282
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/host/sync/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export * from './layout.ts';
2
+ export * from './merge.ts';
3
+ export * from './git.ts';
4
+ export * from './config.ts';
5
+ export * from './service.ts';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host/sync/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA"}
@@ -0,0 +1,6 @@
1
+ export * from "./layout.js";
2
+ export * from "./merge.js";
3
+ export * from "./git.js";
4
+ export * from "./config.js";
5
+ export * from "./service.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/host/sync/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA"}
@@ -0,0 +1,15 @@
1
+ export declare function syncDir(root: string, hash: string): string;
2
+ export declare function syncConfigPath(root: string, hash: string): string;
3
+ export declare function syncMetaPath(root: string, hash: string): string;
4
+ export declare function syncConflictsPath(root: string, hash: string): string;
5
+ export declare function syncBranchName(hash: string): string;
6
+ export declare function resolveSyncHash(cwd: string): string;
7
+ export declare function allSyncPaths(root: string, cwd: string): {
8
+ dir: string;
9
+ config: string;
10
+ meta: string;
11
+ conflicts: string;
12
+ branch: string;
13
+ hash: string;
14
+ };
15
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/host/sync/layout.ts"],"names":[],"mappings":"AAGA,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD;AAGD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;;;;;;;EAUrD"}
@@ -0,0 +1,33 @@
1
+ import { join } from 'node:path';
2
+ import { maestroMetaDir, projectHash } from "../storage/layout.js";
3
+ export function syncDir(root, hash) {
4
+ return join(maestroMetaDir(root), 'sync', hash);
5
+ }
6
+ export function syncConfigPath(root, hash) {
7
+ return join(syncDir(root, hash), 'config.json');
8
+ }
9
+ export function syncMetaPath(root, hash) {
10
+ return join(syncDir(root, hash), 'lastSync.json');
11
+ }
12
+ export function syncConflictsPath(root, hash) {
13
+ return join(syncDir(root, hash), 'conflicts.jsonl');
14
+ }
15
+ export function syncBranchName(hash) {
16
+ return `maestro-memory/${hash}`;
17
+ }
18
+ export function resolveSyncHash(cwd) {
19
+ return projectHash(cwd);
20
+ }
21
+ // aggregated for tests
22
+ export function allSyncPaths(root, cwd) {
23
+ const hash = projectHash(cwd);
24
+ return {
25
+ dir: syncDir(root, hash),
26
+ config: syncConfigPath(root, hash),
27
+ meta: syncMetaPath(root, hash),
28
+ conflicts: syncConflictsPath(root, hash),
29
+ branch: syncBranchName(hash),
30
+ hash,
31
+ };
32
+ }
33
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/host/sync/layout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAElE,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,IAAY;IAChD,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;AACjD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,IAAY;IACvD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,CAAA;AACjD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,IAAY;IACrD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,eAAe,CAAC,CAAA;AACnD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,IAAY;IAC1D,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,iBAAiB,CAAC,CAAA;AACrD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,kBAAkB,IAAI,EAAE,CAAA;AACjC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO,WAAW,CAAC,GAAG,CAAC,CAAA;AACzB,CAAC;AAED,uBAAuB;AACvB,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,GAAW;IACpD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;IAC7B,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;QACxB,MAAM,EAAE,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC;QAClC,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC;QAC9B,SAAS,EAAE,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC;QACxC,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC;QAC5B,IAAI;KACL,CAAA;AACH,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * merge.ts — union merge by id, never drops either version.
3
+ * Pure functions, no I/O.
4
+ */
5
+ export interface ConflictRecord {
6
+ id: string;
7
+ track: string;
8
+ localEntry: string | null;
9
+ remoteEntry: string | null;
10
+ reason: string;
11
+ }
12
+ export interface MergeResult {
13
+ merged: string[];
14
+ conflicts: ConflictRecord[];
15
+ addedLocal: string[];
16
+ addedRemote: string[];
17
+ }
18
+ /**
19
+ * Parse entries into map id => entry. Entries without id are assigned a synthetic
20
+ * id derived from content hash (for safety) but flagged as missing.
21
+ */
22
+ export declare function mapById(entries: string[]): Map<string, string>;
23
+ export declare function idsOf(entries: string[]): Set<string>;
24
+ /**
25
+ * Union merge for memory-style entries (KEY, MEMORY, archive).
26
+ * - local + remote entries with distinct ids => union (both present)
27
+ * - same id, same content => one entry
28
+ * - same id, different content => conflict (neither applied, keep local)
29
+ */
30
+ export declare function mergeMemoryEntries(opts: {
31
+ track: string;
32
+ local: string[];
33
+ remote: string[];
34
+ baseIds?: Set<string>;
35
+ }): MergeResult;
36
+ export declare function mergeTodoEntries(opts: {
37
+ local: string[];
38
+ remote: string[];
39
+ baseIds?: Set<string>;
40
+ }): MergeResult;
41
+ export declare function snapshotIds(entriesByTrack: Record<string, string[]>): Record<string, string[]>;
42
+ //# sourceMappingURL=merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/host/sync/merge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,SAAS,EAAE,cAAc,EAAE,CAAA;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB;AAkBD;;;GAGG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAU9D;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAOpD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CACtB,GAAG,WAAW,CAgGd;AAGD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,GAAG,WAAW,CAIhH;AAGD,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAO9F"}