@agentmeshhq/agent 0.2.1 → 0.3.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 (62) hide show
  1. package/dist/__tests__/context-template.test.d.ts +4 -0
  2. package/dist/__tests__/context-template.test.js +233 -0
  3. package/dist/__tests__/context-template.test.js.map +1 -0
  4. package/dist/__tests__/loader.test.js +140 -28
  5. package/dist/__tests__/loader.test.js.map +1 -1
  6. package/dist/__tests__/no-respawn.test.d.ts +1 -0
  7. package/dist/__tests__/no-respawn.test.js +254 -0
  8. package/dist/__tests__/no-respawn.test.js.map +1 -0
  9. package/dist/__tests__/onboard.test.d.ts +5 -0
  10. package/dist/__tests__/onboard.test.js +341 -0
  11. package/dist/__tests__/onboard.test.js.map +1 -0
  12. package/dist/__tests__/shared-resource-guards.test.d.ts +7 -0
  13. package/dist/__tests__/shared-resource-guards.test.js +260 -0
  14. package/dist/__tests__/shared-resource-guards.test.js.map +1 -0
  15. package/dist/cli/inbox.d.ts +5 -0
  16. package/dist/cli/inbox.js +123 -0
  17. package/dist/cli/inbox.js.map +1 -0
  18. package/dist/cli/index.js +0 -0
  19. package/dist/cli/issue.d.ts +42 -0
  20. package/dist/cli/issue.js +297 -0
  21. package/dist/cli/issue.js.map +1 -0
  22. package/dist/cli/ready.d.ts +5 -0
  23. package/dist/cli/ready.js +131 -0
  24. package/dist/cli/ready.js.map +1 -0
  25. package/dist/cli/sync.d.ts +8 -0
  26. package/dist/cli/sync.js +154 -0
  27. package/dist/cli/sync.js.map +1 -0
  28. package/dist/config/loader.d.ts +0 -4
  29. package/dist/config/loader.js +102 -42
  30. package/dist/config/loader.js.map +1 -1
  31. package/dist/config/schema.d.ts +2 -2
  32. package/dist/core/daemon/context-template.d.ts +11 -0
  33. package/dist/core/daemon/context-template.js +144 -0
  34. package/dist/core/daemon/context-template.js.map +1 -0
  35. package/dist/core/daemon/crash-log.d.ts +0 -2
  36. package/dist/core/daemon/crash-log.js +0 -1
  37. package/dist/core/daemon/crash-log.js.map +1 -1
  38. package/dist/core/daemon/git-auth.d.ts +18 -0
  39. package/dist/core/daemon/git-auth.js +88 -0
  40. package/dist/core/daemon/git-auth.js.map +1 -0
  41. package/dist/core/daemon/health-policy.d.ts +0 -4
  42. package/dist/core/daemon/health-policy.js +0 -8
  43. package/dist/core/daemon/health-policy.js.map +1 -1
  44. package/dist/core/daemon/state.js +1 -0
  45. package/dist/core/daemon/state.js.map +1 -1
  46. package/dist/core/daemon/workspace.d.ts +13 -0
  47. package/dist/core/daemon/workspace.js +39 -0
  48. package/dist/core/daemon/workspace.js.map +1 -1
  49. package/dist/core/daemon.d.ts +9 -6
  50. package/dist/core/daemon.js +206 -185
  51. package/dist/core/daemon.js.map +1 -1
  52. package/dist/core/injector.d.ts +5 -1
  53. package/dist/core/injector.js +77 -0
  54. package/dist/core/injector.js.map +1 -1
  55. package/dist/core/issue-cache.d.ts +44 -0
  56. package/dist/core/issue-cache.js +75 -0
  57. package/dist/core/issue-cache.js.map +1 -0
  58. package/dist/core/registry.d.ts +62 -0
  59. package/dist/core/registry.js +18 -0
  60. package/dist/core/registry.js.map +1 -1
  61. package/package.json +12 -11
  62. package/LICENSE +0 -21
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Stress tests verifying auto-respawn logic has been completely removed.
3
+ *
4
+ * These tests exercise:
5
+ * - health-policy no longer exports shouldResetRestartCount
6
+ * - crash-log no longer accepts restartCount / maxRestartAttempts
7
+ * - AgentState schema no longer carries restartCount
8
+ * - loader no longer exports resetAgentRestartCount
9
+ * - handleSessionDeath marks failed immediately (no restart branch)
10
+ * - handleStuckAgent nudges but never triggers restart
11
+ */
12
+ import { describe, expect, it } from "vitest";
13
+ import * as loader from "../config/loader.js";
14
+ import { formatCrashLog } from "../core/daemon/crash-log.js";
15
+ import * as healthPolicy from "../core/daemon/health-policy.js";
16
+ // ---------------------------------------------------------------------------
17
+ // 1. health-policy: shouldResetRestartCount removed
18
+ // ---------------------------------------------------------------------------
19
+ describe("health-policy: no restart helpers", () => {
20
+ it("should NOT export shouldResetRestartCount", () => {
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ expect(healthPolicy.shouldResetRestartCount).toBeUndefined();
23
+ });
24
+ it("should still export getStuckDetail", () => {
25
+ expect(typeof healthPolicy.getStuckDetail).toBe("function");
26
+ expect(healthPolicy.getStuckDetail({ status: "stuck", details: "idle 5m" })).toBe("idle 5m");
27
+ });
28
+ it("should still export getNudgeMessage", () => {
29
+ expect(typeof healthPolicy.getNudgeMessage).toBe("function");
30
+ const msg = healthPolicy.getNudgeMessage({ status: "permission_blocked" });
31
+ expect(msg).toContain("alternative approach");
32
+ });
33
+ it("should still export isWithinNudgeWaitWindow", () => {
34
+ expect(typeof healthPolicy.isWithinNudgeWaitWindow).toBe("function");
35
+ const now = new Date();
36
+ // Nudge sent 30s ago, window is 120s — should be within window
37
+ const nudgeSentAt = new Date(now.getTime() - 30_000);
38
+ expect(healthPolicy.isWithinNudgeWaitWindow(nudgeSentAt, 120_000, now)).toBe(true);
39
+ // Nudge sent 150s ago — outside window
40
+ const oldNudge = new Date(now.getTime() - 150_000);
41
+ expect(healthPolicy.isWithinNudgeWaitWindow(oldNudge, 120_000, now)).toBe(false);
42
+ // No nudge sent
43
+ expect(healthPolicy.isWithinNudgeWaitWindow(null, 120_000, now)).toBe(false);
44
+ });
45
+ });
46
+ // ---------------------------------------------------------------------------
47
+ // 2. crash-log: no restart fields
48
+ // ---------------------------------------------------------------------------
49
+ describe("crash-log: no restart fields", () => {
50
+ const baseInput = {
51
+ timestamp: "2025-01-15T12:00:00Z",
52
+ agentName: "test-agent",
53
+ agentId: "agent-123",
54
+ reason: "session_died",
55
+ sandboxLabel: "none",
56
+ workdir: "/tmp/work",
57
+ model: "claude-sonnet-4",
58
+ lastOutput: "some output",
59
+ };
60
+ it("should format crash log without restart count line", () => {
61
+ const log = formatCrashLog(baseInput);
62
+ expect(log).toContain("AGENT CRASH DETECTED");
63
+ expect(log).toContain("Reason: session_died");
64
+ expect(log).toContain("Agent: test-agent");
65
+ // Must NOT contain restart count
66
+ expect(log).not.toContain("Restart Count:");
67
+ });
68
+ it("CrashLogInput should not accept restartCount at type level", () => {
69
+ // If someone tries to pass restartCount, TS would error.
70
+ // At runtime we verify the interface shape:
71
+ const keys = Object.keys(baseInput);
72
+ expect(keys).not.toContain("restartCount");
73
+ expect(keys).not.toContain("maxRestartAttempts");
74
+ });
75
+ it("should handle all reason strings without restart logic", () => {
76
+ const reasons = ["unknown", "session_died", "stuck_after_nudge", "container_exited", "oom"];
77
+ for (const reason of reasons) {
78
+ const log = formatCrashLog({ ...baseInput, reason });
79
+ expect(log).toContain(`Reason: ${reason}`);
80
+ expect(log).not.toContain("Restart Count:");
81
+ }
82
+ });
83
+ it("should handle missing optional fields gracefully", () => {
84
+ const minimalInput = {
85
+ timestamp: "2025-01-15T12:00:00Z",
86
+ agentName: "minimal",
87
+ agentId: null,
88
+ reason: "crash",
89
+ sandboxLabel: "none",
90
+ model: "claude-sonnet-4",
91
+ lastOutput: "",
92
+ };
93
+ const log = formatCrashLog(minimalInput);
94
+ expect(log).toContain("Agent: minimal");
95
+ expect(log).toContain("Agent ID: null");
96
+ expect(log).not.toContain("Restart Count:");
97
+ });
98
+ });
99
+ // ---------------------------------------------------------------------------
100
+ // 3. AgentState schema: no restartCount field
101
+ // ---------------------------------------------------------------------------
102
+ describe("AgentState schema: no restartCount", () => {
103
+ it("should allow creating state without restartCount", () => {
104
+ const state = {
105
+ name: "test",
106
+ agentId: "a-1",
107
+ pid: 123,
108
+ tmuxSession: "s",
109
+ startedAt: "2025-01-01T00:00:00Z",
110
+ status: "running",
111
+ };
112
+ // restartCount should not be a key
113
+ expect("restartCount" in state).toBe(false);
114
+ // childPids, stuckSince, lastRestartAt should still be valid optional fields
115
+ const withOptionals = {
116
+ ...state,
117
+ childPids: [100, 200],
118
+ stuckSince: "2025-01-01T01:00:00Z",
119
+ lastRestartAt: "2025-01-01T00:30:00Z",
120
+ };
121
+ expect(withOptionals.childPids).toEqual([100, 200]);
122
+ expect(withOptionals.stuckSince).toBeDefined();
123
+ expect(withOptionals.lastRestartAt).toBeDefined();
124
+ });
125
+ it("should still support all valid AgentStatus values", () => {
126
+ const statuses = ["running", "stopped", "failed", "stuck", "waiting"];
127
+ for (const status of statuses) {
128
+ const state = {
129
+ name: "t",
130
+ agentId: "a",
131
+ pid: 1,
132
+ tmuxSession: "s",
133
+ startedAt: "2025-01-01T00:00:00Z",
134
+ status,
135
+ };
136
+ expect(state.status).toBe(status);
137
+ }
138
+ });
139
+ });
140
+ // ---------------------------------------------------------------------------
141
+ // 4. loader: no resetAgentRestartCount export
142
+ // ---------------------------------------------------------------------------
143
+ describe("loader: no restart helpers", () => {
144
+ it("should NOT export resetAgentRestartCount", () => {
145
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
146
+ expect(loader.resetAgentRestartCount).toBeUndefined();
147
+ });
148
+ it("should still export core functions", () => {
149
+ expect(typeof loader.getAgentState).toBe("function");
150
+ expect(typeof loader.updateAgentInState).toBe("function");
151
+ expect(typeof loader.addAgentToState).toBe("function");
152
+ expect(typeof loader.removeAgentFromState).toBe("function");
153
+ expect(typeof loader.loadState).toBe("function");
154
+ expect(typeof loader.loadConfig).toBe("function");
155
+ });
156
+ });
157
+ // ---------------------------------------------------------------------------
158
+ // 5. Stress: rapid-fire health-policy calls (simulate 60s health monitor ticks)
159
+ // ---------------------------------------------------------------------------
160
+ describe("health-policy stress: repeated calls", () => {
161
+ it("getStuckDetail handles 1000 rapid calls with varied inputs", () => {
162
+ const inputs = [
163
+ { status: "stuck", details: "idle", blockedOn: "tool_call" },
164
+ { status: "stuck", blockedOn: "permission" },
165
+ { status: "stuck" },
166
+ { status: "permission_blocked", details: "awaiting approval" },
167
+ ];
168
+ for (let i = 0; i < 1000; i++) {
169
+ const input = inputs[i % inputs.length];
170
+ const result = healthPolicy.getStuckDetail(input);
171
+ expect(typeof result).toBe("string");
172
+ expect(result.length).toBeGreaterThan(0);
173
+ }
174
+ });
175
+ it("getNudgeMessage handles 1000 rapid calls", () => {
176
+ for (let i = 0; i < 1000; i++) {
177
+ const status = i % 2 === 0 ? "permission_blocked" : "stuck";
178
+ const msg = healthPolicy.getNudgeMessage({ status });
179
+ expect(typeof msg).toBe("string");
180
+ expect(msg.length).toBeGreaterThan(0);
181
+ }
182
+ });
183
+ it("isWithinNudgeWaitWindow handles boundary conditions", () => {
184
+ const now = new Date();
185
+ const windowMs = 120_000;
186
+ // Exactly at boundary
187
+ const exactBoundary = new Date(now.getTime() - windowMs);
188
+ expect(healthPolicy.isWithinNudgeWaitWindow(exactBoundary, windowMs, now)).toBe(false);
189
+ // 1ms before boundary (still within)
190
+ const justInside = new Date(now.getTime() - windowMs + 1);
191
+ expect(healthPolicy.isWithinNudgeWaitWindow(justInside, windowMs, now)).toBe(true);
192
+ // 1ms after boundary (outside)
193
+ const justOutside = new Date(now.getTime() - windowMs - 1);
194
+ expect(healthPolicy.isWithinNudgeWaitWindow(justOutside, windowMs, now)).toBe(false);
195
+ // Future nudge (edge case — should be within window)
196
+ const futureNudge = new Date(now.getTime() + 10_000);
197
+ expect(healthPolicy.isWithinNudgeWaitWindow(futureNudge, windowMs, now)).toBe(true);
198
+ // Zero window
199
+ const recent = new Date(now.getTime() - 1);
200
+ expect(healthPolicy.isWithinNudgeWaitWindow(recent, 0, now)).toBe(false);
201
+ });
202
+ });
203
+ // ---------------------------------------------------------------------------
204
+ // 6. Stress: crash-log formatting under load
205
+ // ---------------------------------------------------------------------------
206
+ describe("crash-log stress: rapid formatting", () => {
207
+ it("formats 500 crash logs without errors or restart references", () => {
208
+ for (let i = 0; i < 500; i++) {
209
+ const log = formatCrashLog({
210
+ timestamp: new Date().toISOString(),
211
+ agentName: `agent-${i}`,
212
+ agentId: `id-${i}`,
213
+ reason: i % 3 === 0 ? "session_died" : i % 3 === 1 ? "stuck_after_nudge" : "unknown",
214
+ sandboxLabel: i % 2 === 0 ? "none" : `container-${i}`,
215
+ workdir: `/tmp/work-${i}`,
216
+ model: "claude-sonnet-4",
217
+ lastOutput: `output line ${i}\n`.repeat(10),
218
+ });
219
+ expect(log).toContain("AGENT CRASH DETECTED");
220
+ expect(log).not.toContain("Restart Count:");
221
+ expect(log).toContain(`Agent: agent-${i}`);
222
+ }
223
+ });
224
+ it("handles very long lastOutput without crash", () => {
225
+ const longOutput = "x".repeat(100_000);
226
+ const log = formatCrashLog({
227
+ timestamp: "2025-01-15T12:00:00Z",
228
+ agentName: "long-output-agent",
229
+ agentId: "id-long",
230
+ reason: "oom",
231
+ sandboxLabel: "none",
232
+ model: "claude-sonnet-4",
233
+ lastOutput: longOutput,
234
+ });
235
+ expect(log).toContain(longOutput);
236
+ expect(log).not.toContain("Restart Count:");
237
+ });
238
+ it("handles empty/special-character agent names", () => {
239
+ const names = ["", "agent with spaces", "agent-with-émojis-🤖", "agent/with/slashes"];
240
+ for (const name of names) {
241
+ const log = formatCrashLog({
242
+ timestamp: "2025-01-15T12:00:00Z",
243
+ agentName: name,
244
+ agentId: null,
245
+ reason: "crash",
246
+ sandboxLabel: "none",
247
+ model: "claude-sonnet-4",
248
+ lastOutput: "",
249
+ });
250
+ expect(log).toContain(`Agent: ${name}`);
251
+ }
252
+ });
253
+ });
254
+ //# sourceMappingURL=no-respawn.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-respawn.test.js","sourceRoot":"","sources":["../../src/__tests__/no-respawn.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Onboard Tests - Epic #103
3
+ * Tests for git-auth setup/cleanup and onboard message injection.
4
+ */
5
+ export {};
@@ -0,0 +1,341 @@
1
+ /**
2
+ * Onboard Tests - Epic #103
3
+ * Tests for git-auth setup/cleanup and onboard message injection.
4
+ */
5
+ import { execSync } from "node:child_process";
6
+ import * as fs from "node:fs";
7
+ import { beforeEach, describe, expect, it, vi } from "vitest";
8
+ import { cleanupGitAuth, setupGitAuth } from "../core/daemon/git-auth.js";
9
+ import { configureGitIdentity, validatePushAccess } from "../core/daemon/workspace.js";
10
+ import { injectOnboardMessage } from "../core/injector.js";
11
+ // ============================================================================
12
+ // Mock tmux sendKeys
13
+ // ============================================================================
14
+ const { sendKeysMock } = vi.hoisted(() => ({
15
+ sendKeysMock: vi.fn(),
16
+ }));
17
+ vi.mock("../core/tmux.js", () => ({
18
+ sendKeys: sendKeysMock,
19
+ }));
20
+ // ============================================================================
21
+ // Mock child_process for workspace tests
22
+ // ============================================================================
23
+ vi.mock("node:child_process", () => ({
24
+ execSync: vi.fn(),
25
+ }));
26
+ // ============================================================================
27
+ // Mock fs for git-auth tests
28
+ // ============================================================================
29
+ vi.mock("node:fs");
30
+ const mockFs = vi.mocked(fs);
31
+ // ============================================================================
32
+ // injectOnboardMessage tests
33
+ // ============================================================================
34
+ describe("injectOnboardMessage", () => {
35
+ beforeEach(() => {
36
+ vi.clearAllMocks();
37
+ });
38
+ const baseOnboard = {
39
+ agent: {
40
+ agent_id: "agent-123",
41
+ display_name: "test-agent",
42
+ model: "claude-sonnet-4",
43
+ capabilities: ["coding", "review"],
44
+ },
45
+ assignment: {
46
+ assignment_id: "asn-1",
47
+ role: "contributor",
48
+ priority: 8,
49
+ notes: "Primary dev",
50
+ },
51
+ project: {
52
+ project_id: "prj-1",
53
+ name: "TestProject",
54
+ code: "TP",
55
+ description: "A test project",
56
+ workdir: "/workspace",
57
+ instructions: "Follow coding guidelines.",
58
+ workflow_config: {
59
+ branch_prefix: "feat/",
60
+ pr_target_branch: "dev",
61
+ commit_convention: "conventional",
62
+ protected_branches: ["main", "dev"],
63
+ code_review_required: true,
64
+ custom_rules: ["Run tests first"],
65
+ },
66
+ },
67
+ repos: [
68
+ {
69
+ repo_id: "rep-1",
70
+ provider: "github",
71
+ full_name: "org/repo",
72
+ url: "https://github.com/org/repo.git",
73
+ default_branch: "main",
74
+ credential: null,
75
+ },
76
+ ],
77
+ team: [
78
+ {
79
+ agent_id: "agent-456",
80
+ display_name: "review-bot",
81
+ model: "claude-opus-4-5",
82
+ role: "reviewer",
83
+ status: "online",
84
+ },
85
+ ],
86
+ hub_api: {
87
+ handoffs: "POST /api/v1/workspaces/:workspace/handoffs",
88
+ claims: "POST /api/v1/workspaces/:workspace/claims",
89
+ blockers: "POST /api/v1/workspaces/:workspace/blockers",
90
+ inbox: "GET /api/v1/workspaces/:workspace/inbox",
91
+ heartbeat: "POST /api/v1/agents/heartbeat",
92
+ },
93
+ };
94
+ it("injects structured onboard message with all sections", () => {
95
+ injectOnboardMessage("test-agent", baseOnboard);
96
+ expect(sendKeysMock).toHaveBeenCalledTimes(1);
97
+ const message = String(sendKeysMock.mock.calls[0]?.[1] ?? "");
98
+ // Identity section
99
+ expect(message).toContain("test-agent");
100
+ expect(message).toContain("claude-sonnet-4");
101
+ expect(message).toContain("contributor");
102
+ // Project section
103
+ expect(message).toContain("TestProject");
104
+ expect(message).toContain("TP");
105
+ expect(message).toContain("A test project");
106
+ // Repository section
107
+ expect(message).toContain("org/repo");
108
+ expect(message).toContain("github");
109
+ // Workflow rules
110
+ expect(message).toContain("feat/");
111
+ expect(message).toContain("dev");
112
+ expect(message).toContain("conventional");
113
+ expect(message).toContain("Run tests first");
114
+ // Team section
115
+ expect(message).toContain("review-bot");
116
+ expect(message).toContain("reviewer");
117
+ expect(message).toContain("online");
118
+ // Hub API
119
+ expect(message).toContain("handoffs");
120
+ expect(message).toContain("heartbeat");
121
+ // Instructions
122
+ expect(message).toContain("Follow coding guidelines.");
123
+ });
124
+ it("handles agent with no assignment or project", () => {
125
+ const noProject = {
126
+ ...baseOnboard,
127
+ assignment: null,
128
+ project: null,
129
+ repos: [],
130
+ team: [],
131
+ };
132
+ injectOnboardMessage("lonely-agent", noProject);
133
+ expect(sendKeysMock).toHaveBeenCalledTimes(1);
134
+ const message = String(sendKeysMock.mock.calls[0]?.[1] ?? "");
135
+ // Should still have identity
136
+ expect(message).toContain("test-agent");
137
+ expect(message).toContain("claude-sonnet-4");
138
+ // Should NOT have project/team sections content
139
+ expect(message).not.toContain("TestProject");
140
+ expect(message).not.toContain("review-bot");
141
+ });
142
+ it("handles empty custom rules and no instructions", () => {
143
+ const minimal = {
144
+ ...baseOnboard,
145
+ project: {
146
+ ...baseOnboard.project,
147
+ instructions: null,
148
+ workflow_config: {
149
+ ...baseOnboard.project.workflow_config,
150
+ custom_rules: [],
151
+ },
152
+ },
153
+ };
154
+ injectOnboardMessage("test-agent", minimal);
155
+ expect(sendKeysMock).toHaveBeenCalledTimes(1);
156
+ const message = String(sendKeysMock.mock.calls[0]?.[1] ?? "");
157
+ expect(message).not.toContain("Project Instructions");
158
+ });
159
+ });
160
+ // ============================================================================
161
+ // setupGitAuth tests
162
+ // ============================================================================
163
+ describe("setupGitAuth", () => {
164
+ beforeEach(() => {
165
+ vi.clearAllMocks();
166
+ mockFs.existsSync.mockReturnValue(false);
167
+ mockFs.mkdirSync.mockReturnValue(undefined);
168
+ mockFs.writeFileSync.mockReturnValue(undefined);
169
+ mockFs.appendFileSync.mockReturnValue(undefined);
170
+ });
171
+ it("creates credentials directory if missing", () => {
172
+ setupGitAuth({
173
+ type: "pat",
174
+ value: "ghp_test123",
175
+ repoUrl: "https://github.com/org/repo.git",
176
+ agentName: "test-agent",
177
+ });
178
+ expect(mockFs.mkdirSync).toHaveBeenCalledWith(expect.stringContaining("credentials"), expect.objectContaining({ recursive: true, mode: 0o700 }));
179
+ });
180
+ it("configures PAT credential with git-credentials file", () => {
181
+ const result = setupGitAuth({
182
+ type: "pat",
183
+ value: "ghp_test123",
184
+ repoUrl: "https://github.com/org/repo.git",
185
+ agentName: "my-agent",
186
+ });
187
+ // Should write credential file
188
+ expect(mockFs.writeFileSync).toHaveBeenCalledWith(expect.stringContaining("my-agent.git-credentials"), expect.stringContaining("https://x-access-token:ghp_test123@github.com"), expect.objectContaining({ mode: 0o600 }));
189
+ // Should return git config env vars
190
+ expect(result.GIT_CONFIG_KEY_0).toBe("credential.helper");
191
+ expect(result.GIT_CONFIG_VALUE_0).toContain("store");
192
+ expect(result.GIT_CONFIG_VALUE_0).toContain("my-agent.git-credentials");
193
+ });
194
+ it("configures SSH deploy key", () => {
195
+ const sshKey = "-----BEGIN OPENSSH PRIVATE KEY-----\ntest\n-----END OPENSSH PRIVATE KEY-----";
196
+ const result = setupGitAuth({
197
+ type: "ssh_deploy_key",
198
+ value: sshKey,
199
+ repoUrl: "git@github.com:org/repo.git",
200
+ agentName: "ssh-agent",
201
+ });
202
+ // Should write key file with correct permissions
203
+ expect(mockFs.writeFileSync).toHaveBeenCalledWith(expect.stringContaining("ssh-agent.deploy-key"), sshKey, expect.objectContaining({ mode: 0o600 }));
204
+ // Should return GIT_SSH_COMMAND
205
+ expect(result.GIT_SSH_COMMAND).toContain("ssh -i");
206
+ expect(result.GIT_SSH_COMMAND).toContain("ssh-agent.deploy-key");
207
+ expect(result.GIT_SSH_COMMAND).toContain("StrictHostKeyChecking=no");
208
+ });
209
+ it("extracts host from repo URL for PAT", () => {
210
+ setupGitAuth({
211
+ type: "pat",
212
+ value: "token123",
213
+ repoUrl: "https://gitlab.com/org/repo.git",
214
+ agentName: "gitlab-agent",
215
+ });
216
+ expect(mockFs.writeFileSync).toHaveBeenCalledWith(expect.any(String), expect.stringContaining("@gitlab.com"), expect.any(Object));
217
+ });
218
+ it("returns empty object for unknown credential type", () => {
219
+ const result = setupGitAuth({
220
+ type: "unknown_type",
221
+ value: "something",
222
+ repoUrl: "https://github.com/org/repo.git",
223
+ agentName: "test-agent",
224
+ });
225
+ expect(result).toEqual({});
226
+ });
227
+ });
228
+ // ============================================================================
229
+ // cleanupGitAuth tests
230
+ // ============================================================================
231
+ describe("cleanupGitAuth", () => {
232
+ beforeEach(() => {
233
+ vi.clearAllMocks();
234
+ });
235
+ it("removes credential files for an agent", () => {
236
+ mockFs.existsSync.mockReturnValue(true);
237
+ mockFs.unlinkSync.mockReturnValue(undefined);
238
+ cleanupGitAuth("my-agent");
239
+ expect(mockFs.unlinkSync).toHaveBeenCalledTimes(2);
240
+ expect(mockFs.unlinkSync).toHaveBeenCalledWith(expect.stringContaining("my-agent.git-credentials"));
241
+ expect(mockFs.unlinkSync).toHaveBeenCalledWith(expect.stringContaining("my-agent.deploy-key"));
242
+ });
243
+ it("skips files that do not exist", () => {
244
+ mockFs.existsSync.mockReturnValue(false);
245
+ cleanupGitAuth("no-files-agent");
246
+ expect(mockFs.unlinkSync).not.toHaveBeenCalled();
247
+ });
248
+ it("handles unlink errors gracefully", () => {
249
+ mockFs.existsSync.mockReturnValue(true);
250
+ mockFs.unlinkSync.mockImplementation(() => {
251
+ throw new Error("permission denied");
252
+ });
253
+ // Should not throw
254
+ expect(() => cleanupGitAuth("error-agent")).not.toThrow();
255
+ });
256
+ });
257
+ // ============================================================================
258
+ // fetchOnboard type tests
259
+ // ============================================================================
260
+ describe("OnboardData types", () => {
261
+ it("OnboardData structure is valid", () => {
262
+ const data = {
263
+ agent: {
264
+ agent_id: "id",
265
+ display_name: "name",
266
+ model: "model",
267
+ capabilities: [],
268
+ },
269
+ assignment: null,
270
+ project: null,
271
+ repos: [],
272
+ team: [],
273
+ hub_api: {
274
+ handoffs: "",
275
+ claims: "",
276
+ blockers: "",
277
+ inbox: "",
278
+ heartbeat: "",
279
+ },
280
+ };
281
+ expect(data.agent.agent_id).toBe("id");
282
+ expect(data.assignment).toBeNull();
283
+ expect(data.repos).toHaveLength(0);
284
+ });
285
+ });
286
+ // ============================================================================
287
+ // configureGitIdentity tests
288
+ // ============================================================================
289
+ const mockExecSync = vi.mocked(execSync);
290
+ describe("configureGitIdentity", () => {
291
+ beforeEach(() => {
292
+ vi.clearAllMocks();
293
+ });
294
+ it("sets user.name and user.email via git config", () => {
295
+ mockExecSync.mockReturnValue(Buffer.from(""));
296
+ configureGitIdentity({
297
+ workspacePath: "/workspace",
298
+ agentName: "my-agent",
299
+ agentDisplayName: "My Agent",
300
+ });
301
+ expect(mockExecSync).toHaveBeenCalledWith('git config user.name "My Agent"', expect.objectContaining({ cwd: "/workspace" }));
302
+ expect(mockExecSync).toHaveBeenCalledWith('git config user.email "my-agent@agents.agentmeshhq.dev"', expect.objectContaining({ cwd: "/workspace" }));
303
+ });
304
+ it("handles errors gracefully", () => {
305
+ mockExecSync.mockImplementation(() => {
306
+ throw new Error("not a git repo");
307
+ });
308
+ expect(() => configureGitIdentity({
309
+ workspacePath: "/bad-path",
310
+ agentName: "agent",
311
+ agentDisplayName: "Agent",
312
+ })).not.toThrow();
313
+ });
314
+ });
315
+ // ============================================================================
316
+ // validatePushAccess tests
317
+ // ============================================================================
318
+ describe("validatePushAccess", () => {
319
+ beforeEach(() => {
320
+ vi.clearAllMocks();
321
+ });
322
+ it("returns true when dry-run succeeds", () => {
323
+ mockExecSync.mockReturnValue(Buffer.from(""));
324
+ const result = validatePushAccess("/workspace");
325
+ expect(result).toBe(true);
326
+ expect(mockExecSync).toHaveBeenCalledWith("git push --dry-run origin HEAD", expect.objectContaining({ cwd: "/workspace", timeout: 15_000 }));
327
+ });
328
+ it("returns false when dry-run fails", () => {
329
+ mockExecSync.mockImplementation(() => {
330
+ throw new Error("permission denied");
331
+ });
332
+ const result = validatePushAccess("/workspace");
333
+ expect(result).toBe(false);
334
+ });
335
+ it("uses custom remote branch when provided", () => {
336
+ mockExecSync.mockReturnValue(Buffer.from(""));
337
+ validatePushAccess("/workspace", "feature/test");
338
+ expect(mockExecSync).toHaveBeenCalledWith("git push --dry-run origin feature/test", expect.objectContaining({ cwd: "/workspace" }));
339
+ });
340
+ });
341
+ //# sourceMappingURL=onboard.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboard.test.js","sourceRoot":"","sources":["../../src/__tests__/onboard.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Shared Resource Guards Tests
3
+ *
4
+ * Tests for workdir conflict detection, serve port collision detection,
5
+ * HQ workdir per-agent expansion, and servePort state persistence.
6
+ */
7
+ export {};