github-issue-tower-defence-management 1.69.2 → 1.69.4

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 (33) hide show
  1. package/.github/workflows/api-created_issue_pr.yml +3 -0
  2. package/.github/workflows/codeql.yml +3 -0
  3. package/.github/workflows/commit-lint.yml +3 -0
  4. package/.github/workflows/create-pr.yml +3 -0
  5. package/.github/workflows/empty-format-test-job.yml +6 -0
  6. package/.github/workflows/format.yml +3 -0
  7. package/.github/workflows/publish.yml +3 -0
  8. package/.github/workflows/test.yml +3 -0
  9. package/.github/workflows/umino-project.yml +6 -0
  10. package/CHANGELOG.md +14 -0
  11. package/README.md +1 -1
  12. package/bin/adapter/entry-points/cli/index.js +1 -0
  13. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  14. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +7 -2
  15. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  16. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +2 -2
  17. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
  18. package/bin/domain/usecases/HandleScheduledEventUseCase.js +1 -0
  19. package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -1
  20. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js +33 -9
  21. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js.map +1 -1
  22. package/package.json +1 -1
  23. package/src/adapter/entry-points/cli/index.ts +1 -0
  24. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +2 -0
  25. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +2 -2
  26. package/src/domain/usecases/HandleScheduledEventUseCase.ts +2 -0
  27. package/src/domain/usecases/RevertOrphanedPreparationUseCase.test.ts +262 -2
  28. package/src/domain/usecases/RevertOrphanedPreparationUseCase.ts +71 -13
  29. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
  30. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts +1 -0
  31. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -1
  32. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts +3 -2
  33. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"RevertOrphanedPreparationUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/RevertOrphanedPreparationUseCase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RevertOrphanedPreparationUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/RevertOrphanedPreparationUseCase.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-issue-tower-defence-management",
3
- "version": "1.69.2",
3
+ "version": "1.69.4",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "scripts": {
@@ -258,6 +258,7 @@ program
258
258
  projectUrl,
259
259
  allowIssueCacheMinutes,
260
260
  preparationProcessCheckCommand,
261
+ thresholdForAutoReject: config.thresholdForAutoReject ?? 3,
261
262
  awLogDirectoryPath: config.awLogDirectoryPath,
262
263
  awLogStaleThresholdMinutes: config.awLogStaleThresholdMinutes,
263
264
  });
@@ -103,6 +103,8 @@ export class HandleScheduledEventUseCaseHandler {
103
103
  claudeCodeOauthTokenListJsonPath:
104
104
  readmeConfig.claudeCodeOauthTokenListJsonPath ??
105
105
  input.claudeCodeOauthTokenListJsonPath,
106
+ thresholdForAutoReject:
107
+ readmeConfig.thresholdForAutoReject ?? input.thresholdForAutoReject,
106
108
  startPreparation: input.startPreparation
107
109
  ? {
108
110
  ...input.startPreparation,
@@ -884,14 +884,14 @@ export class ApiV3CheerioRestIssueRepository
884
884
  const responseData: unknown = await response.json();
885
885
  if (!isIssueTimelineResponse(responseData)) {
886
886
  throw new Error(
887
- 'Unexpected response shape when fetching issue timeline',
887
+ `Unexpected response shape when fetching issue timeline: ${issueUrl}`,
888
888
  );
889
889
  }
890
890
 
891
891
  const issueData = responseData.data?.repository?.issue;
892
892
  if (!issueData) {
893
893
  throw new Error(
894
- 'Issue not found when fetching timeline from GitHub GraphQL API',
894
+ `Issue not found when fetching timeline from GitHub GraphQL API: ${issueUrl}`,
895
895
  );
896
896
  }
897
897
 
@@ -94,6 +94,7 @@ export class HandleScheduledEventUseCase {
94
94
  notifyFinishedPreparation?: {
95
95
  awaitingQualityCheckStatusName?: string | null;
96
96
  } | null;
97
+ thresholdForAutoReject?: number;
97
98
  }): Promise<{
98
99
  project: Project;
99
100
  issues: Issue[];
@@ -297,6 +298,7 @@ ${JSON.stringify(e)}
297
298
  allowIssueCacheMinutes: input.allowIssueCacheMinutes,
298
299
  preparationProcessCheckCommand:
299
300
  input.startPreparation.preparationProcessCheckCommand,
301
+ thresholdForAutoReject: input.thresholdForAutoReject ?? 3,
300
302
  awLogDirectoryPath: input.startPreparation.awLogDirectoryPath,
301
303
  awLogStaleThresholdMinutes:
302
304
  input.startPreparation.awLogStaleThresholdMinutes,
@@ -53,6 +53,12 @@ const createMockProject = (): Project => ({
53
53
  color: 'BLUE',
54
54
  description: '',
55
55
  },
56
+ {
57
+ id: '5',
58
+ name: 'Failed Preparation',
59
+ color: 'RED',
60
+ description: '',
61
+ },
56
62
  ],
57
63
  },
58
64
  nextActionDate: null,
@@ -107,7 +113,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
107
113
  >
108
114
  >;
109
115
  let mockIssueCommentRepository: Mocked<
110
- Pick<IssueCommentRepository, 'getCommentsFromIssue'>
116
+ Pick<IssueCommentRepository, 'getCommentsFromIssue' | 'createComment'>
111
117
  >;
112
118
  let mockLocalCommandRunner: Mocked<LocalCommandRunner>;
113
119
  let mockProject: Project;
@@ -129,6 +135,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
129
135
  };
130
136
  mockIssueCommentRepository = {
131
137
  getCommentsFromIssue: jest.fn().mockResolvedValue([]),
138
+ createComment: jest.fn().mockResolvedValue(undefined),
132
139
  };
133
140
  mockLocalCommandRunner = {
134
141
  runCommand: jest.fn(),
@@ -161,6 +168,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
161
168
  projectUrl: 'https://github.com/user/repo',
162
169
  allowIssueCacheMinutes: 60,
163
170
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
171
+ thresholdForAutoReject: 3,
164
172
  });
165
173
 
166
174
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
@@ -206,6 +214,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
206
214
  projectUrl: 'https://github.com/user/repo',
207
215
  allowIssueCacheMinutes: 60,
208
216
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
217
+ thresholdForAutoReject: 3,
209
218
  });
210
219
 
211
220
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
@@ -244,6 +253,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
244
253
  projectUrl: 'https://github.com/user/repo',
245
254
  allowIssueCacheMinutes: 60,
246
255
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
256
+ thresholdForAutoReject: 3,
247
257
  });
248
258
 
249
259
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
@@ -277,6 +287,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
277
287
  projectUrl: 'https://github.com/user/repo',
278
288
  allowIssueCacheMinutes: 60,
279
289
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
290
+ thresholdForAutoReject: 3,
280
291
  });
281
292
 
282
293
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
@@ -310,6 +321,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
310
321
  projectUrl: 'https://github.com/user/repo',
311
322
  allowIssueCacheMinutes: 60,
312
323
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
324
+ thresholdForAutoReject: 3,
313
325
  });
314
326
 
315
327
  expect(mockIssueRepository.findRelatedOpenPRs.mock.calls).toHaveLength(0);
@@ -344,6 +356,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
344
356
  projectUrl: 'https://github.com/user/repo',
345
357
  allowIssueCacheMinutes: 60,
346
358
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
359
+ thresholdForAutoReject: 3,
347
360
  });
348
361
 
349
362
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
@@ -377,13 +390,14 @@ describe('RevertOrphanedPreparationUseCase', () => {
377
390
  projectUrl: 'https://github.com/user/repo',
378
391
  allowIssueCacheMinutes: 60,
379
392
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
393
+ thresholdForAutoReject: 3,
380
394
  });
381
395
 
382
396
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
383
397
  expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('1');
384
398
  });
385
399
 
386
- it('should never post a comment regardless of orphan outcome', async () => {
400
+ it('should post Auto Status Check: REJECTED comment when orphan path reverts to Awaiting Workspace', async () => {
387
401
  const stuckIssue = createMockIssue({
388
402
  url: 'https://github.com/user/repo/issues/10',
389
403
  status: 'Preparation',
@@ -403,9 +417,18 @@ describe('RevertOrphanedPreparationUseCase', () => {
403
417
  projectUrl: 'https://github.com/user/repo',
404
418
  allowIssueCacheMinutes: 60,
405
419
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
420
+ thresholdForAutoReject: 3,
406
421
  });
407
422
 
408
423
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
424
+ expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('1');
425
+ expect(mockIssueCommentRepository.createComment.mock.calls).toHaveLength(1);
426
+ expect(mockIssueCommentRepository.createComment.mock.calls[0][0]).toBe(
427
+ stuckIssue,
428
+ );
429
+ expect(mockIssueCommentRepository.createComment.mock.calls[0][1]).toBe(
430
+ 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION',
431
+ );
409
432
  });
410
433
 
411
434
  it('should leave in-flight Preparation issue untouched when check command exits zero', async () => {
@@ -427,6 +450,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
427
450
  projectUrl: 'https://github.com/user/repo',
428
451
  allowIssueCacheMinutes: 60,
429
452
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
453
+ thresholdForAutoReject: 3,
430
454
  });
431
455
 
432
456
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(0);
@@ -459,6 +483,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
459
483
  projectUrl: 'https://github.com/user/repo',
460
484
  allowIssueCacheMinutes: 60,
461
485
  preparationProcessCheckCommand: 'check {URL}',
486
+ thresholdForAutoReject: 3,
462
487
  });
463
488
 
464
489
  expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
@@ -498,6 +523,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
498
523
  projectUrl: 'https://github.com/user/repo',
499
524
  allowIssueCacheMinutes: 60,
500
525
  preparationProcessCheckCommand: 'check {URL}',
526
+ thresholdForAutoReject: 3,
501
527
  });
502
528
 
503
529
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
@@ -512,6 +538,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
512
538
  projectUrl: 'https://github.com/user/repo',
513
539
  allowIssueCacheMinutes: 0,
514
540
  preparationProcessCheckCommand: 'check {URL}',
541
+ thresholdForAutoReject: 3,
515
542
  }),
516
543
  ).rejects.toThrow('Project not found');
517
544
  });
@@ -525,6 +552,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
525
552
  projectUrl: 'https://github.com/user/repo',
526
553
  allowIssueCacheMinutes: 0,
527
554
  preparationProcessCheckCommand: 'check {URL}',
555
+ thresholdForAutoReject: 3,
528
556
  }),
529
557
  ).rejects.toThrow('Project not found. projectId: project-1');
530
558
  });
@@ -560,6 +588,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
560
588
  projectUrl: 'https://github.com/user/repo',
561
589
  allowIssueCacheMinutes: 0,
562
590
  preparationProcessCheckCommand: 'check {URL}',
591
+ thresholdForAutoReject: 3,
563
592
  });
564
593
 
565
594
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(0);
@@ -578,6 +607,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
578
607
  projectUrl: 'https://github.com/user/repo',
579
608
  allowIssueCacheMinutes: 60,
580
609
  preparationProcessCheckCommand: 'check {URL}',
610
+ thresholdForAutoReject: 3,
581
611
  });
582
612
 
583
613
  expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(0);
@@ -614,6 +644,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
614
644
  projectUrl: 'https://github.com/user/repo',
615
645
  allowIssueCacheMinutes: 60,
616
646
  preparationProcessCheckCommand: 'pgrep -fa "Please handover {URL}"',
647
+ thresholdForAutoReject: 3,
617
648
  awLogDirectoryPath: '/home/user/logs-aw',
618
649
  awLogStaleThresholdMinutes: 15,
619
650
  });
@@ -676,6 +707,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
676
707
  projectUrl: 'https://github.com/user/repo',
677
708
  allowIssueCacheMinutes: 60,
678
709
  preparationProcessCheckCommand: 'pgrep -fa "Please handover {URL}"',
710
+ thresholdForAutoReject: 3,
679
711
  awLogDirectoryPath: '/home/user/logs-aw',
680
712
  awLogStaleThresholdMinutes: 15,
681
713
  });
@@ -710,6 +742,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
710
742
  projectUrl: 'https://github.com/user/repo',
711
743
  allowIssueCacheMinutes: 60,
712
744
  preparationProcessCheckCommand: 'pgrep -fa "Please handover {URL}"',
745
+ thresholdForAutoReject: 3,
713
746
  awLogDirectoryPath: '/home/user/logs-aw',
714
747
  awLogStaleThresholdMinutes: 15,
715
748
  });
@@ -740,6 +773,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
740
773
  projectUrl: 'https://github.com/user/repo',
741
774
  allowIssueCacheMinutes: 60,
742
775
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
776
+ thresholdForAutoReject: 3,
743
777
  });
744
778
 
745
779
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(0);
@@ -769,6 +803,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
769
803
  projectUrl: 'https://github.com/user/repo',
770
804
  allowIssueCacheMinutes: 60,
771
805
  preparationProcessCheckCommand: 'pgrep -fa "Please handover {URL}"',
806
+ thresholdForAutoReject: 3,
772
807
  awLogDirectoryPath: '/home/user/logs-aw',
773
808
  awLogStaleThresholdMinutes: 15,
774
809
  });
@@ -796,6 +831,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
796
831
  projectUrl: 'https://github.com/user/repo',
797
832
  allowIssueCacheMinutes: 0,
798
833
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
834
+ thresholdForAutoReject: 3,
799
835
  });
800
836
 
801
837
  expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
@@ -828,6 +864,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
828
864
  projectUrl: 'https://github.com/user/repo',
829
865
  allowIssueCacheMinutes: 60,
830
866
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
867
+ thresholdForAutoReject: 3,
831
868
  });
832
869
 
833
870
  expect(
@@ -837,4 +874,227 @@ describe('RevertOrphanedPreparationUseCase', () => {
837
874
  expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
838
875
  expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('4');
839
876
  });
877
+
878
+ it('should transition orphaned issue to Failed Preparation when rejection threshold is met', async () => {
879
+ const stuckIssue = createMockIssue({
880
+ url: 'https://github.com/user/repo/issues/10',
881
+ status: 'Preparation',
882
+ });
883
+ mockIssueRepository.getAllIssues.mockResolvedValue({
884
+ issues: [stuckIssue],
885
+ cacheUsed: false,
886
+ });
887
+ mockLocalCommandRunner.runCommand.mockResolvedValue({
888
+ stdout: '',
889
+ stderr: '',
890
+ exitCode: 1,
891
+ });
892
+ mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
893
+ {
894
+ author: 'bot',
895
+ content: 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION',
896
+ createdAt: new Date(),
897
+ },
898
+ {
899
+ author: 'bot',
900
+ content: 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION',
901
+ createdAt: new Date(),
902
+ },
903
+ ]);
904
+
905
+ await useCase.run({
906
+ projectUrl: 'https://github.com/user/repo',
907
+ allowIssueCacheMinutes: 60,
908
+ preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
909
+ thresholdForAutoReject: 3,
910
+ });
911
+
912
+ expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
913
+ expect(mockIssueRepository.updateStatus.mock.calls[0][0]).toBe(mockProject);
914
+ expect(mockIssueRepository.updateStatus.mock.calls[0][1]).toBe(stuckIssue);
915
+ expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('5');
916
+ expect(mockIssueCommentRepository.createComment.mock.calls).toHaveLength(1);
917
+ expect(mockIssueCommentRepository.createComment.mock.calls[0][0]).toBe(
918
+ stuckIssue,
919
+ );
920
+ expect(mockIssueCommentRepository.createComment.mock.calls[0][1]).toBe(
921
+ 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION\n\nFailed to pass the check automatically for 3 times',
922
+ );
923
+ });
924
+
925
+ it('should revert orphaned issue to Awaiting Workspace when rejection threshold is not yet met', async () => {
926
+ const stuckIssue = createMockIssue({
927
+ url: 'https://github.com/user/repo/issues/10',
928
+ status: 'Preparation',
929
+ });
930
+ mockIssueRepository.getAllIssues.mockResolvedValue({
931
+ issues: [stuckIssue],
932
+ cacheUsed: false,
933
+ });
934
+ mockLocalCommandRunner.runCommand.mockResolvedValue({
935
+ stdout: '',
936
+ stderr: '',
937
+ exitCode: 1,
938
+ });
939
+ mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
940
+ {
941
+ author: 'bot',
942
+ content: 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION',
943
+ createdAt: new Date(),
944
+ },
945
+ ]);
946
+
947
+ await useCase.run({
948
+ projectUrl: 'https://github.com/user/repo',
949
+ allowIssueCacheMinutes: 60,
950
+ preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
951
+ thresholdForAutoReject: 3,
952
+ });
953
+
954
+ expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
955
+ expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('1');
956
+ expect(mockIssueCommentRepository.createComment.mock.calls).toHaveLength(1);
957
+ expect(mockIssueCommentRepository.createComment.mock.calls[0][1]).toBe(
958
+ 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION',
959
+ );
960
+ });
961
+
962
+ it('should not transition to Failed Preparation when an earlier escalation comment is already in the recent window', async () => {
963
+ const stuckIssue = createMockIssue({
964
+ url: 'https://github.com/user/repo/issues/10',
965
+ status: 'Preparation',
966
+ });
967
+ mockIssueRepository.getAllIssues.mockResolvedValue({
968
+ issues: [stuckIssue],
969
+ cacheUsed: false,
970
+ });
971
+ mockLocalCommandRunner.runCommand.mockResolvedValue({
972
+ stdout: '',
973
+ stderr: '',
974
+ exitCode: 1,
975
+ });
976
+ mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
977
+ {
978
+ author: 'bot',
979
+ content:
980
+ 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION\n\nFailed to pass the check automatically for 3 times',
981
+ createdAt: new Date(),
982
+ },
983
+ {
984
+ author: 'bot',
985
+ content: 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION',
986
+ createdAt: new Date(),
987
+ },
988
+ {
989
+ author: 'bot',
990
+ content: 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION',
991
+ createdAt: new Date(),
992
+ },
993
+ ]);
994
+
995
+ await useCase.run({
996
+ projectUrl: 'https://github.com/user/repo',
997
+ allowIssueCacheMinutes: 60,
998
+ preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
999
+ thresholdForAutoReject: 3,
1000
+ });
1001
+
1002
+ expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
1003
+ expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('1');
1004
+ expect(mockIssueCommentRepository.createComment.mock.calls).toHaveLength(1);
1005
+ expect(mockIssueCommentRepository.createComment.mock.calls[0][1]).toBe(
1006
+ 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION',
1007
+ );
1008
+ });
1009
+
1010
+ it('should not post a rejection comment when orphaned issue advances to Awaiting Quality Check', async () => {
1011
+ const stuckIssue = createMockIssue({
1012
+ url: 'https://github.com/user/repo/issues/10',
1013
+ status: 'Preparation',
1014
+ });
1015
+ mockIssueRepository.getAllIssues.mockResolvedValue({
1016
+ issues: [stuckIssue],
1017
+ cacheUsed: false,
1018
+ });
1019
+ mockLocalCommandRunner.runCommand.mockResolvedValue({
1020
+ stdout: '',
1021
+ stderr: '',
1022
+ exitCode: 1,
1023
+ });
1024
+ mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
1025
+ {
1026
+ author: 'bot',
1027
+ content: 'From: :robot: agent report',
1028
+ createdAt: new Date(),
1029
+ },
1030
+ ]);
1031
+ mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([
1032
+ createPassingPr(),
1033
+ ]);
1034
+
1035
+ await useCase.run({
1036
+ projectUrl: 'https://github.com/user/repo',
1037
+ allowIssueCacheMinutes: 60,
1038
+ preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
1039
+ thresholdForAutoReject: 3,
1040
+ });
1041
+
1042
+ expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
1043
+ expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('4');
1044
+ expect(mockIssueCommentRepository.createComment.mock.calls).toHaveLength(0);
1045
+ });
1046
+
1047
+ it('should revert to Awaiting Workspace when Failed Preparation status option is not present even at threshold', async () => {
1048
+ const projectWithoutFailedPreparation = {
1049
+ ...mockProject,
1050
+ status: {
1051
+ ...mockProject.status,
1052
+ statuses: mockProject.status.statuses.filter(
1053
+ (s) => s.name !== 'Failed Preparation',
1054
+ ),
1055
+ },
1056
+ };
1057
+ mockProjectRepository.getProject.mockResolvedValue(
1058
+ projectWithoutFailedPreparation,
1059
+ );
1060
+ const stuckIssue = createMockIssue({
1061
+ url: 'https://github.com/user/repo/issues/10',
1062
+ status: 'Preparation',
1063
+ });
1064
+ mockIssueRepository.getAllIssues.mockResolvedValue({
1065
+ issues: [stuckIssue],
1066
+ cacheUsed: false,
1067
+ });
1068
+ mockLocalCommandRunner.runCommand.mockResolvedValue({
1069
+ stdout: '',
1070
+ stderr: '',
1071
+ exitCode: 1,
1072
+ });
1073
+ mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
1074
+ {
1075
+ author: 'bot',
1076
+ content: 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION',
1077
+ createdAt: new Date(),
1078
+ },
1079
+ {
1080
+ author: 'bot',
1081
+ content: 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION',
1082
+ createdAt: new Date(),
1083
+ },
1084
+ ]);
1085
+
1086
+ await useCase.run({
1087
+ projectUrl: 'https://github.com/user/repo',
1088
+ allowIssueCacheMinutes: 60,
1089
+ preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
1090
+ thresholdForAutoReject: 3,
1091
+ });
1092
+
1093
+ expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
1094
+ expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('1');
1095
+ expect(mockIssueCommentRepository.createComment.mock.calls).toHaveLength(1);
1096
+ expect(mockIssueCommentRepository.createComment.mock.calls[0][1]).toBe(
1097
+ 'Auto Status Check: REJECTED\n- ORPHANED_PREPARATION',
1098
+ );
1099
+ });
840
1100
  });