@markjaquith/agency 1.11.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +302 -113
  2. package/cli.ts +123 -415
  3. package/index.ts +1 -1
  4. package/package.json +12 -17
  5. package/skills/agency/SKILL.md +258 -0
  6. package/src/cli.test.ts +290 -0
  7. package/src/commands/description.test.ts +103 -0
  8. package/src/commands/epic.test.ts +103 -0
  9. package/src/commands/epic.ts +101 -0
  10. package/src/commands/init.test.ts +42 -290
  11. package/src/commands/init.ts +15 -123
  12. package/src/commands/phase.ts +120 -0
  13. package/src/commands/pr.test.ts +19 -170
  14. package/src/commands/pr.ts +23 -179
  15. package/src/commands/repo.test.ts +80 -0
  16. package/src/commands/repo.ts +83 -0
  17. package/src/commands/status.test.ts +35 -477
  18. package/src/commands/status.ts +24 -213
  19. package/src/commands/task-phase.test.ts +206 -0
  20. package/src/commands/task.ts +83 -1285
  21. package/src/commands/validate.test.ts +91 -0
  22. package/src/commands/validate.ts +50 -0
  23. package/src/commands/work.test.ts +172 -419
  24. package/src/commands/work.ts +47 -166
  25. package/src/services/EpicService.test.ts +71 -0
  26. package/src/services/EpicService.ts +135 -0
  27. package/src/services/FileSystemService.ts +61 -92
  28. package/src/services/PhaseService.ts +323 -0
  29. package/src/services/PullRequestService.test.ts +386 -0
  30. package/src/services/PullRequestService.ts +143 -0
  31. package/src/services/RepositoryService.test.ts +106 -0
  32. package/src/services/RepositoryService.ts +159 -0
  33. package/src/services/TaskPhaseService.test.ts +217 -0
  34. package/src/services/TaskService.ts +192 -0
  35. package/src/services/WorkbaseService.test.ts +446 -0
  36. package/src/services/WorkbaseService.ts +493 -0
  37. package/src/services/WorktreeService.test.ts +599 -0
  38. package/src/services/WorktreeService.ts +357 -0
  39. package/src/test-utils.ts +41 -438
  40. package/src/types.ts +1 -215
  41. package/src/utils/command.ts +1 -5
  42. package/src/utils/effect.test.ts +24 -0
  43. package/src/utils/effect.ts +3 -273
  44. package/src/utils/process.test.ts +0 -15
  45. package/src/utils/process.ts +1 -60
  46. package/src/workbase/frontmatter.test.ts +50 -0
  47. package/src/workbase/frontmatter.ts +77 -0
  48. package/src/workbase/repository-reference.test.ts +25 -0
  49. package/src/workbase/repository-reference.ts +18 -0
  50. package/src/workbase/schemas.test.ts +146 -0
  51. package/src/workbase/schemas.ts +78 -0
  52. package/src/workbase/worktree-command.test.ts +61 -0
  53. package/src/workbase/worktree-command.ts +52 -0
  54. package/src/commands/base.test.ts +0 -198
  55. package/src/commands/base.ts +0 -198
  56. package/src/commands/clean.test.ts +0 -299
  57. package/src/commands/clean.ts +0 -274
  58. package/src/commands/completions.test.ts +0 -51
  59. package/src/commands/completions.ts +0 -308
  60. package/src/commands/emit.integration.test.ts +0 -549
  61. package/src/commands/emit.test.ts +0 -576
  62. package/src/commands/emit.ts +0 -700
  63. package/src/commands/emitted.test.ts +0 -226
  64. package/src/commands/emitted.ts +0 -57
  65. package/src/commands/loop.test.ts +0 -621
  66. package/src/commands/loop.ts +0 -406
  67. package/src/commands/merge.integration.test.ts +0 -195
  68. package/src/commands/merge.test.ts +0 -246
  69. package/src/commands/merge.ts +0 -244
  70. package/src/commands/pull.test.ts +0 -395
  71. package/src/commands/pull.ts +0 -205
  72. package/src/commands/push.test.ts +0 -518
  73. package/src/commands/push.ts +0 -434
  74. package/src/commands/rebase.test.ts +0 -521
  75. package/src/commands/rebase.ts +0 -232
  76. package/src/commands/save.test.ts +0 -247
  77. package/src/commands/save.ts +0 -162
  78. package/src/commands/source.test.ts +0 -195
  79. package/src/commands/source.ts +0 -72
  80. package/src/commands/switch.test.ts +0 -194
  81. package/src/commands/switch.ts +0 -84
  82. package/src/commands/task-branching.test.ts +0 -633
  83. package/src/commands/task-continue.test.ts +0 -311
  84. package/src/commands/task-edit.test.ts +0 -235
  85. package/src/commands/task-main.test.ts +0 -1066
  86. package/src/commands/task-squash.test.ts +0 -266
  87. package/src/commands/tasks.test.ts +0 -391
  88. package/src/commands/tasks.ts +0 -161
  89. package/src/commands/template-delete.test.ts +0 -178
  90. package/src/commands/template-delete.ts +0 -98
  91. package/src/commands/template-list.test.ts +0 -135
  92. package/src/commands/template-list.ts +0 -87
  93. package/src/commands/template-view.test.ts +0 -158
  94. package/src/commands/template-view.ts +0 -86
  95. package/src/commands/template.test.ts +0 -32
  96. package/src/commands/template.ts +0 -96
  97. package/src/commands/use.test.ts +0 -87
  98. package/src/commands/use.ts +0 -97
  99. package/src/constants.ts +0 -10
  100. package/src/errors.ts +0 -17
  101. package/src/schemas.ts +0 -33
  102. package/src/services/AgencyMetadataService.ts +0 -311
  103. package/src/services/ClaudeService.test.ts +0 -184
  104. package/src/services/ClaudeService.ts +0 -91
  105. package/src/services/ConfigService.ts +0 -115
  106. package/src/services/FilterRepoService.ts +0 -164
  107. package/src/services/FormatterService.test.ts +0 -432
  108. package/src/services/FormatterService.ts +0 -219
  109. package/src/services/GitService.ts +0 -1183
  110. package/src/services/MockFilterRepoService.ts +0 -140
  111. package/src/services/OpencodeService.ts +0 -263
  112. package/src/services/PromptService.ts +0 -183
  113. package/src/services/TemplateService.ts +0 -81
  114. package/src/types/native-exec.d.ts +0 -8
  115. package/src/utils/colors.ts +0 -178
  116. package/src/utils/git-path.ts +0 -6
  117. package/src/utils/glob.test.ts +0 -161
  118. package/src/utils/glob.ts +0 -78
  119. package/src/utils/paths.ts +0 -51
  120. package/src/utils/pr-branch.test.ts +0 -376
  121. package/src/utils/pr-branch.ts +0 -508
  122. package/src/utils/spinner.test.ts +0 -45
  123. package/src/utils/spinner.ts +0 -96
  124. package/src/utils/task-parser.test.ts +0 -172
  125. package/src/utils/task-parser.ts +0 -93
  126. package/templates/AGENCY.md +0 -22
  127. package/templates/AGENTS.md +0 -11
  128. package/templates/CLAUDE.md +0 -3
  129. package/templates/TASK.md +0 -5
  130. package/templates/opencode.json +0 -4
@@ -1,518 +0,0 @@
1
- import { test, expect, describe, beforeEach, afterEach } from "bun:test"
2
- import { join } from "path"
3
- import { push } from "./push"
4
- import {
5
- createTempDir,
6
- cleanupTempDir,
7
- initGitRepo,
8
- getCurrentBranch,
9
- getGitOutput,
10
- createCommit,
11
- checkoutBranch,
12
- createBranch,
13
- addAndCommit,
14
- renameBranch,
15
- runTestEffect,
16
- runTestEffectWithMockFilterRepo,
17
- } from "../test-utils"
18
-
19
- async function setupAgencyJson(gitRoot: string): Promise<void> {
20
- const agencyJson = {
21
- version: 1,
22
- injectedFiles: ["AGENTS.MD", "TASK.md"],
23
- template: "test",
24
- createdAt: new Date().toISOString(),
25
- }
26
- await Bun.write(
27
- join(gitRoot, "agency.json"),
28
- JSON.stringify(agencyJson, null, 2) + "\n",
29
- )
30
- await addAndCommit(gitRoot, "agency.json", "Add agency.json")
31
- }
32
-
33
- async function setupBareRemote(): Promise<string> {
34
- // Create a bare repository outside the working tree to avoid polluting git status
35
- const remoteDir = await createTempDir()
36
- await Bun.spawn(["git", "init", "--bare", remoteDir], {
37
- stdout: "pipe",
38
- stderr: "pipe",
39
- }).exited
40
- return remoteDir
41
- }
42
-
43
- describe("push command", () => {
44
- let tempDir: string
45
- let remoteDir: string
46
- let originalCwd: string
47
-
48
- beforeEach(async () => {
49
- tempDir = await createTempDir()
50
- originalCwd = process.cwd()
51
- process.chdir(tempDir)
52
-
53
- // Set config path to non-existent file to use defaults
54
- process.env.AGENCY_CONFIG_PATH = join(tempDir, "non-existent-config.json")
55
-
56
- // Initialize git repo
57
- await initGitRepo(tempDir)
58
- await createCommit(tempDir, "Initial commit")
59
-
60
- // Rename to main if needed
61
- const currentBranch = await getCurrentBranch(tempDir)
62
- if (currentBranch === "master") {
63
- await renameBranch(tempDir, "main")
64
- }
65
-
66
- // Setup bare remote and push main
67
- remoteDir = await setupBareRemote()
68
- await Bun.spawn(["git", "remote", "add", "origin", remoteDir], {
69
- cwd: tempDir,
70
- stdout: "pipe",
71
- stderr: "pipe",
72
- }).exited
73
- await Bun.spawn(["git", "push", "-u", "origin", "main"], {
74
- cwd: tempDir,
75
- stdout: "pipe",
76
- stderr: "pipe",
77
- }).exited
78
-
79
- // Setup agency.json
80
- await setupAgencyJson(tempDir)
81
-
82
- // Create a source branch (with agency-- prefix per new default config)
83
- await createBranch(tempDir, "agency--feature")
84
- await createCommit(tempDir, "Feature work")
85
- })
86
-
87
- afterEach(async () => {
88
- process.chdir(originalCwd)
89
- delete process.env.AGENCY_CONFIG_PATH
90
- await cleanupTempDir(tempDir)
91
- await cleanupTempDir(remoteDir)
92
- })
93
-
94
- describe("basic functionality", () => {
95
- test("fails when there are uncommitted changes", async () => {
96
- // Create uncommitted changes
97
- await Bun.write(join(tempDir, "uncommitted.txt"), "uncommitted\n")
98
-
99
- expect(
100
- runTestEffect(
101
- push({ baseBranch: "main", silent: true, skipFilter: true }),
102
- ),
103
- ).rejects.toThrow(/uncommitted changes/)
104
- })
105
-
106
- test("fails when there are staged but uncommitted changes", async () => {
107
- // Create a staged but uncommitted change
108
- await Bun.write(join(tempDir, "staged.txt"), "staged\n")
109
- await Bun.spawn(["git", "add", "staged.txt"], {
110
- cwd: tempDir,
111
- stdout: "pipe",
112
- stderr: "pipe",
113
- }).exited
114
-
115
- expect(
116
- runTestEffect(
117
- push({ baseBranch: "main", silent: true, skipFilter: true }),
118
- ),
119
- ).rejects.toThrow(/uncommitted changes/)
120
- })
121
-
122
- test("creates emit branch, pushes it, and returns to source", async () => {
123
- // We're on agency--feature branch (source)
124
- expect(await getCurrentBranch(tempDir)).toBe("agency--feature")
125
-
126
- // Run push command
127
- await runTestEffect(
128
- push({ baseBranch: "main", silent: true, skipFilter: true }),
129
- )
130
-
131
- // Should be back on agency--feature branch (source)
132
- expect(await getCurrentBranch(tempDir)).toBe("agency--feature")
133
-
134
- // emit branch (feature) should exist locally and on remote
135
- const branches = await getGitOutput(tempDir, ["branch"])
136
- expect(branches).toContain("feature")
137
-
138
- const remoteBranches = await getGitOutput(tempDir, [
139
- "ls-remote",
140
- "--heads",
141
- "origin",
142
- "feature",
143
- ])
144
- expect(remoteBranches).toContain("feature")
145
- })
146
-
147
- test("forwards verbose output from emit step", async () => {
148
- const originalLog = console.log
149
- const logMessages: string[] = []
150
- console.log = (msg: string) => {
151
- logMessages.push(msg)
152
- }
153
-
154
- try {
155
- await runTestEffect(
156
- push({
157
- baseBranch: "main",
158
- verbose: true,
159
- skipFilter: true,
160
- }),
161
- )
162
- } finally {
163
- console.log = originalLog
164
- }
165
-
166
- expect(logMessages).toContain("Step 1: Emitting...")
167
- expect(
168
- logMessages.some(
169
- (msg) => msg.includes("Using base branch:") && msg.includes("main"),
170
- ),
171
- ).toBe(true)
172
- expect(
173
- logMessages.some((msg) =>
174
- msg.includes("Skipping git-filter-repo (skipFilter=true)"),
175
- ),
176
- ).toBe(true)
177
- expect(logMessages.some((msg) => msg.includes("Emitted"))).toBe(true)
178
- })
179
-
180
- test("works with custom branch name", async () => {
181
- await runTestEffect(
182
- push({
183
- baseBranch: "main",
184
- emit: "custom-pr-branch",
185
- silent: true,
186
- skipFilter: true,
187
- }),
188
- )
189
-
190
- // Should be back on agency--feature branch (source)
191
- expect(await getCurrentBranch(tempDir)).toBe("agency--feature")
192
-
193
- // Custom branch should exist
194
- const branches = await getGitOutput(tempDir, ["branch"])
195
- expect(branches).toContain("custom-pr-branch")
196
- })
197
-
198
- test("recreates emit branch if it already exists", async () => {
199
- // First push
200
- await runTestEffect(
201
- push({ baseBranch: "main", silent: true, skipFilter: true }),
202
- )
203
-
204
- // Make more changes on source branch
205
- await checkoutBranch(tempDir, "agency--feature")
206
- await createCommit(tempDir, "More feature work")
207
-
208
- // Second push should recreate the emit branch
209
- await runTestEffect(
210
- push({ baseBranch: "main", silent: true, skipFilter: true }),
211
- )
212
-
213
- // Should still be back on agency--feature branch (source)
214
- expect(await getCurrentBranch(tempDir)).toBe("agency--feature")
215
- })
216
- })
217
-
218
- describe("error handling", () => {
219
- test("throws when emitted CLAUDE.md references AGENCY.md", async () => {
220
- await Bun.write(
221
- join(tempDir, "CLAUDE.md"),
222
- "# Instructions\n\n@AGENCY.md\n",
223
- )
224
- await addAndCommit(tempDir, "CLAUDE.md", "Add Claude agency reference")
225
-
226
- await expect(
227
- runTestEffectWithMockFilterRepo(
228
- push({ baseBranch: "main", silent: true }),
229
- ),
230
- ).rejects.toThrow(
231
- "Failed to create emit branch: CLAUDE.md on emitted branch feature still references @AGENCY.md",
232
- )
233
- })
234
-
235
- test("switches to source branch when run from emit branch", async () => {
236
- // First create the emit branch from source branch
237
- await runTestEffect(
238
- push({ baseBranch: "main", silent: true, skipFilter: true }),
239
- )
240
-
241
- // Now we're on agency--feature, switch to the emit branch (feature)
242
- await checkoutBranch(tempDir, "feature")
243
-
244
- // Verify we're on the emit branch
245
- expect(await getCurrentBranch(tempDir)).toBe("feature")
246
-
247
- // Make a change on source branch that we'll push
248
- await checkoutBranch(tempDir, "agency--feature")
249
- await createCommit(tempDir, "Another feature commit")
250
-
251
- // Switch back to emit branch
252
- await checkoutBranch(tempDir, "feature")
253
-
254
- // Run push from emit branch - should detect we're on emit branch,
255
- // switch to source (agency--feature), and continue
256
- await runTestEffect(
257
- push({ baseBranch: "main", silent: true, skipFilter: true }),
258
- )
259
-
260
- // Should be back on agency--feature branch (the source branch)
261
- expect(await getCurrentBranch(tempDir)).toBe("agency--feature")
262
- })
263
-
264
- test("throws error when not in a git repository", async () => {
265
- const nonGitDir = await createTempDir()
266
- process.chdir(nonGitDir)
267
-
268
- await expect(
269
- runTestEffect(
270
- push({ baseBranch: "main", silent: true, skipFilter: true }),
271
- ),
272
- ).rejects.toThrow("Not in a git repository")
273
-
274
- await cleanupTempDir(nonGitDir)
275
- })
276
-
277
- test("handles push failure gracefully", async () => {
278
- // Remove the remote to cause push to fail
279
- await Bun.spawn(["git", "remote", "remove", "origin"], {
280
- cwd: tempDir,
281
- stdout: "pipe",
282
- stderr: "pipe",
283
- }).exited
284
-
285
- // Push should fail because no remote exists
286
- await expect(
287
- runTestEffect(
288
- push({ baseBranch: "main", silent: true, skipFilter: true }),
289
- ),
290
- ).rejects.toThrow(/No git remotes found/)
291
- })
292
- })
293
-
294
- describe("silent mode", () => {
295
- test("silent flag suppresses output", async () => {
296
- // Capture output
297
- const originalLog = console.log
298
- let logCalled = false
299
- console.log = () => {
300
- logCalled = true
301
- }
302
-
303
- await runTestEffect(
304
- push({ baseBranch: "main", silent: true, skipFilter: true }),
305
- )
306
-
307
- console.log = originalLog
308
- expect(logCalled).toBe(false)
309
- })
310
- })
311
-
312
- describe("force push", () => {
313
- test("force pushes when branch has diverged and --force is provided", async () => {
314
- // First push
315
- await runTestEffect(
316
- push({ baseBranch: "main", silent: true, skipFilter: true }),
317
- )
318
-
319
- // Make changes on source branch
320
- await checkoutBranch(tempDir, "agency--feature")
321
- await createCommit(tempDir, "More feature work")
322
-
323
- // Modify the emit branch to create divergence
324
- await checkoutBranch(tempDir, "feature")
325
- await createCommit(tempDir, "Direct emit branch commit")
326
- await Bun.spawn(["git", "push"], {
327
- cwd: tempDir,
328
- stdout: "pipe",
329
- stderr: "pipe",
330
- }).exited
331
-
332
- // Go back to source branch and try to push again with --force
333
- await checkoutBranch(tempDir, "agency--feature")
334
-
335
- // Capture output to check for force push message
336
- const originalLog = console.log
337
- let logMessages: string[] = []
338
- console.log = (msg: string) => {
339
- logMessages.push(msg)
340
- }
341
-
342
- await runTestEffect(
343
- push({
344
- baseBranch: "main",
345
- force: true,
346
- silent: false,
347
- skipFilter: true,
348
- }),
349
- )
350
-
351
- console.log = originalLog
352
-
353
- // Should be back on agency--feature branch (source)
354
- expect(await getCurrentBranch(tempDir)).toBe("agency--feature")
355
-
356
- // Should have reported force push
357
- expect(logMessages.some((msg) => msg.includes("(forced)"))).toBe(true)
358
- })
359
-
360
- test("suggests using --force when push is rejected without it", async () => {
361
- // First push
362
- await runTestEffect(
363
- push({ baseBranch: "main", silent: true, skipFilter: true }),
364
- )
365
-
366
- // Make changes on source branch
367
- await checkoutBranch(tempDir, "agency--feature")
368
- await createCommit(tempDir, "More feature work")
369
-
370
- // Modify the emit branch to create divergence
371
- await checkoutBranch(tempDir, "feature")
372
- await createCommit(tempDir, "Direct emit branch commit")
373
- await Bun.spawn(["git", "push"], {
374
- cwd: tempDir,
375
- stdout: "pipe",
376
- stderr: "pipe",
377
- }).exited
378
-
379
- // Go back to source branch and try to push without --force
380
- await checkoutBranch(tempDir, "agency--feature")
381
-
382
- // Should throw error suggesting --force
383
- await expect(
384
- runTestEffect(
385
- push({ baseBranch: "main", silent: true, skipFilter: true }),
386
- ),
387
- ).rejects.toThrow(
388
- /non-fast-forward update.*agency push --force|agency push --force.*non-fast-forward update/s,
389
- )
390
-
391
- // Should still be on agency--feature branch (not left in intermediate state)
392
- expect(await getCurrentBranch(tempDir)).toBe("agency--feature")
393
- })
394
-
395
- test("reports pre-push hook output without suggesting --force", async () => {
396
- await Bun.spawn(
397
- ["git", "config", "core.hooksPath", join(tempDir, ".git", "hooks")],
398
- {
399
- cwd: tempDir,
400
- stdout: "pipe",
401
- stderr: "pipe",
402
- },
403
- ).exited
404
- const hookPath = join(tempDir, ".git", "hooks", "pre-push")
405
- await Bun.write(
406
- hookPath,
407
- [
408
- "#!/bin/sh",
409
- "printf 'pre-push hook stdout failure\\n'",
410
- "printf 'pre-push hook stderr failure\\n' >&2",
411
- "exit 1",
412
- "",
413
- ].join("\n"),
414
- )
415
- await Bun.spawn(["chmod", "+x", hookPath], {
416
- cwd: tempDir,
417
- stdout: "pipe",
418
- stderr: "pipe",
419
- }).exited
420
-
421
- let error: unknown
422
- try {
423
- await runTestEffect(
424
- push({ baseBranch: "main", silent: true, skipFilter: true }),
425
- )
426
- } catch (caught) {
427
- error = caught
428
- }
429
-
430
- expect(error).toBeInstanceOf(Error)
431
- const message = error instanceof Error ? error.message : String(error)
432
- expect(message).toContain("pre-push hook stdout failure")
433
- expect(message).toContain("pre-push hook stderr failure")
434
- expect(message).not.toContain("agency push --force")
435
-
436
- expect(await getCurrentBranch(tempDir)).toBe("agency--feature")
437
- })
438
-
439
- test("does not report force push when --force is provided but not needed", async () => {
440
- // Capture output to check for force push message
441
- const originalLog = console.log
442
- let logMessages: string[] = []
443
- console.log = (msg: string) => {
444
- logMessages.push(msg)
445
- }
446
-
447
- // First push with --force (but it won't actually need force)
448
- await runTestEffect(
449
- push({
450
- baseBranch: "main",
451
- force: true,
452
- silent: false,
453
- skipFilter: true,
454
- }),
455
- )
456
-
457
- console.log = originalLog
458
-
459
- // Should be back on agency--feature branch (source)
460
- expect(await getCurrentBranch(tempDir)).toBe("agency--feature")
461
-
462
- // Should NOT have reported force push (since it wasn't actually used)
463
- expect(logMessages.some((msg) => msg.includes("Force pushed"))).toBe(
464
- false,
465
- )
466
- expect(logMessages.some((msg) => msg.includes("Pushed"))).toBe(true)
467
- })
468
- })
469
-
470
- describe("--pr flag", () => {
471
- test("handles gh CLI failure gracefully and continues", async () => {
472
- // Capture error output
473
- const originalError = console.error
474
- let errorMessages: string[] = []
475
- console.error = (msg: string) => {
476
- errorMessages.push(msg)
477
- }
478
-
479
- // Should not throw - command should complete despite gh failure
480
- // (gh will fail in test environment because there's no GitHub remote)
481
- await runTestEffect(
482
- push({ baseBranch: "main", pr: true, silent: true, skipFilter: true }),
483
- )
484
-
485
- console.error = originalError
486
-
487
- // Should be back on agency--feature branch (command completes despite gh failure)
488
- expect(await getCurrentBranch(tempDir)).toBe("agency--feature")
489
-
490
- // Should have warned about gh failure
491
- expect(
492
- errorMessages.some((msg) => msg.includes("Failed to open GitHub PR")),
493
- ).toBe(true)
494
- })
495
-
496
- test("does not call gh when --pr flag is not set", async () => {
497
- // Capture error output
498
- const originalError = console.error
499
- let errorMessages: string[] = []
500
- console.error = (msg: string) => {
501
- errorMessages.push(msg)
502
- }
503
-
504
- // Push without --pr flag
505
- await runTestEffect(
506
- push({ baseBranch: "main", silent: true, skipFilter: true }),
507
- )
508
-
509
- console.error = originalError
510
-
511
- // Should be back on agency--feature branch (source)
512
- expect(await getCurrentBranch(tempDir)).toBe("agency--feature")
513
-
514
- // gh should NOT have been called (no error about GitHub PR)
515
- expect(errorMessages.some((msg) => msg.includes("GitHub PR"))).toBe(false)
516
- })
517
- })
518
- })