@made-by-moonlight/athene-plugin-workspace-clone 0.9.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.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Composio, Inc.
4
+ Copyright (c) 2026 slievr (Athene fork)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,603 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import * as childProcess from "node:child_process";
3
+ import * as fs from "node:fs";
4
+ const { getShellMock, recordActivityEventMock } = vi.hoisted(() => ({
5
+ getShellMock: vi.fn(() => ({ cmd: "sh", args: (c) => ["-c", c] })),
6
+ recordActivityEventMock: vi.fn(),
7
+ }));
8
+ vi.mock("@made-by-moonlight/athene-core", async () => {
9
+ const actual = (await vi.importActual("@made-by-moonlight/athene-core"));
10
+ return {
11
+ ...actual,
12
+ getShell: getShellMock,
13
+ recordActivityEvent: recordActivityEventMock,
14
+ };
15
+ });
16
+ // Mock node:child_process with custom promisify support
17
+ vi.mock("node:child_process", () => {
18
+ const mockExecFile = vi.fn();
19
+ mockExecFile[Symbol.for("nodejs.util.promisify.custom")] = vi.fn();
20
+ return { execFile: mockExecFile };
21
+ });
22
+ // Mock node:fs
23
+ vi.mock("node:fs", () => ({
24
+ existsSync: vi.fn(),
25
+ rmSync: vi.fn(),
26
+ mkdirSync: vi.fn(),
27
+ readdirSync: vi.fn(),
28
+ }));
29
+ // Mock node:os
30
+ vi.mock("node:os", () => ({
31
+ homedir: () => "/mock-home",
32
+ }));
33
+ // Force POSIX path semantics in tests so "/mock-home/..." assertions match on
34
+ // Windows too. Only this test file uses the posix override.
35
+ vi.mock("node:path", async () => {
36
+ const actual = (await vi.importActual("node:path"));
37
+ return { ...actual.posix, default: actual.posix };
38
+ });
39
+ // Get reference to the promisify-custom mock — this is what the plugin actually calls
40
+ const mockExecFileAsync = childProcess.execFile[Symbol.for("nodejs.util.promisify.custom")];
41
+ /** Queue a successful git command with the given stdout. */
42
+ function mockGitSuccess(stdout) {
43
+ mockExecFileAsync.mockResolvedValueOnce({ stdout: stdout + "\n", stderr: "" });
44
+ }
45
+ /** Queue a failed git command. */
46
+ function mockGitError(message) {
47
+ mockExecFileAsync.mockRejectedValueOnce(new Error(message));
48
+ }
49
+ /** Create a ProjectConfig for testing. */
50
+ function makeProject(overrides) {
51
+ return {
52
+ name: "test-project",
53
+ repo: "test/repo",
54
+ path: "/repo/path",
55
+ defaultBranch: "main",
56
+ sessionPrefix: "test",
57
+ ...overrides,
58
+ };
59
+ }
60
+ // Import after mocks are set up
61
+ import clonePlugin, { manifest, create } from "../index.js";
62
+ import * as core from "@made-by-moonlight/athene-core";
63
+ const mockGetShell = core.getShell;
64
+ beforeEach(() => {
65
+ vi.clearAllMocks();
66
+ });
67
+ // ---------------------------------------------------------------------------
68
+ // manifest
69
+ // ---------------------------------------------------------------------------
70
+ describe("manifest", () => {
71
+ it("has name 'clone' and slot 'workspace'", () => {
72
+ expect(manifest.name).toBe("clone");
73
+ expect(manifest.slot).toBe("workspace");
74
+ expect(manifest.version).toBe("0.1.0");
75
+ expect(manifest.description).toBe("Workspace plugin: git clone isolation");
76
+ });
77
+ it("default export includes manifest and create", () => {
78
+ expect(clonePlugin.manifest).toBe(manifest);
79
+ expect(clonePlugin.create).toBe(create);
80
+ });
81
+ });
82
+ // ---------------------------------------------------------------------------
83
+ // create() factory
84
+ // ---------------------------------------------------------------------------
85
+ describe("create()", () => {
86
+ it("returns a Workspace with name 'clone'", () => {
87
+ const workspace = create();
88
+ expect(workspace.name).toBe("clone");
89
+ });
90
+ it("uses ~/.ao-clones as default base dir", async () => {
91
+ const workspace = create();
92
+ // Setup: remote URL lookup
93
+ mockGitSuccess("https://github.com/test/repo.git");
94
+ // existsSync: workspace path does not exist yet
95
+ fs.existsSync.mockReturnValue(false);
96
+ // git clone
97
+ mockGitSuccess("");
98
+ // git checkout -b
99
+ mockGitSuccess("");
100
+ const info = await workspace.create({
101
+ projectId: "myproject",
102
+ sessionId: "session-1",
103
+ branch: "feat/test",
104
+ project: makeProject(),
105
+ });
106
+ expect(info.path).toBe("/mock-home/.ao-clones/myproject/session-1");
107
+ });
108
+ it("uses custom cloneDir when configured", async () => {
109
+ const workspace = create({ cloneDir: "~/custom-clones" });
110
+ mockGitSuccess("https://github.com/test/repo.git");
111
+ fs.existsSync.mockReturnValue(false);
112
+ mockGitSuccess("");
113
+ mockGitSuccess("");
114
+ const info = await workspace.create({
115
+ projectId: "myproject",
116
+ sessionId: "session-2",
117
+ branch: "feat/custom",
118
+ project: makeProject(),
119
+ });
120
+ expect(info.path).toBe("/mock-home/custom-clones/myproject/session-2");
121
+ });
122
+ });
123
+ // ---------------------------------------------------------------------------
124
+ // workspace.create()
125
+ // ---------------------------------------------------------------------------
126
+ describe("workspace.create()", () => {
127
+ it("gets remote URL via git remote get-url origin", async () => {
128
+ const workspace = create();
129
+ // 1: git remote get-url origin
130
+ mockGitSuccess("https://github.com/test/repo.git");
131
+ fs.existsSync.mockReturnValue(false);
132
+ // 2: git clone
133
+ mockGitSuccess("");
134
+ // 3: git checkout -b
135
+ mockGitSuccess("");
136
+ await workspace.create({
137
+ projectId: "proj",
138
+ sessionId: "sess",
139
+ branch: "feat/branch",
140
+ project: makeProject(),
141
+ });
142
+ // First call should be git remote get-url origin
143
+ expect(mockExecFileAsync).toHaveBeenNthCalledWith(1, "git", ["remote", "get-url", "origin"], {
144
+ cwd: "/repo/path",
145
+ });
146
+ });
147
+ it("falls back to local path when remote URL lookup fails", async () => {
148
+ const workspace = create();
149
+ // 1: git remote get-url origin FAILS
150
+ mockGitError("fatal: not a git repository");
151
+ fs.existsSync.mockReturnValue(false);
152
+ // 2: git clone (uses local path as remoteUrl)
153
+ mockGitSuccess("");
154
+ // 3: git checkout -b
155
+ mockGitSuccess("");
156
+ await workspace.create({
157
+ projectId: "proj",
158
+ sessionId: "sess",
159
+ branch: "feat/branch",
160
+ project: makeProject(),
161
+ });
162
+ // Clone should use local path as the remote URL
163
+ const cloneCall = mockExecFileAsync.mock.calls[1];
164
+ expect(cloneCall[0]).toBe("git");
165
+ const cloneArgs = cloneCall[1];
166
+ // The remote URL argument (after --reference repoPath --branch defaultBranch) is the 6th arg
167
+ expect(cloneArgs[5]).toBe("/repo/path");
168
+ });
169
+ it("calls git clone with --reference flag", async () => {
170
+ const workspace = create();
171
+ mockGitSuccess("https://github.com/test/repo.git");
172
+ fs.existsSync.mockReturnValue(false);
173
+ mockGitSuccess("");
174
+ mockGitSuccess("");
175
+ await workspace.create({
176
+ projectId: "proj",
177
+ sessionId: "sess",
178
+ branch: "feat/branch",
179
+ project: makeProject({ defaultBranch: "develop" }),
180
+ });
181
+ // The clone call (second call overall)
182
+ expect(mockExecFileAsync).toHaveBeenNthCalledWith(2, "git", [
183
+ "clone",
184
+ "--reference",
185
+ "/repo/path",
186
+ "--branch",
187
+ "develop",
188
+ "https://github.com/test/repo.git",
189
+ "/mock-home/.ao-clones/proj/sess",
190
+ ]);
191
+ });
192
+ it("creates feature branch via checkout -b", async () => {
193
+ const workspace = create();
194
+ mockGitSuccess("https://github.com/test/repo.git");
195
+ fs.existsSync.mockReturnValue(false);
196
+ mockGitSuccess("");
197
+ // git checkout -b feat/new-branch
198
+ mockGitSuccess("");
199
+ await workspace.create({
200
+ projectId: "proj",
201
+ sessionId: "sess",
202
+ branch: "feat/new-branch",
203
+ project: makeProject(),
204
+ });
205
+ // Third call: checkout -b
206
+ expect(mockExecFileAsync).toHaveBeenNthCalledWith(3, "git", ["checkout", "-b", "feat/new-branch"], { cwd: "/mock-home/.ao-clones/proj/sess" });
207
+ });
208
+ it("falls back to plain checkout when branch already exists", async () => {
209
+ const workspace = create();
210
+ mockGitSuccess("https://github.com/test/repo.git");
211
+ fs.existsSync.mockReturnValue(false);
212
+ mockGitSuccess("");
213
+ // git checkout -b fails (branch exists)
214
+ mockGitError("fatal: A branch named 'feat/existing' already exists");
215
+ // git checkout (plain) succeeds
216
+ mockGitSuccess("");
217
+ const info = await workspace.create({
218
+ projectId: "proj",
219
+ sessionId: "sess",
220
+ branch: "feat/existing",
221
+ project: makeProject(),
222
+ });
223
+ // Fourth call: plain checkout
224
+ expect(mockExecFileAsync).toHaveBeenNthCalledWith(4, "git", ["checkout", "feat/existing"], {
225
+ cwd: "/mock-home/.ao-clones/proj/sess",
226
+ });
227
+ expect(recordActivityEventMock).toHaveBeenCalledWith(expect.objectContaining({
228
+ source: "workspace",
229
+ kind: "workspace.branch_collision",
230
+ level: "warn",
231
+ projectId: "proj",
232
+ sessionId: "sess",
233
+ data: expect.objectContaining({
234
+ plugin: "workspace-clone",
235
+ branch: "feat/existing",
236
+ errorMessage: expect.stringContaining("already exists"),
237
+ }),
238
+ }));
239
+ expect(info.branch).toBe("feat/existing");
240
+ });
241
+ it("does not emit branch_collision when checkout -b fails for a non-collision reason", async () => {
242
+ const workspace = create();
243
+ mockGitSuccess("https://github.com/test/repo.git");
244
+ fs.existsSync.mockReturnValue(false);
245
+ mockGitSuccess("");
246
+ // git checkout -b fails for a non-collision reason
247
+ mockGitError("fatal: cannot lock ref 'refs/heads/feat/locked': Permission denied");
248
+ // git checkout (plain) succeeds
249
+ mockGitSuccess("");
250
+ const info = await workspace.create({
251
+ projectId: "proj",
252
+ sessionId: "sess",
253
+ branch: "feat/locked",
254
+ project: makeProject(),
255
+ });
256
+ expect(info.branch).toBe("feat/locked");
257
+ const branchCollisionCalls = recordActivityEventMock.mock.calls.filter(([event]) => event.kind === "workspace.branch_collision");
258
+ expect(branchCollisionCalls).toHaveLength(0);
259
+ });
260
+ it("cleans up partial clone on clone failure", async () => {
261
+ const workspace = create();
262
+ mockGitSuccess("https://github.com/test/repo.git");
263
+ // existsSync: first call for "already exists" check => false
264
+ // second call inside catch for cleanup check => true
265
+ fs.existsSync
266
+ .mockReturnValueOnce(false)
267
+ .mockReturnValueOnce(true);
268
+ // git clone fails
269
+ mockGitError("fatal: could not read from remote repository");
270
+ await expect(workspace.create({
271
+ projectId: "proj",
272
+ sessionId: "sess",
273
+ branch: "feat/branch",
274
+ project: makeProject(),
275
+ })).rejects.toThrow('Failed to clone repo for session "sess"');
276
+ // rmSync should be called to clean up
277
+ expect(fs.rmSync).toHaveBeenCalledWith("/mock-home/.ao-clones/proj/sess", {
278
+ recursive: true,
279
+ force: true,
280
+ });
281
+ });
282
+ it("cleans up clone on checkout failure and throws", async () => {
283
+ const workspace = create();
284
+ mockGitSuccess("https://github.com/test/repo.git");
285
+ fs.existsSync.mockReturnValue(false);
286
+ // git clone succeeds
287
+ mockGitSuccess("");
288
+ // git checkout -b fails
289
+ mockGitError("error: pathspec did not match");
290
+ // git checkout (fallback) also fails
291
+ mockGitError("error: pathspec 'bad-branch' did not match");
292
+ await expect(workspace.create({
293
+ projectId: "proj",
294
+ sessionId: "sess",
295
+ branch: "bad-branch",
296
+ project: makeProject(),
297
+ })).rejects.toThrow('Failed to checkout branch "bad-branch" in clone');
298
+ // rmSync should be called to clean up the orphaned clone
299
+ expect(fs.rmSync).toHaveBeenCalledWith("/mock-home/.ao-clones/proj/sess", {
300
+ recursive: true,
301
+ force: true,
302
+ });
303
+ });
304
+ it("throws if workspace path already exists", async () => {
305
+ const workspace = create();
306
+ mockGitSuccess("https://github.com/test/repo.git");
307
+ // existsSync returns true — path already exists
308
+ fs.existsSync.mockReturnValue(true);
309
+ await expect(workspace.create({
310
+ projectId: "proj",
311
+ sessionId: "sess",
312
+ branch: "feat/branch",
313
+ project: makeProject(),
314
+ })).rejects.toThrow('Workspace path "/mock-home/.ao-clones/proj/sess" already exists for session "sess"');
315
+ });
316
+ it("rejects invalid projectId with special characters", async () => {
317
+ const workspace = create();
318
+ await expect(workspace.create({
319
+ projectId: "bad/project",
320
+ sessionId: "sess",
321
+ branch: "feat/branch",
322
+ project: makeProject(),
323
+ })).rejects.toThrow('Invalid projectId "bad/project"');
324
+ });
325
+ it("rejects projectId with dots", async () => {
326
+ const workspace = create();
327
+ await expect(workspace.create({
328
+ projectId: "bad.project",
329
+ sessionId: "sess",
330
+ branch: "feat/branch",
331
+ project: makeProject(),
332
+ })).rejects.toThrow('Invalid projectId "bad.project"');
333
+ });
334
+ it("rejects invalid sessionId with special characters", async () => {
335
+ const workspace = create();
336
+ await expect(workspace.create({
337
+ projectId: "proj",
338
+ sessionId: "bad session!",
339
+ branch: "feat/branch",
340
+ project: makeProject(),
341
+ })).rejects.toThrow('Invalid sessionId "bad session!"');
342
+ });
343
+ it("rejects sessionId with path traversal", async () => {
344
+ const workspace = create();
345
+ await expect(workspace.create({
346
+ projectId: "proj",
347
+ sessionId: "../escape",
348
+ branch: "feat/branch",
349
+ project: makeProject(),
350
+ })).rejects.toThrow('Invalid sessionId "../escape"');
351
+ });
352
+ it("returns correct WorkspaceInfo", async () => {
353
+ const workspace = create();
354
+ mockGitSuccess("https://github.com/test/repo.git");
355
+ fs.existsSync.mockReturnValue(false);
356
+ mockGitSuccess("");
357
+ mockGitSuccess("");
358
+ const info = await workspace.create({
359
+ projectId: "my-project",
360
+ sessionId: "session-42",
361
+ branch: "feat/awesome",
362
+ project: makeProject(),
363
+ });
364
+ expect(info).toEqual({
365
+ path: "/mock-home/.ao-clones/my-project/session-42",
366
+ branch: "feat/awesome",
367
+ sessionId: "session-42",
368
+ projectId: "my-project",
369
+ });
370
+ });
371
+ it("creates project clone directory with recursive option", async () => {
372
+ const workspace = create();
373
+ mockGitSuccess("https://github.com/test/repo.git");
374
+ fs.existsSync.mockReturnValue(false);
375
+ mockGitSuccess("");
376
+ mockGitSuccess("");
377
+ await workspace.create({
378
+ projectId: "proj",
379
+ sessionId: "sess",
380
+ branch: "feat/branch",
381
+ project: makeProject(),
382
+ });
383
+ expect(fs.mkdirSync).toHaveBeenCalledWith("/mock-home/.ao-clones/proj", { recursive: true });
384
+ });
385
+ it("expands ~ in project path", async () => {
386
+ const workspace = create();
387
+ mockGitSuccess("https://github.com/test/repo.git");
388
+ fs.existsSync.mockReturnValue(false);
389
+ mockGitSuccess("");
390
+ mockGitSuccess("");
391
+ await workspace.create({
392
+ projectId: "proj",
393
+ sessionId: "sess",
394
+ branch: "feat/branch",
395
+ project: makeProject({ path: "~/my-repos/project" }),
396
+ });
397
+ // git remote get-url should use expanded path
398
+ expect(mockExecFileAsync).toHaveBeenNthCalledWith(1, "git", ["remote", "get-url", "origin"], {
399
+ cwd: "/mock-home/my-repos/project",
400
+ });
401
+ });
402
+ });
403
+ // ---------------------------------------------------------------------------
404
+ // workspace.destroy()
405
+ // ---------------------------------------------------------------------------
406
+ describe("workspace.destroy()", () => {
407
+ it("removes directory with rmSync when it exists", async () => {
408
+ const workspace = create();
409
+ fs.existsSync.mockReturnValue(true);
410
+ await workspace.destroy("/mock-home/.ao-clones/proj/sess");
411
+ expect(fs.rmSync).toHaveBeenCalledWith("/mock-home/.ao-clones/proj/sess", {
412
+ recursive: true,
413
+ force: true,
414
+ });
415
+ });
416
+ it("does not throw when directory does not exist", async () => {
417
+ const workspace = create();
418
+ fs.existsSync.mockReturnValue(false);
419
+ await expect(workspace.destroy("/mock-home/.ao-clones/proj/nonexistent")).resolves.toBeUndefined();
420
+ expect(fs.rmSync).not.toHaveBeenCalled();
421
+ });
422
+ });
423
+ // ---------------------------------------------------------------------------
424
+ // workspace.list()
425
+ // ---------------------------------------------------------------------------
426
+ describe("workspace.list()", () => {
427
+ it("returns empty array when project directory does not exist", async () => {
428
+ const workspace = create();
429
+ fs.existsSync.mockReturnValue(false);
430
+ const result = await workspace.list("myproject");
431
+ expect(result).toEqual([]);
432
+ });
433
+ it("returns workspace entries with branch info", async () => {
434
+ const workspace = create();
435
+ fs.existsSync.mockReturnValue(true);
436
+ fs.readdirSync.mockReturnValue([
437
+ { name: "session-1", isDirectory: () => true },
438
+ { name: "session-2", isDirectory: () => true },
439
+ ]);
440
+ // git branch --show-current for each directory
441
+ mockGitSuccess("feat/feature-a");
442
+ mockGitSuccess("feat/feature-b");
443
+ const result = await workspace.list("myproject");
444
+ expect(result).toEqual([
445
+ {
446
+ path: "/mock-home/.ao-clones/myproject/session-1",
447
+ branch: "feat/feature-a",
448
+ sessionId: "session-1",
449
+ projectId: "myproject",
450
+ },
451
+ {
452
+ path: "/mock-home/.ao-clones/myproject/session-2",
453
+ branch: "feat/feature-b",
454
+ sessionId: "session-2",
455
+ projectId: "myproject",
456
+ },
457
+ ]);
458
+ // Verify git branch --show-current was called for each entry
459
+ expect(mockExecFileAsync).toHaveBeenNthCalledWith(1, "git", ["branch", "--show-current"], {
460
+ cwd: "/mock-home/.ao-clones/myproject/session-1",
461
+ });
462
+ expect(mockExecFileAsync).toHaveBeenNthCalledWith(2, "git", ["branch", "--show-current"], {
463
+ cwd: "/mock-home/.ao-clones/myproject/session-2",
464
+ });
465
+ });
466
+ it("skips non-directory entries", async () => {
467
+ const workspace = create();
468
+ fs.existsSync.mockReturnValue(true);
469
+ fs.readdirSync.mockReturnValue([
470
+ { name: "session-1", isDirectory: () => true },
471
+ { name: "some-file.txt", isDirectory: () => false },
472
+ { name: ".DS_Store", isDirectory: () => false },
473
+ ]);
474
+ // Only one git call for the single directory
475
+ mockGitSuccess("main");
476
+ const result = await workspace.list("myproject");
477
+ expect(result).toHaveLength(1);
478
+ expect(result[0].sessionId).toBe("session-1");
479
+ expect(mockExecFileAsync).toHaveBeenCalledTimes(1);
480
+ });
481
+ it("skips invalid git repos with console warning", async () => {
482
+ const workspace = create();
483
+ fs.existsSync.mockReturnValue(true);
484
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
485
+ fs.readdirSync.mockReturnValue([
486
+ { name: "valid-session", isDirectory: () => true },
487
+ { name: "corrupt-session", isDirectory: () => true },
488
+ ]);
489
+ // First directory succeeds
490
+ mockGitSuccess("feat/working");
491
+ // Second directory fails (not a valid git repo)
492
+ mockGitError("fatal: not a git repository");
493
+ const result = await workspace.list("myproject");
494
+ expect(result).toHaveLength(1);
495
+ expect(result[0].sessionId).toBe("valid-session");
496
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('[workspace-clone] Skipping "corrupt-session"'));
497
+ warnSpy.mockRestore();
498
+ });
499
+ it("emits corrupt_clone_skipped only once per clone path", async () => {
500
+ const workspace = create();
501
+ fs.existsSync.mockReturnValue(true);
502
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
503
+ fs.readdirSync.mockReturnValue([
504
+ { name: "corrupt-repeat", isDirectory: () => true },
505
+ ]);
506
+ mockGitError("fatal: not a git repository");
507
+ mockGitError("fatal: not a git repository");
508
+ await expect(workspace.list("myproject")).resolves.toEqual([]);
509
+ await expect(workspace.list("myproject")).resolves.toEqual([]);
510
+ const corruptCloneCalls = recordActivityEventMock.mock.calls.filter(([event]) => event.kind === "workspace.corrupt_clone_skipped");
511
+ expect(corruptCloneCalls).toHaveLength(1);
512
+ expect(corruptCloneCalls[0][0]).toEqual(expect.objectContaining({
513
+ projectId: "myproject",
514
+ sessionId: "corrupt-repeat",
515
+ source: "workspace",
516
+ kind: "workspace.corrupt_clone_skipped",
517
+ data: expect.objectContaining({
518
+ clonePath: "/mock-home/.ao-clones/myproject/corrupt-repeat",
519
+ }),
520
+ }));
521
+ warnSpy.mockRestore();
522
+ });
523
+ it("rejects invalid projectId with special characters", async () => {
524
+ const workspace = create();
525
+ await expect(workspace.list("bad/project")).rejects.toThrow('Invalid projectId "bad/project"');
526
+ });
527
+ it("rejects projectId with spaces", async () => {
528
+ const workspace = create();
529
+ await expect(workspace.list("bad project")).rejects.toThrow('Invalid projectId "bad project"');
530
+ });
531
+ });
532
+ // ---------------------------------------------------------------------------
533
+ // workspace.postCreate()
534
+ // ---------------------------------------------------------------------------
535
+ describe("workspace.postCreate()", () => {
536
+ it("runs each postCreate command using getShell()", async () => {
537
+ const workspace = create();
538
+ const info = {
539
+ path: "/mock-home/.ao-clones/proj/sess",
540
+ branch: "feat/branch",
541
+ sessionId: "sess",
542
+ projectId: "proj",
543
+ };
544
+ const project = makeProject({
545
+ postCreate: ["pnpm install", "pnpm build"],
546
+ });
547
+ mockGetShell.mockReturnValue({ cmd: "sh", args: (c) => ["-c", c] });
548
+ // Two commands
549
+ mockGitSuccess("");
550
+ mockGitSuccess("");
551
+ await workspace.postCreate(info, project);
552
+ expect(mockGetShell).toHaveBeenCalled();
553
+ expect(mockExecFileAsync).toHaveBeenCalledTimes(2);
554
+ expect(mockExecFileAsync).toHaveBeenNthCalledWith(1, "sh", ["-c", "pnpm install"], {
555
+ cwd: "/mock-home/.ao-clones/proj/sess",
556
+ });
557
+ expect(mockExecFileAsync).toHaveBeenNthCalledWith(2, "sh", ["-c", "pnpm build"], {
558
+ cwd: "/mock-home/.ao-clones/proj/sess",
559
+ });
560
+ });
561
+ it("uses Windows shell (pwsh) when getShell returns pwsh", async () => {
562
+ const workspace = create();
563
+ const info = {
564
+ path: "/mock-home/.ao-clones/proj/sess",
565
+ branch: "feat/branch",
566
+ sessionId: "sess",
567
+ projectId: "proj",
568
+ };
569
+ const project = makeProject({ postCreate: ["npm install"] });
570
+ mockGetShell.mockReturnValueOnce({
571
+ cmd: "pwsh",
572
+ args: (c) => ["-NoLogo", "-NonInteractive", "-Command", c],
573
+ });
574
+ mockGitSuccess("");
575
+ await workspace.postCreate(info, project);
576
+ expect(mockExecFileAsync).toHaveBeenCalledWith("pwsh", ["-NoLogo", "-NonInteractive", "-Command", "npm install"], { cwd: "/mock-home/.ao-clones/proj/sess" });
577
+ });
578
+ it("does nothing when postCreate is undefined", async () => {
579
+ const workspace = create();
580
+ const info = {
581
+ path: "/mock-home/.ao-clones/proj/sess",
582
+ branch: "feat/branch",
583
+ sessionId: "sess",
584
+ projectId: "proj",
585
+ };
586
+ const project = makeProject(); // no postCreate
587
+ await workspace.postCreate(info, project);
588
+ expect(mockExecFileAsync).not.toHaveBeenCalled();
589
+ });
590
+ it("does nothing when postCreate is empty array", async () => {
591
+ const workspace = create();
592
+ const info = {
593
+ path: "/mock-home/.ao-clones/proj/sess",
594
+ branch: "feat/branch",
595
+ sessionId: "sess",
596
+ projectId: "proj",
597
+ };
598
+ const project = makeProject({ postCreate: [] });
599
+ await workspace.postCreate(info, project);
600
+ expect(mockExecFileAsync).not.toHaveBeenCalled();
601
+ });
602
+ });
603
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type Workspace } from "@made-by-moonlight/athene-core";
2
+ export declare const manifest: {
3
+ name: string;
4
+ slot: "workspace";
5
+ description: string;
6
+ version: string;
7
+ };
8
+ export declare function create(config?: Record<string, unknown>): Workspace;
9
+ declare const _default: {
10
+ manifest: {
11
+ name: string;
12
+ slot: "workspace";
13
+ description: string;
14
+ version: string;
15
+ };
16
+ create: typeof create;
17
+ };
18
+ export default _default;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAKL,KAAK,SAAS,EAGf,MAAM,gCAAgC,CAAC;AAIxC,eAAO,MAAM,QAAQ;;;;;CAKpB,CAAC;AAmCF,wBAAgB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAuOlE;;;;;;;;;;AAED,wBAAsE"}
package/dist/index.js ADDED
@@ -0,0 +1,260 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import { existsSync, rmSync, mkdirSync, readdirSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { homedir } from "node:os";
6
+ import { getShell, recordActivityEvent, } from "@made-by-moonlight/athene-core";
7
+ const execFileAsync = promisify(execFile);
8
+ export const manifest = {
9
+ name: "clone",
10
+ slot: "workspace",
11
+ description: "Workspace plugin: git clone isolation",
12
+ version: "0.1.0",
13
+ };
14
+ /** Run a git command in a given directory */
15
+ async function git(cwd, ...args) {
16
+ const { stdout } = await execFileAsync("git", args, { cwd });
17
+ return stdout.trimEnd();
18
+ }
19
+ /** Only allow safe characters in path segments to prevent directory traversal */
20
+ const SAFE_PATH_SEGMENT = /^[a-zA-Z0-9_-]+$/;
21
+ function assertSafePathSegment(value, label) {
22
+ if (!SAFE_PATH_SEGMENT.test(value)) {
23
+ throw new Error(`Invalid ${label} "${value}": must match ${SAFE_PATH_SEGMENT}`);
24
+ }
25
+ }
26
+ /** Expand ~ to home directory */
27
+ function expandPath(p) {
28
+ if (p.startsWith("~/")) {
29
+ return join(homedir(), p.slice(2));
30
+ }
31
+ return p;
32
+ }
33
+ function getErrorMessage(err) {
34
+ return err instanceof Error ? err.message : String(err);
35
+ }
36
+ function isBranchAlreadyExistsError(err) {
37
+ return getErrorMessage(err).toLowerCase().includes("already exists");
38
+ }
39
+ const emittedCorruptClonePaths = new Set();
40
+ export function create(config) {
41
+ const cloneBaseDir = config?.cloneDir
42
+ ? expandPath(config.cloneDir)
43
+ : join(homedir(), ".ao-clones");
44
+ return {
45
+ name: "clone",
46
+ async create(cfg) {
47
+ assertSafePathSegment(cfg.projectId, "projectId");
48
+ assertSafePathSegment(cfg.sessionId, "sessionId");
49
+ const repoPath = expandPath(cfg.project.path);
50
+ const projectCloneDir = join(cloneBaseDir, cfg.projectId);
51
+ const clonePath = join(projectCloneDir, cfg.sessionId);
52
+ mkdirSync(projectCloneDir, { recursive: true });
53
+ // Get the remote URL from the source repo
54
+ let remoteUrl;
55
+ try {
56
+ remoteUrl = await git(repoPath, "remote", "get-url", "origin");
57
+ }
58
+ catch {
59
+ // Fallback: use the local path as source
60
+ remoteUrl = repoPath;
61
+ }
62
+ // Fail early if destination already exists — avoid deleting a pre-existing
63
+ // workspace in the error handler below
64
+ if (existsSync(clonePath)) {
65
+ throw new Error(`Workspace path "${clonePath}" already exists for session "${cfg.sessionId}" — destroy it before re-creating`);
66
+ }
67
+ // Clone using --reference for faster clone with shared objects
68
+ try {
69
+ await execFileAsync("git", [
70
+ "clone",
71
+ "--reference",
72
+ repoPath,
73
+ "--branch",
74
+ cfg.project.defaultBranch,
75
+ remoteUrl,
76
+ clonePath,
77
+ ]);
78
+ }
79
+ catch (cloneErr) {
80
+ // Clone failed — clean up any partial directory left on disk
81
+ if (existsSync(clonePath)) {
82
+ rmSync(clonePath, { recursive: true, force: true });
83
+ }
84
+ const msg = cloneErr instanceof Error ? cloneErr.message : String(cloneErr);
85
+ throw new Error(`Failed to clone repo for session "${cfg.sessionId}": ${msg}`, {
86
+ cause: cloneErr,
87
+ });
88
+ }
89
+ // Create and checkout the feature branch
90
+ try {
91
+ await git(clonePath, "checkout", "-b", cfg.branch);
92
+ }
93
+ catch (branchErr) {
94
+ // Branch may exist on remote — try plain checkout, but only label it
95
+ // as a branch_collision when git reported the distinct collision shape.
96
+ if (isBranchAlreadyExistsError(branchErr)) {
97
+ recordActivityEvent({
98
+ projectId: cfg.projectId,
99
+ sessionId: cfg.sessionId,
100
+ source: "workspace",
101
+ kind: "workspace.branch_collision",
102
+ level: "warn",
103
+ summary: `branch "${cfg.branch}" already exists; falling back to checkout`,
104
+ data: {
105
+ plugin: "workspace-clone",
106
+ branch: cfg.branch,
107
+ errorMessage: getErrorMessage(branchErr),
108
+ },
109
+ });
110
+ }
111
+ try {
112
+ await git(clonePath, "checkout", cfg.branch);
113
+ }
114
+ catch (checkoutErr) {
115
+ // Both checkout attempts failed — clean up the orphaned clone
116
+ rmSync(clonePath, { recursive: true, force: true });
117
+ const msg = checkoutErr instanceof Error ? checkoutErr.message : String(checkoutErr);
118
+ throw new Error(`Failed to checkout branch "${cfg.branch}" in clone: ${msg}`, {
119
+ cause: checkoutErr,
120
+ });
121
+ }
122
+ }
123
+ return {
124
+ path: clonePath,
125
+ branch: cfg.branch,
126
+ sessionId: cfg.sessionId,
127
+ projectId: cfg.projectId,
128
+ };
129
+ },
130
+ async destroy(workspacePath) {
131
+ if (existsSync(workspacePath)) {
132
+ rmSync(workspacePath, { recursive: true, force: true });
133
+ }
134
+ },
135
+ async list(projectId) {
136
+ assertSafePathSegment(projectId, "projectId");
137
+ const projectCloneDir = join(cloneBaseDir, projectId);
138
+ if (!existsSync(projectCloneDir))
139
+ return [];
140
+ const entries = readdirSync(projectCloneDir, { withFileTypes: true });
141
+ const infos = [];
142
+ for (const entry of entries) {
143
+ if (!entry.isDirectory())
144
+ continue;
145
+ const clonePath = join(projectCloneDir, entry.name);
146
+ let branch;
147
+ try {
148
+ branch = await git(clonePath, "branch", "--show-current");
149
+ }
150
+ catch (err) {
151
+ // Warn about corrupted clones instead of silently skipping.
152
+ // RCA: "session shows up on disk but isn't returned by list()".
153
+ const msg = err instanceof Error ? err.message : String(err);
154
+ // eslint-disable-next-line no-console -- expected diagnostic for corrupted clones
155
+ console.warn(`[workspace-clone] Skipping "${entry.name}": not a valid git repo (${msg})`);
156
+ if (!emittedCorruptClonePaths.has(clonePath)) {
157
+ emittedCorruptClonePaths.add(clonePath);
158
+ recordActivityEvent({
159
+ projectId,
160
+ sessionId: entry.name,
161
+ source: "workspace",
162
+ kind: "workspace.corrupt_clone_skipped",
163
+ level: "warn",
164
+ summary: `skipped corrupt clone "${entry.name}"`,
165
+ data: {
166
+ plugin: "workspace-clone",
167
+ clonePath,
168
+ errorMessage: msg,
169
+ },
170
+ });
171
+ }
172
+ continue;
173
+ }
174
+ infos.push({
175
+ path: clonePath,
176
+ branch,
177
+ sessionId: entry.name,
178
+ projectId,
179
+ });
180
+ }
181
+ return infos;
182
+ },
183
+ async exists(workspacePath) {
184
+ if (!existsSync(workspacePath))
185
+ return false;
186
+ try {
187
+ await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], {
188
+ cwd: workspacePath,
189
+ timeout: 30_000,
190
+ });
191
+ return true;
192
+ }
193
+ catch {
194
+ return false;
195
+ }
196
+ },
197
+ async restore(cfg, workspacePath) {
198
+ const repoPath = expandPath(cfg.project.path);
199
+ // Get remote URL
200
+ let remoteUrl;
201
+ try {
202
+ remoteUrl = await git(repoPath, "remote", "get-url", "origin");
203
+ }
204
+ catch {
205
+ remoteUrl = repoPath;
206
+ }
207
+ // Clone fresh — clean up partial directory on failure
208
+ try {
209
+ await execFileAsync("git", [
210
+ "clone",
211
+ "--reference",
212
+ repoPath,
213
+ "--branch",
214
+ cfg.project.defaultBranch,
215
+ remoteUrl,
216
+ workspacePath,
217
+ ]);
218
+ }
219
+ catch (cloneErr) {
220
+ rmSync(workspacePath, { recursive: true, force: true });
221
+ const msg = cloneErr instanceof Error ? cloneErr.message : String(cloneErr);
222
+ throw new Error(`Clone failed during restore: ${msg}`, { cause: cloneErr });
223
+ }
224
+ // Try to checkout the branch
225
+ try {
226
+ await git(workspacePath, "checkout", cfg.branch);
227
+ }
228
+ catch {
229
+ try {
230
+ await git(workspacePath, "checkout", "-b", cfg.branch);
231
+ }
232
+ catch (checkoutErr) {
233
+ rmSync(workspacePath, { recursive: true, force: true });
234
+ const msg = checkoutErr instanceof Error ? checkoutErr.message : String(checkoutErr);
235
+ throw new Error(`Failed to checkout branch "${cfg.branch}" during restore: ${msg}`, {
236
+ cause: checkoutErr,
237
+ });
238
+ }
239
+ }
240
+ return {
241
+ path: workspacePath,
242
+ branch: cfg.branch,
243
+ sessionId: cfg.sessionId,
244
+ projectId: cfg.projectId,
245
+ };
246
+ },
247
+ async postCreate(info, project) {
248
+ // Run postCreate hooks
249
+ // NOTE: commands run with full shell privileges — they come from trusted YAML config
250
+ if (project.postCreate) {
251
+ const shell = getShell();
252
+ for (const command of project.postCreate) {
253
+ await execFileAsync(shell.cmd, shell.args(command), { cwd: info.path });
254
+ }
255
+ }
256
+ },
257
+ };
258
+ }
259
+ export default { manifest, create };
260
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@made-by-moonlight/athene-plugin-workspace-clone",
3
+ "version": "0.9.1",
4
+ "description": "Workspace plugin: git clone",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/slievr/Athene.git",
21
+ "directory": "packages/plugins/workspace-clone"
22
+ },
23
+ "homepage": "https://github.com/slievr/Athene",
24
+ "bugs": {
25
+ "url": "https://github.com/slievr/Athene/issues"
26
+ },
27
+ "engines": {
28
+ "node": ">=20.0.0"
29
+ },
30
+ "dependencies": {
31
+ "@made-by-moonlight/athene-core": "0.9.1"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^25.2.3",
35
+ "typescript": "^5.7.0",
36
+ "vitest": "^3.0.0"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "typecheck": "tsc --noEmit",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "clean": "rm -rf dist"
47
+ }
48
+ }