github-issue-tower-defence-management 1.69.3 → 1.69.5

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 (44) hide show
  1. package/.github/CODEOWNERS +5 -0
  2. package/.github/copilot-instructions.md +6 -0
  3. package/.github/dependabot.yml +17 -0
  4. package/.github/instructions/code-review.instructions.md +7 -0
  5. package/.github/workflows/api-created_issue_pr.yml +9 -1
  6. package/.github/workflows/codeql.yml +3 -0
  7. package/.github/workflows/commit-lint.yml +8 -0
  8. package/.github/workflows/configs/commitlint.config.js +5 -0
  9. package/.github/workflows/create-pr.yml +9 -1
  10. package/.github/workflows/empty-format-test-job.yml +6 -0
  11. package/.github/workflows/format.yml +3 -0
  12. package/.github/workflows/publish.yml +3 -0
  13. package/.github/workflows/secret-scan.yml +51 -0
  14. package/.github/workflows/test.yml +3 -0
  15. package/.github/workflows/umino-project.yml +22 -3
  16. package/.gitleaks.toml +9 -0
  17. package/CHANGELOG.md +14 -0
  18. package/README.md +2 -2
  19. package/bin/adapter/entry-points/cli/index.js +3 -2
  20. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  21. package/bin/adapter/entry-points/cli/projectConfig.js +24 -1
  22. package/bin/adapter/entry-points/cli/projectConfig.js.map +1 -1
  23. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +10 -3
  24. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  25. package/bin/domain/usecases/HandleScheduledEventUseCase.js +1 -0
  26. package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -1
  27. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js +33 -9
  28. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js.map +1 -1
  29. package/package.json +1 -1
  30. package/renovate.json +5 -0
  31. package/src/adapter/entry-points/cli/index.test.ts +102 -0
  32. package/src/adapter/entry-points/cli/index.ts +3 -2
  33. package/src/adapter/entry-points/cli/projectConfig.ts +30 -1
  34. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +5 -1
  35. package/src/domain/usecases/HandleScheduledEventUseCase.ts +2 -0
  36. package/src/domain/usecases/RevertOrphanedPreparationUseCase.test.ts +262 -2
  37. package/src/domain/usecases/RevertOrphanedPreparationUseCase.ts +71 -13
  38. package/types/adapter/entry-points/cli/projectConfig.d.ts +1 -1
  39. package/types/adapter/entry-points/cli/projectConfig.d.ts.map +1 -1
  40. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
  41. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts +1 -0
  42. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -1
  43. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts +3 -2
  44. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts.map +1 -1
@@ -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
  });
@@ -6,12 +6,16 @@ import { IssueCommentRepository } from './adapter-interfaces/IssueCommentReposit
6
6
  import { ProjectRepository } from './adapter-interfaces/ProjectRepository';
7
7
  import { LocalCommandRunner } from './adapter-interfaces/LocalCommandRunner';
8
8
  import { Issue } from '../entities/Issue';
9
+ import { Comment } from '../entities/Comment';
9
10
  import {
10
11
  AWAITING_QUALITY_CHECK_STATUS_NAME,
11
12
  AWAITING_WORKSPACE_STATUS_NAME,
13
+ FAILED_PREPARATION_STATUS_NAME,
12
14
  PREPARATION_STATUS_NAME,
13
15
  } from '../entities/WorkflowStatus';
14
16
 
17
+ const ORPHANED_PREPARATION_REJECTION_DETAIL = 'ORPHANED_PREPARATION';
18
+
15
19
  export class RevertOrphanedPreparationUseCase {
16
20
  constructor(
17
21
  readonly projectRepository: Pick<
@@ -27,7 +31,7 @@ export class RevertOrphanedPreparationUseCase {
27
31
  >,
28
32
  readonly issueCommentRepository: Pick<
29
33
  IssueCommentRepository,
30
- 'getCommentsFromIssue'
34
+ 'getCommentsFromIssue' | 'createComment'
31
35
  >,
32
36
  readonly localCommandRunner: LocalCommandRunner,
33
37
  ) {}
@@ -36,6 +40,7 @@ export class RevertOrphanedPreparationUseCase {
36
40
  projectUrl: string;
37
41
  allowIssueCacheMinutes: number;
38
42
  preparationProcessCheckCommand: string;
43
+ thresholdForAutoReject: number;
39
44
  awLogDirectoryPath?: string;
40
45
  awLogStaleThresholdMinutes?: number;
41
46
  awaitingQualityCheckStatus?: string | null;
@@ -74,11 +79,19 @@ export class RevertOrphanedPreparationUseCase {
74
79
  (s) => s.name === resolvedQualityCheckStatusName,
75
80
  );
76
81
 
82
+ const failedPreparationStatusOption = project.status.statuses.find(
83
+ (s) => s.name === FAILED_PREPARATION_STATUS_NAME,
84
+ );
85
+
77
86
  for (const issue of preparationIssues) {
78
87
  const isOrphaned = await this.isOrphanedIssue(issue, params);
79
- if (isOrphaned) {
80
- const hasRejections = await this.evaluateHasRejections(issue);
81
- if (!hasRejections && awaitingQualityCheckStatusOption) {
88
+ if (!isOrphaned) {
89
+ continue;
90
+ }
91
+ const { hasRejections, comments } =
92
+ await this.evaluateHasRejections(issue);
93
+ if (!hasRejections) {
94
+ if (awaitingQualityCheckStatusOption) {
82
95
  await this.issueRepository.updateStatus(
83
96
  project,
84
97
  issue,
@@ -91,22 +104,65 @@ export class RevertOrphanedPreparationUseCase {
91
104
  awaitingWorkspaceStatusOption.id,
92
105
  );
93
106
  }
107
+ continue;
108
+ }
109
+
110
+ const rejectionStatusMessage = `Auto Status Check: REJECTED\n- ${ORPHANED_PREPARATION_REJECTION_DETAIL}`;
111
+ const lastTargetComments = comments.slice(
112
+ -params.thresholdForAutoReject * 2,
113
+ );
114
+ const rejectionCommentCount = lastTargetComments.filter((comment) =>
115
+ comment.content.startsWith('Auto Status Check: REJECTED'),
116
+ ).length;
117
+ const alreadyEscalated = lastTargetComments.some((comment) =>
118
+ comment.content
119
+ .toLowerCase()
120
+ .includes('failed to pass the check automatically'),
121
+ );
122
+
123
+ if (
124
+ failedPreparationStatusOption &&
125
+ rejectionCommentCount + 1 >= params.thresholdForAutoReject &&
126
+ !alreadyEscalated
127
+ ) {
128
+ await this.issueRepository.updateStatus(
129
+ project,
130
+ issue,
131
+ failedPreparationStatusOption.id,
132
+ );
133
+ await this.issueCommentRepository.createComment(
134
+ issue,
135
+ `${rejectionStatusMessage}\n\nFailed to pass the check automatically for ${params.thresholdForAutoReject} times`,
136
+ );
137
+ continue;
94
138
  }
139
+
140
+ await this.issueRepository.updateStatus(
141
+ project,
142
+ issue,
143
+ awaitingWorkspaceStatusOption.id,
144
+ );
145
+ await this.issueCommentRepository.createComment(
146
+ issue,
147
+ rejectionStatusMessage,
148
+ );
95
149
  }
96
150
  };
97
151
 
98
- private evaluateHasRejections = async (issue: Issue): Promise<boolean> => {
152
+ private evaluateHasRejections = async (
153
+ issue: Issue,
154
+ ): Promise<{ hasRejections: boolean; comments: Comment[] }> => {
99
155
  if (issue.isClosed) {
100
- return false;
156
+ return { hasRejections: false, comments: [] };
101
157
  }
102
158
  const comments =
103
159
  await this.issueCommentRepository.getCommentsFromIssue(issue);
104
160
  const lastComment = comments[comments.length - 1];
105
161
  if (!lastComment || !lastComment.content.startsWith('From: :robot:')) {
106
- return true;
162
+ return { hasRejections: true, comments };
107
163
  }
108
164
  if (this.reportBodyHasNextStep(lastComment.content)) {
109
- return true;
165
+ return { hasRejections: true, comments };
110
166
  }
111
167
 
112
168
  const categoryLabels = issue.labels.filter((label) =>
@@ -119,7 +175,7 @@ export class RevertOrphanedPreparationUseCase {
119
175
  hasLlmAgentLabel ||
120
176
  (categoryLabels.length > 0 && !categoryLabels.includes('category:e2e'))
121
177
  ) {
122
- return false;
178
+ return { hasRejections: false, comments };
123
179
  }
124
180
 
125
181
  const prsToCheck = issue.isPr
@@ -127,13 +183,15 @@ export class RevertOrphanedPreparationUseCase {
127
183
  : await this.issueRepository.findRelatedOpenPRs(issue.url);
128
184
 
129
185
  if (prsToCheck.length !== 1) {
130
- return true;
186
+ return { hasRejections: true, comments };
131
187
  }
132
188
 
133
189
  const pr = prsToCheck[0];
134
- return (
135
- pr.isConflicted || !pr.isPassedAllCiJob || !pr.isResolvedAllReviewComments
136
- );
190
+ const hasRejections =
191
+ pr.isConflicted ||
192
+ !pr.isPassedAllCiJob ||
193
+ !pr.isResolvedAllReviewComments;
194
+ return { hasRejections, comments };
137
195
  };
138
196
 
139
197
  private resolveOpenPrsForPrItem = async (
@@ -19,7 +19,7 @@ export type ConfigFile = {
19
19
  };
20
20
  export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
21
21
  export declare const loadConfigFile: (configFilePath: string) => ConfigFile;
22
- export declare const parseProjectReadmeConfig: (readme: string) => ConfigFile;
22
+ export declare const parseProjectReadmeConfig: (readme: string, projectUrl?: string) => ConfigFile;
23
23
  export declare const mergeConfigs: (configFile: ConfigFile, cliOverrides: ConfigFile, readmeOverrides: ConfigFile) => ConfigFile;
24
24
  export declare const fetchProjectReadme: (projectUrl: string, token: string) => Promise<string | null>;
25
25
  //# sourceMappingURL=projectConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"projectConfig.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/projectConfig.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iCAAiC,CAAC,EAAE,MAAM,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC,CAAC;AAoCF,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACH,CAAC;AAEvE,eAAO,MAAM,cAAc,GAAI,gBAAgB,MAAM,KAAG,UAmDvD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,QAAQ,MAAM,KAAG,UAsDzD,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,YAAY,UAAU,EACtB,cAAc,UAAU,EACxB,iBAAiB,UAAU,KAC1B,UA+DD,CAAC;AAkBH,eAAO,MAAM,kBAAkB,GAC7B,YAAY,MAAM,EAClB,OAAO,MAAM,KACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CA0DvB,CAAC"}
1
+ {"version":3,"file":"projectConfig.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/projectConfig.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iCAAiC,CAAC,EAAE,MAAM,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC,CAAC;AAoCF,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACH,CAAC;AAmBvE,eAAO,MAAM,cAAc,GAAI,gBAAgB,MAAM,KAAG,UAmDvD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,MAAM,EACd,aAAa,MAAM,KAClB,UA+DF,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,YAAY,UAAU,EACtB,cAAc,UAAU,EACxB,iBAAiB,UAAU,KAC1B,UA+DD,CAAC;AAkBH,eAAO,MAAM,kBAAkB,GAC7B,YAAY,MAAM,EAClB,OAAO,MAAM,KACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CA0DvB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AA2B3D,qBAAa,kCAAkC;IAC7C,MAAM,GACJ,gBAAgB,MAAM,EACtB,UAAU,OAAO,KAChB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,IAAI,EAAE,CAAC;KACzB,GAAG,IAAI,CAAC,CAmPP;CACH"}
1
+ {"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AA2B3D,qBAAa,kCAAkC;IAC7C,MAAM,GACJ,gBAAgB,MAAM,EACtB,UAAU,OAAO,KAChB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,IAAI,EAAE,CAAC;KACzB,GAAG,IAAI,CAAC,CAuPP;CACH"}
@@ -82,6 +82,7 @@ export declare class HandleScheduledEventUseCase {
82
82
  notifyFinishedPreparation?: {
83
83
  awaitingQualityCheckStatusName?: string | null;
84
84
  } | null;
85
+ thresholdForAutoReject?: number;
85
86
  }) => Promise<{
86
87
  project: Project;
87
88
  issues: Issue[];
@@ -1 +1 @@
1
- {"version":3,"file":"HandleScheduledEventUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/HandleScheduledEventUseCase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"HandleScheduledEventUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/HandleScheduledEventUseCase.ts"],"names":[],"mappings":"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"}
@@ -5,13 +5,14 @@ import { LocalCommandRunner } from './adapter-interfaces/LocalCommandRunner';
5
5
  export declare class RevertOrphanedPreparationUseCase {
6
6
  readonly projectRepository: Pick<ProjectRepository, 'findProjectIdByUrl' | 'getProject'>;
7
7
  readonly issueRepository: Pick<IssueRepository, 'getAllIssues' | 'updateStatus' | 'findRelatedOpenPRs' | 'getOpenPullRequest'>;
8
- readonly issueCommentRepository: Pick<IssueCommentRepository, 'getCommentsFromIssue'>;
8
+ readonly issueCommentRepository: Pick<IssueCommentRepository, 'getCommentsFromIssue' | 'createComment'>;
9
9
  readonly localCommandRunner: LocalCommandRunner;
10
- constructor(projectRepository: Pick<ProjectRepository, 'findProjectIdByUrl' | 'getProject'>, issueRepository: Pick<IssueRepository, 'getAllIssues' | 'updateStatus' | 'findRelatedOpenPRs' | 'getOpenPullRequest'>, issueCommentRepository: Pick<IssueCommentRepository, 'getCommentsFromIssue'>, localCommandRunner: LocalCommandRunner);
10
+ constructor(projectRepository: Pick<ProjectRepository, 'findProjectIdByUrl' | 'getProject'>, issueRepository: Pick<IssueRepository, 'getAllIssues' | 'updateStatus' | 'findRelatedOpenPRs' | 'getOpenPullRequest'>, issueCommentRepository: Pick<IssueCommentRepository, 'getCommentsFromIssue' | 'createComment'>, localCommandRunner: LocalCommandRunner);
11
11
  run: (params: {
12
12
  projectUrl: string;
13
13
  allowIssueCacheMinutes: number;
14
14
  preparationProcessCheckCommand: string;
15
+ thresholdForAutoReject: number;
15
16
  awLogDirectoryPath?: string;
16
17
  awLogStaleThresholdMinutes?: number;
17
18
  awaitingQualityCheckStatus?: string | null;