@agentmeshhq/agent 0.2.1 → 0.4.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 (65) hide show
  1. package/README.md +6 -0
  2. package/dist/__tests__/context-template.test.d.ts +4 -0
  3. package/dist/__tests__/context-template.test.js +235 -0
  4. package/dist/__tests__/context-template.test.js.map +1 -0
  5. package/dist/__tests__/default-branch-fallback.test.d.ts +10 -0
  6. package/dist/__tests__/default-branch-fallback.test.js +123 -0
  7. package/dist/__tests__/default-branch-fallback.test.js.map +1 -0
  8. package/dist/__tests__/default-repo-fallback.test.d.ts +12 -0
  9. package/dist/__tests__/default-repo-fallback.test.js +156 -0
  10. package/dist/__tests__/default-repo-fallback.test.js.map +1 -0
  11. package/dist/__tests__/loader.test.js +140 -28
  12. package/dist/__tests__/loader.test.js.map +1 -1
  13. package/dist/__tests__/no-respawn.test.d.ts +1 -0
  14. package/dist/__tests__/no-respawn.test.js +254 -0
  15. package/dist/__tests__/no-respawn.test.js.map +1 -0
  16. package/dist/__tests__/onboard.test.d.ts +5 -0
  17. package/dist/__tests__/onboard.test.js +343 -0
  18. package/dist/__tests__/onboard.test.js.map +1 -0
  19. package/dist/__tests__/project-flag.test.d.ts +9 -0
  20. package/dist/__tests__/project-flag.test.js +140 -0
  21. package/dist/__tests__/project-flag.test.js.map +1 -0
  22. package/dist/__tests__/shared-resource-guards.test.d.ts +7 -0
  23. package/dist/__tests__/shared-resource-guards.test.js +260 -0
  24. package/dist/__tests__/shared-resource-guards.test.js.map +1 -0
  25. package/dist/cli/index.js +6 -0
  26. package/dist/cli/index.js.map +1 -1
  27. package/dist/cli/start.d.ts +4 -0
  28. package/dist/cli/start.js +6 -0
  29. package/dist/cli/start.js.map +1 -1
  30. package/dist/config/loader.d.ts +0 -4
  31. package/dist/config/loader.js +102 -42
  32. package/dist/config/loader.js.map +1 -1
  33. package/dist/config/schema.d.ts +2 -2
  34. package/dist/core/daemon/bootstrap.d.ts +4 -0
  35. package/dist/core/daemon/bootstrap.js +2 -0
  36. package/dist/core/daemon/bootstrap.js.map +1 -1
  37. package/dist/core/daemon/context-template.d.ts +11 -0
  38. package/dist/core/daemon/context-template.js +144 -0
  39. package/dist/core/daemon/context-template.js.map +1 -0
  40. package/dist/core/daemon/crash-log.d.ts +0 -2
  41. package/dist/core/daemon/crash-log.js +0 -1
  42. package/dist/core/daemon/crash-log.js.map +1 -1
  43. package/dist/core/daemon/git-auth.d.ts +18 -0
  44. package/dist/core/daemon/git-auth.js +94 -0
  45. package/dist/core/daemon/git-auth.js.map +1 -0
  46. package/dist/core/daemon/health-policy.d.ts +0 -4
  47. package/dist/core/daemon/health-policy.js +0 -8
  48. package/dist/core/daemon/health-policy.js.map +1 -1
  49. package/dist/core/daemon/state.js +1 -0
  50. package/dist/core/daemon/state.js.map +1 -1
  51. package/dist/core/daemon/workspace.d.ts +13 -0
  52. package/dist/core/daemon/workspace.js +39 -0
  53. package/dist/core/daemon/workspace.js.map +1 -1
  54. package/dist/core/daemon.d.ts +19 -6
  55. package/dist/core/daemon.js +337 -199
  56. package/dist/core/daemon.js.map +1 -1
  57. package/dist/core/injector.d.ts +5 -1
  58. package/dist/core/injector.js +77 -0
  59. package/dist/core/injector.js.map +1 -1
  60. package/dist/core/registry.d.ts +97 -0
  61. package/dist/core/registry.js +59 -0
  62. package/dist/core/registry.js.map +1 -1
  63. package/dist/core/tmux-runtime.js +4 -0
  64. package/dist/core/tmux-runtime.js.map +1 -1
  65. package/package.json +1 -1
package/README.md CHANGED
@@ -154,6 +154,12 @@ In Feb 2026, `0.2.0` was published manually with `npm publish` from a commit who
154
154
 
155
155
  The fix was to bump past `0.2.0` → `0.2.1` using the correct automated pipeline.
156
156
 
157
+ ### March 2026: v0.3.0 manual publish (same mistake repeated)
158
+
159
+ Published `0.3.0` manually via `npm publish` during E2E verification of PR #304 (unique workdirs + deploy key cloning). The brew formula was also updated manually with an incorrect tarball URL (`agentmeshhq-agent-0.3.0.tgz` → 404; correct is `agent-0.3.0.tgz`). Additional issues found: deploy key credential inactive, orphaned GitHub deploy key, missing `repo_id` on agent assignments, FK violation on HQ deploy-key endpoint.
160
+
161
+ Fix: Corrected brew formula URL + SHA. Tagged `agent-v0.3.0` retroactively. Full post-mortem in `~/Dev/infra-docs/agent-release-ops.md`.
162
+
157
163
  ## License
158
164
 
159
165
  MIT
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Tests for context-template.ts — CLAUDE.md generation, write, and removal.
3
+ */
4
+ export {};
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Tests for context-template.ts — CLAUDE.md generation, write, and removal.
3
+ */
4
+ import * as fs from "node:fs";
5
+ import * as path from "node:path";
6
+ import { beforeEach, describe, expect, it, vi } from "vitest";
7
+ import { generateClaudeMd, removeClaudeMd, writeClaudeMd, } from "../core/daemon/context-template.js";
8
+ vi.mock("node:fs");
9
+ const mockFs = vi.mocked(fs);
10
+ // ============================================================================
11
+ // Shared test data
12
+ // ============================================================================
13
+ const baseOnboard = {
14
+ agent: {
15
+ agent_id: "agent-123",
16
+ display_name: "test-agent",
17
+ model: "claude-sonnet-4",
18
+ capabilities: ["coding", "review"],
19
+ },
20
+ assignment: {
21
+ assignment_id: "asn-1",
22
+ role: "contributor",
23
+ priority: 8,
24
+ notes: "Primary dev",
25
+ },
26
+ project: {
27
+ project_id: "prj-1",
28
+ name: "TestProject",
29
+ code: "TP",
30
+ description: "A test project",
31
+ workdir: "/workspace",
32
+ default_branch: null,
33
+ default_repo_id: null,
34
+ instructions: "Follow coding guidelines.",
35
+ workflow_config: {
36
+ branch_prefix: "feat/",
37
+ pr_target_branch: "dev",
38
+ commit_convention: "conventional",
39
+ protected_branches: ["main", "dev"],
40
+ code_review_required: true,
41
+ custom_rules: ["Run tests first"],
42
+ },
43
+ },
44
+ repos: [
45
+ {
46
+ repo_id: "rep-1",
47
+ provider: "github",
48
+ full_name: "org/repo",
49
+ url: "https://github.com/org/repo.git",
50
+ default_branch: "main",
51
+ credential: { type: "pat", value: "ghp_SECRET" },
52
+ },
53
+ ],
54
+ team: [
55
+ {
56
+ agent_id: "agent-456",
57
+ display_name: "review-bot",
58
+ model: "claude-opus-4-5",
59
+ role: "reviewer",
60
+ status: "online",
61
+ },
62
+ ],
63
+ hub_api: {
64
+ handoffs: "POST /api/v1/workspaces/:workspace/handoffs",
65
+ claims: "POST /api/v1/workspaces/:workspace/claims",
66
+ blockers: "POST /api/v1/workspaces/:workspace/blockers",
67
+ inbox: "GET /api/v1/workspaces/:workspace/inbox",
68
+ heartbeat: "POST /api/v1/agents/heartbeat",
69
+ },
70
+ };
71
+ // ============================================================================
72
+ // generateClaudeMd
73
+ // ============================================================================
74
+ describe("generateClaudeMd", () => {
75
+ it("renders full output with all sections", () => {
76
+ const md = generateClaudeMd(baseOnboard);
77
+ // Auto-generated header
78
+ expect(md).toContain("AUTO-GENERATED by AgentMesh");
79
+ // Identity
80
+ expect(md).toContain("test-agent");
81
+ expect(md).toContain("claude-sonnet-4");
82
+ expect(md).toContain("contributor");
83
+ expect(md).toContain("coding, review");
84
+ // Project
85
+ expect(md).toContain("TestProject");
86
+ expect(md).toContain("`TP`");
87
+ expect(md).toContain("A test project");
88
+ // Workflow
89
+ expect(md).toContain("`feat/`");
90
+ expect(md).toContain("`dev`");
91
+ expect(md).toContain("conventional");
92
+ expect(md).toContain("NEVER push directly");
93
+ expect(md).toContain("Run tests first");
94
+ // Team
95
+ expect(md).toContain("review-bot");
96
+ expect(md).toContain("reviewer");
97
+ // Hub API
98
+ expect(md).toContain("handoffs");
99
+ expect(md).toContain("heartbeat");
100
+ // Repos
101
+ expect(md).toContain("`org/repo`");
102
+ expect(md).toContain("github");
103
+ // Instructions
104
+ expect(md).toContain("Follow coding guidelines.");
105
+ // Footer
106
+ expect(md).toContain("Generated at");
107
+ });
108
+ it("never includes credential values", () => {
109
+ const md = generateClaudeMd(baseOnboard);
110
+ expect(md).not.toContain("ghp_SECRET");
111
+ expect(md).not.toContain("credential");
112
+ });
113
+ it("handles no project", () => {
114
+ const noProject = {
115
+ ...baseOnboard,
116
+ project: null,
117
+ assignment: null,
118
+ repos: [],
119
+ team: [],
120
+ };
121
+ const md = generateClaudeMd(noProject);
122
+ expect(md).toContain("test-agent");
123
+ expect(md).not.toContain("TestProject");
124
+ expect(md).not.toContain("Git Workflow Rules");
125
+ });
126
+ it("handles no team", () => {
127
+ const noTeam = { ...baseOnboard, team: [] };
128
+ const md = generateClaudeMd(noTeam);
129
+ expect(md).not.toContain("| Agent |");
130
+ expect(md).not.toContain("review-bot");
131
+ });
132
+ it("handles no instructions", () => {
133
+ const noInstructions = {
134
+ ...baseOnboard,
135
+ project: { ...baseOnboard.project, instructions: null },
136
+ };
137
+ const md = generateClaudeMd(noInstructions);
138
+ expect(md).not.toContain("Project Instructions");
139
+ });
140
+ it("handles custom rules", () => {
141
+ const multiRules = {
142
+ ...baseOnboard,
143
+ project: {
144
+ ...baseOnboard.project,
145
+ workflow_config: {
146
+ ...baseOnboard.project.workflow_config,
147
+ custom_rules: ["Rule A", "Rule B"],
148
+ },
149
+ },
150
+ };
151
+ const md = generateClaudeMd(multiRules);
152
+ expect(md).toContain("Rule A");
153
+ expect(md).toContain("Rule B");
154
+ });
155
+ });
156
+ // ============================================================================
157
+ // writeClaudeMd
158
+ // ============================================================================
159
+ describe("writeClaudeMd", () => {
160
+ beforeEach(() => {
161
+ vi.clearAllMocks();
162
+ mockFs.writeFileSync.mockReturnValue(undefined);
163
+ mockFs.appendFileSync.mockReturnValue(undefined);
164
+ });
165
+ it("writes CLAUDE.md and returns path", () => {
166
+ mockFs.existsSync.mockImplementation((p) => {
167
+ if (String(p) === "/workspace")
168
+ return true;
169
+ if (String(p).endsWith(".gitignore"))
170
+ return false;
171
+ return false;
172
+ });
173
+ mockFs.readFileSync.mockReturnValue("");
174
+ const result = writeClaudeMd({ workdir: "/workspace", onboard: baseOnboard });
175
+ expect(result).toBe(path.join("/workspace", "CLAUDE.md"));
176
+ expect(mockFs.writeFileSync).toHaveBeenCalledWith(path.join("/workspace", "CLAUDE.md"), expect.stringContaining("AUTO-GENERATED"), expect.objectContaining({ encoding: "utf-8" }));
177
+ });
178
+ it("returns null if workdir does not exist", () => {
179
+ mockFs.existsSync.mockReturnValue(false);
180
+ const result = writeClaudeMd({ workdir: "/nonexistent", onboard: baseOnboard });
181
+ expect(result).toBeNull();
182
+ expect(mockFs.writeFileSync).not.toHaveBeenCalled();
183
+ });
184
+ it("appends CLAUDE.md to .gitignore if not present", () => {
185
+ mockFs.existsSync.mockImplementation((p) => {
186
+ if (String(p) === "/workspace")
187
+ return true;
188
+ if (String(p).endsWith(".gitignore"))
189
+ return true;
190
+ return false;
191
+ });
192
+ mockFs.readFileSync.mockReturnValue("node_modules\n.env\n");
193
+ writeClaudeMd({ workdir: "/workspace", onboard: baseOnboard });
194
+ expect(mockFs.appendFileSync).toHaveBeenCalledWith(path.join("/workspace", ".gitignore"), "CLAUDE.md\n");
195
+ });
196
+ it("does not duplicate CLAUDE.md in .gitignore", () => {
197
+ mockFs.existsSync.mockImplementation((p) => {
198
+ if (String(p) === "/workspace")
199
+ return true;
200
+ if (String(p).endsWith(".gitignore"))
201
+ return true;
202
+ return false;
203
+ });
204
+ mockFs.readFileSync.mockReturnValue("node_modules\nCLAUDE.md\n");
205
+ writeClaudeMd({ workdir: "/workspace", onboard: baseOnboard });
206
+ expect(mockFs.appendFileSync).not.toHaveBeenCalled();
207
+ });
208
+ });
209
+ // ============================================================================
210
+ // removeClaudeMd
211
+ // ============================================================================
212
+ describe("removeClaudeMd", () => {
213
+ beforeEach(() => {
214
+ vi.clearAllMocks();
215
+ });
216
+ it("removes existing CLAUDE.md", () => {
217
+ mockFs.existsSync.mockReturnValue(true);
218
+ mockFs.unlinkSync.mockReturnValue(undefined);
219
+ removeClaudeMd("/workspace");
220
+ expect(mockFs.unlinkSync).toHaveBeenCalledWith(path.join("/workspace", "CLAUDE.md"));
221
+ });
222
+ it("handles missing file gracefully", () => {
223
+ mockFs.existsSync.mockReturnValue(false);
224
+ expect(() => removeClaudeMd("/workspace")).not.toThrow();
225
+ expect(mockFs.unlinkSync).not.toHaveBeenCalled();
226
+ });
227
+ it("handles unlink errors gracefully", () => {
228
+ mockFs.existsSync.mockReturnValue(true);
229
+ mockFs.unlinkSync.mockImplementation(() => {
230
+ throw new Error("permission denied");
231
+ });
232
+ expect(() => removeClaudeMd("/workspace")).not.toThrow();
233
+ });
234
+ });
235
+ //# sourceMappingURL=context-template.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-template.test.js","sourceRoot":"","sources":["../../src/__tests__/context-template.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Tests for project default_branch fallback logic.
3
+ *
4
+ * Resolution order (highest priority first):
5
+ * 1. Assignment repo.default_branch (agent assigned to specific repo)
6
+ * 2. project.default_branch (project-level override)
7
+ * 3. onboardData.repos[0].default_branch (first onboard repo)
8
+ * 4. "main" (hardcoded fallback)
9
+ */
10
+ export {};
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Tests for project default_branch fallback logic.
3
+ *
4
+ * Resolution order (highest priority first):
5
+ * 1. Assignment repo.default_branch (agent assigned to specific repo)
6
+ * 2. project.default_branch (project-level override)
7
+ * 3. onboardData.repos[0].default_branch (first onboard repo)
8
+ * 4. "main" (hardcoded fallback)
9
+ */
10
+ import { describe, expect, it } from "vitest";
11
+ /**
12
+ * Extracts the branch resolution logic from daemon.ts checkAssignments()
13
+ * for isolated unit testing. This mirrors the actual code paths.
14
+ */
15
+ function resolveBranch(assignments, onboardRepos) {
16
+ const repoAssignment = assignments.find((a) => a.repo !== null);
17
+ // If agent has a specific repo assignment, use that repo's branch
18
+ if (repoAssignment?.repo) {
19
+ return repoAssignment.repo.default_branch;
20
+ }
21
+ // Fallback: project default_branch > onboard repo branch > "main"
22
+ const projectDefaultBranch = assignments[0]?.project.default_branch ?? null;
23
+ return projectDefaultBranch ?? onboardRepos[0]?.default_branch ?? "main";
24
+ }
25
+ function makeAssignment(overrides) {
26
+ return {
27
+ assignment_id: "asn-1",
28
+ role: "dev",
29
+ status: "active",
30
+ notes: null,
31
+ priority: 5,
32
+ created_at: new Date().toISOString(),
33
+ project: {
34
+ project_id: "prj-1",
35
+ name: "Test",
36
+ code: "TEST",
37
+ description: null,
38
+ workdir: "/workspace",
39
+ default_branch: overrides.project_default_branch ?? null,
40
+ default_repo_id: null,
41
+ },
42
+ repo: overrides.repo
43
+ ? {
44
+ repo_id: "rep-1",
45
+ provider: "github",
46
+ full_name: "org/repo",
47
+ url: "https://github.com/org/repo.git",
48
+ default_branch: overrides.repo.default_branch,
49
+ }
50
+ : null,
51
+ };
52
+ }
53
+ describe("default_branch fallback resolution", () => {
54
+ it("uses repo assignment branch when agent has a specific repo", () => {
55
+ const assignments = [
56
+ makeAssignment({
57
+ project_default_branch: "dev",
58
+ repo: { default_branch: "feature/special" },
59
+ }),
60
+ ];
61
+ const branch = resolveBranch(assignments, [{ default_branch: "staging" }]);
62
+ expect(branch).toBe("feature/special");
63
+ });
64
+ it("uses project default_branch when no repo assignment", () => {
65
+ const assignments = [
66
+ makeAssignment({
67
+ project_default_branch: "dev",
68
+ repo: null,
69
+ }),
70
+ ];
71
+ const branch = resolveBranch(assignments, [{ default_branch: "main" }]);
72
+ expect(branch).toBe("dev");
73
+ });
74
+ it("uses onboard repo branch when project default_branch is null", () => {
75
+ const assignments = [
76
+ makeAssignment({
77
+ project_default_branch: null,
78
+ repo: null,
79
+ }),
80
+ ];
81
+ const branch = resolveBranch(assignments, [{ default_branch: "staging" }]);
82
+ expect(branch).toBe("staging");
83
+ });
84
+ it("falls back to 'main' when everything is null/empty", () => {
85
+ const assignments = [
86
+ makeAssignment({
87
+ project_default_branch: null,
88
+ repo: null,
89
+ }),
90
+ ];
91
+ const branch = resolveBranch(assignments, []);
92
+ expect(branch).toBe("main");
93
+ });
94
+ it("falls back to 'main' when onboard repo branch is null and no project default", () => {
95
+ const assignments = [
96
+ makeAssignment({
97
+ project_default_branch: null,
98
+ repo: null,
99
+ }),
100
+ ];
101
+ const branch = resolveBranch(assignments, [{ default_branch: null }]);
102
+ expect(branch).toBe("main");
103
+ });
104
+ it("prefers project default_branch over onboard repo branch", () => {
105
+ const assignments = [
106
+ makeAssignment({
107
+ project_default_branch: "dev",
108
+ repo: null,
109
+ }),
110
+ ];
111
+ const branch = resolveBranch(assignments, [{ default_branch: "main" }]);
112
+ expect(branch).toBe("dev");
113
+ });
114
+ it("handles empty assignments array", () => {
115
+ const branch = resolveBranch([], [{ default_branch: "staging" }]);
116
+ expect(branch).toBe("staging");
117
+ });
118
+ it("handles empty assignments and empty repos", () => {
119
+ const branch = resolveBranch([], []);
120
+ expect(branch).toBe("main");
121
+ });
122
+ });
123
+ //# sourceMappingURL=default-branch-fallback.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-branch-fallback.test.js","sourceRoot":"","sources":["../../src/__tests__/default-branch-fallback.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Tests for project default_repo_id fallback logic.
3
+ *
4
+ * Resolution order (highest priority first):
5
+ * 1. Assignment repo (agent assigned to a specific repo)
6
+ * 2. project.default_repo_id (project-level default repo)
7
+ * 3. onboardData.repos[0] (first onboard repo — no ordering guarantee)
8
+ *
9
+ * The default_repo_id allows a project with multiple repos to specify
10
+ * which repo agents should use when they don't have a specific repo assignment.
11
+ */
12
+ export {};
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Tests for project default_repo_id fallback logic.
3
+ *
4
+ * Resolution order (highest priority first):
5
+ * 1. Assignment repo (agent assigned to a specific repo)
6
+ * 2. project.default_repo_id (project-level default repo)
7
+ * 3. onboardData.repos[0] (first onboard repo — no ordering guarantee)
8
+ *
9
+ * The default_repo_id allows a project with multiple repos to specify
10
+ * which repo agents should use when they don't have a specific repo assignment.
11
+ */
12
+ import { describe, expect, it } from "vitest";
13
+ /**
14
+ * Mirrors the fallback logic from daemon.ts checkAssignments()
15
+ * for isolated unit testing.
16
+ */
17
+ function resolveRepo(assignments, onboardRepos) {
18
+ // If agent has a specific repo assignment, use that
19
+ const repoAssignment = assignments.find((a) => a.repo !== null);
20
+ if (repoAssignment?.repo) {
21
+ return {
22
+ repo_id: repoAssignment.repo.repo_id,
23
+ provider: repoAssignment.repo.provider,
24
+ full_name: repoAssignment.repo.full_name,
25
+ url: repoAssignment.repo.url,
26
+ default_branch: repoAssignment.repo.default_branch,
27
+ credential: null,
28
+ };
29
+ }
30
+ // Fallback: default_repo_id > repos[0]
31
+ const projectDefaultRepoId = assignments[0]?.project.default_repo_id ?? null;
32
+ const defaultRepo = projectDefaultRepoId
33
+ ? onboardRepos.find((r) => r.repo_id === projectDefaultRepoId)
34
+ : null;
35
+ return defaultRepo ?? onboardRepos[0] ?? null;
36
+ }
37
+ function makeAssignment(overrides) {
38
+ return {
39
+ assignment_id: "asn-1",
40
+ role: "dev",
41
+ status: "active",
42
+ notes: null,
43
+ priority: 5,
44
+ created_at: new Date().toISOString(),
45
+ project: {
46
+ project_id: "prj-1",
47
+ name: "Test",
48
+ code: "TEST",
49
+ description: null,
50
+ workdir: "/workspace",
51
+ default_branch: null,
52
+ default_repo_id: overrides.project_default_repo_id ?? null,
53
+ },
54
+ repo: overrides.repo
55
+ ? {
56
+ repo_id: overrides.repo.repo_id,
57
+ provider: "github",
58
+ full_name: "org/repo",
59
+ url: "https://github.com/org/repo.git",
60
+ default_branch: overrides.repo.default_branch,
61
+ }
62
+ : null,
63
+ };
64
+ }
65
+ const REPOS = [
66
+ {
67
+ repo_id: "rep-alpha",
68
+ provider: "github",
69
+ full_name: "org/alpha",
70
+ url: "https://github.com/org/alpha.git",
71
+ default_branch: "main",
72
+ credential: null,
73
+ },
74
+ {
75
+ repo_id: "rep-beta",
76
+ provider: "github",
77
+ full_name: "org/beta",
78
+ url: "https://github.com/org/beta.git",
79
+ default_branch: "develop",
80
+ credential: null,
81
+ },
82
+ ];
83
+ describe("default_repo_id fallback resolution", () => {
84
+ it("uses repo assignment when agent has a specific repo", () => {
85
+ const assignments = [
86
+ makeAssignment({
87
+ project_default_repo_id: "rep-beta",
88
+ repo: { repo_id: "rep-gamma", default_branch: "feature/x" },
89
+ }),
90
+ ];
91
+ const repo = resolveRepo(assignments, REPOS);
92
+ expect(repo?.repo_id).toBe("rep-gamma");
93
+ });
94
+ it("uses default_repo_id when no repo assignment", () => {
95
+ const assignments = [
96
+ makeAssignment({
97
+ project_default_repo_id: "rep-beta",
98
+ repo: null,
99
+ }),
100
+ ];
101
+ const repo = resolveRepo(assignments, REPOS);
102
+ expect(repo?.repo_id).toBe("rep-beta");
103
+ expect(repo?.full_name).toBe("org/beta");
104
+ });
105
+ it("falls back to repos[0] when default_repo_id is null", () => {
106
+ const assignments = [
107
+ makeAssignment({
108
+ project_default_repo_id: null,
109
+ repo: null,
110
+ }),
111
+ ];
112
+ const repo = resolveRepo(assignments, REPOS);
113
+ expect(repo?.repo_id).toBe("rep-alpha");
114
+ });
115
+ it("falls back to repos[0] when default_repo_id doesn't match any repo", () => {
116
+ const assignments = [
117
+ makeAssignment({
118
+ project_default_repo_id: "rep-nonexistent",
119
+ repo: null,
120
+ }),
121
+ ];
122
+ const repo = resolveRepo(assignments, REPOS);
123
+ expect(repo?.repo_id).toBe("rep-alpha");
124
+ });
125
+ it("returns null when no repos and no assignment", () => {
126
+ const assignments = [
127
+ makeAssignment({
128
+ project_default_repo_id: null,
129
+ repo: null,
130
+ }),
131
+ ];
132
+ const repo = resolveRepo(assignments, []);
133
+ expect(repo).toBeNull();
134
+ });
135
+ it("handles empty assignments array", () => {
136
+ const repo = resolveRepo([], REPOS);
137
+ expect(repo?.repo_id).toBe("rep-alpha");
138
+ });
139
+ it("handles empty assignments and empty repos", () => {
140
+ const repo = resolveRepo([], []);
141
+ expect(repo).toBeNull();
142
+ });
143
+ it("prefers default_repo_id over repos[0]", () => {
144
+ const assignments = [
145
+ makeAssignment({
146
+ project_default_repo_id: "rep-beta",
147
+ repo: null,
148
+ }),
149
+ ];
150
+ const repo = resolveRepo(assignments, REPOS);
151
+ // Should pick beta (default_repo_id), not alpha (repos[0])
152
+ expect(repo?.repo_id).toBe("rep-beta");
153
+ expect(repo?.default_branch).toBe("develop");
154
+ });
155
+ });
156
+ //# sourceMappingURL=default-repo-fallback.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-repo-fallback.test.js","sourceRoot":"","sources":["../../src/__tests__/default-repo-fallback.test.ts"],"names":[],"mappings":"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"}