github-issue-tower-defence-management 1.120.0 → 1.122.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 (123) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +8 -9
  3. package/bin/adapter/entry-points/cli/index.js +8 -14
  4. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  5. package/bin/adapter/entry-points/cli/projectConfig.js +0 -6
  6. package/bin/adapter/entry-points/cli/projectConfig.js.map +1 -1
  7. package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js +6 -12
  8. package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js.map +1 -1
  9. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +8 -10
  10. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  11. package/bin/adapter/entry-points/handlers/inTmuxByHumanDataWriter.js +2 -1
  12. package/bin/adapter/entry-points/handlers/inTmuxByHumanDataWriter.js.map +1 -1
  13. package/bin/adapter/entry-points/handlers/machineStatusWriter.js +23 -19
  14. package/bin/adapter/entry-points/handlers/machineStatusWriter.js.map +1 -1
  15. package/bin/adapter/entry-points/handlers/situationFileWriter.js.map +1 -1
  16. package/bin/adapter/entry-points/handlers/staleTmuxSessionCleaner.js +1 -2
  17. package/bin/adapter/entry-points/handlers/staleTmuxSessionCleaner.js.map +1 -1
  18. package/bin/adapter/repositories/LocalStorageCacheRepository.js +25 -0
  19. package/bin/adapter/repositories/LocalStorageCacheRepository.js.map +1 -1
  20. package/bin/adapter/repositories/ProcHostMetricsRepository.js +10 -5
  21. package/bin/adapter/repositories/ProcHostMetricsRepository.js.map +1 -1
  22. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +119 -59
  23. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
  24. package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js +12 -3
  25. package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js.map +1 -1
  26. package/bin/domain/usecases/GetStoryObjectMapUseCase.js +1 -1
  27. package/bin/domain/usecases/GetStoryObjectMapUseCase.js.map +1 -1
  28. package/bin/domain/usecases/HandleScheduledEventUseCase.js +1 -8
  29. package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -1
  30. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +2 -2
  31. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
  32. package/bin/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.js +1 -1
  33. package/bin/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.js.map +1 -1
  34. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js +1 -1
  35. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js.map +1 -1
  36. package/bin/domain/usecases/SetupTowerDefenceProjectUseCase.js +1 -1
  37. package/bin/domain/usecases/SetupTowerDefenceProjectUseCase.js.map +1 -1
  38. package/bin/domain/usecases/StaleTmuxSessionKillUseCase.js +1 -1
  39. package/bin/domain/usecases/StaleTmuxSessionKillUseCase.js.map +1 -1
  40. package/bin/domain/usecases/StartPreparationUseCase.js +1 -1
  41. package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -1
  42. package/bin/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.js +2 -2
  43. package/bin/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.js.map +1 -1
  44. package/package.json +1 -1
  45. package/src/adapter/entry-points/cli/index.test.ts +0 -5
  46. package/src/adapter/entry-points/cli/index.ts +16 -17
  47. package/src/adapter/entry-points/cli/projectConfig.ts +0 -8
  48. package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.test.ts +4 -25
  49. package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.ts +4 -7
  50. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.test.ts +2 -25
  51. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +4 -4
  52. package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.test.ts +11 -0
  53. package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.ts +3 -0
  54. package/src/adapter/entry-points/handlers/machineStatusWriter.test.ts +29 -11
  55. package/src/adapter/entry-points/handlers/machineStatusWriter.ts +30 -19
  56. package/src/adapter/entry-points/handlers/situationFileWriter.test.ts +0 -5
  57. package/src/adapter/entry-points/handlers/situationFileWriter.ts +0 -1
  58. package/src/adapter/entry-points/handlers/staleTmuxSessionCleaner.test.ts +0 -5
  59. package/src/adapter/entry-points/handlers/staleTmuxSessionCleaner.ts +1 -9
  60. package/src/adapter/repositories/LocalStorageCacheRepository.test.ts +75 -0
  61. package/src/adapter/repositories/LocalStorageCacheRepository.ts +24 -0
  62. package/src/adapter/repositories/ProcHostMetricsRepository.test.ts +29 -8
  63. package/src/adapter/repositories/ProcHostMetricsRepository.ts +10 -6
  64. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +198 -47
  65. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +160 -81
  66. package/src/adapter/repositories/issue/GraphqlProjectItemRepository.ts +23 -3
  67. package/src/domain/usecases/GetStoryObjectMapUseCase.test.ts +7 -12
  68. package/src/domain/usecases/GetStoryObjectMapUseCase.ts +1 -5
  69. package/src/domain/usecases/HandleScheduledEventUseCase.test.ts +8 -24
  70. package/src/domain/usecases/HandleScheduledEventUseCase.ts +6 -17
  71. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +4 -8
  72. package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.test.ts +35 -42
  73. package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.ts +1 -5
  74. package/src/domain/usecases/RevertOrphanedPreparationUseCase.test.ts +32 -32
  75. package/src/domain/usecases/RevertOrphanedPreparationUseCase.ts +1 -5
  76. package/src/domain/usecases/SetupTowerDefenceProjectUseCase.test.ts +17 -4
  77. package/src/domain/usecases/SetupTowerDefenceProjectUseCase.ts +1 -4
  78. package/src/domain/usecases/StaleTmuxSessionKillUseCase.test.ts +1 -7
  79. package/src/domain/usecases/StaleTmuxSessionKillUseCase.ts +1 -5
  80. package/src/domain/usecases/StartPreparationUseCase.test.ts +1 -94
  81. package/src/domain/usecases/StartPreparationUseCase.ts +2 -5
  82. package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +3 -10
  83. package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.test.ts +11 -0
  84. package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.ts +3 -1
  85. package/types/adapter/entry-points/cli/projectConfig.d.ts +0 -1
  86. package/types/adapter/entry-points/cli/projectConfig.d.ts.map +1 -1
  87. package/types/adapter/entry-points/function/getStoryObjectMap.d.ts +1 -1
  88. package/types/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.d.ts +1 -1
  89. package/types/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.d.ts.map +1 -1
  90. package/types/adapter/entry-points/handlers/inTmuxByHumanDataWriter.d.ts +1 -0
  91. package/types/adapter/entry-points/handlers/inTmuxByHumanDataWriter.d.ts.map +1 -1
  92. package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts +1 -0
  93. package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts.map +1 -1
  94. package/types/adapter/entry-points/handlers/situationFileWriter.d.ts +0 -1
  95. package/types/adapter/entry-points/handlers/situationFileWriter.d.ts.map +1 -1
  96. package/types/adapter/entry-points/handlers/staleTmuxSessionCleaner.d.ts +0 -1
  97. package/types/adapter/entry-points/handlers/staleTmuxSessionCleaner.d.ts.map +1 -1
  98. package/types/adapter/repositories/LocalStorageCacheRepository.d.ts +2 -0
  99. package/types/adapter/repositories/LocalStorageCacheRepository.d.ts.map +1 -1
  100. package/types/adapter/repositories/ProcHostMetricsRepository.d.ts +1 -1
  101. package/types/adapter/repositories/ProcHostMetricsRepository.d.ts.map +1 -1
  102. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +22 -7
  103. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
  104. package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts +2 -1
  105. package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts.map +1 -1
  106. package/types/domain/usecases/GetStoryObjectMapUseCase.d.ts +0 -1
  107. package/types/domain/usecases/GetStoryObjectMapUseCase.d.ts.map +1 -1
  108. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts +0 -1
  109. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -1
  110. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
  111. package/types/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.d.ts +0 -1
  112. package/types/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.d.ts.map +1 -1
  113. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts +0 -1
  114. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts.map +1 -1
  115. package/types/domain/usecases/SetupTowerDefenceProjectUseCase.d.ts.map +1 -1
  116. package/types/domain/usecases/StaleTmuxSessionKillUseCase.d.ts +0 -1
  117. package/types/domain/usecases/StaleTmuxSessionKillUseCase.d.ts.map +1 -1
  118. package/types/domain/usecases/StartPreparationUseCase.d.ts +0 -1
  119. package/types/domain/usecases/StartPreparationUseCase.d.ts.map +1 -1
  120. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +4 -3
  121. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -1
  122. package/types/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.d.ts +1 -0
  123. package/types/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.d.ts.map +1 -1
@@ -128,9 +128,11 @@ describe('RevertOrphanedPreparationUseCase', () => {
128
128
  getProject: jest.fn().mockResolvedValue(mockProject),
129
129
  };
130
130
  mockIssueRepository = {
131
- getAllIssues: jest
132
- .fn()
133
- .mockResolvedValue({ issues: [], cacheUsed: false }),
131
+ getAllIssues: jest.fn().mockResolvedValue({
132
+ project: mockProject,
133
+ issues: [],
134
+ cacheUsed: false,
135
+ }),
134
136
  updateStatus: jest.fn().mockResolvedValue(undefined),
135
137
  findRelatedOpenPRs: jest.fn().mockResolvedValue([]),
136
138
  getOpenPullRequest: jest.fn().mockResolvedValue(null),
@@ -156,6 +158,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
156
158
  status: 'Preparation',
157
159
  });
158
160
  mockIssueRepository.getAllIssues.mockResolvedValue({
161
+ project: mockProject,
159
162
  issues: [stuckIssue],
160
163
  cacheUsed: false,
161
164
  });
@@ -168,7 +171,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
168
171
 
169
172
  await useCase.run({
170
173
  projectUrl: 'https://github.com/user/repo',
171
- allowIssueCacheMinutes: 60,
172
174
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
173
175
  thresholdForAutoReject: 3,
174
176
  });
@@ -193,6 +195,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
193
195
  status: 'Preparation',
194
196
  });
195
197
  mockIssueRepository.getAllIssues.mockResolvedValue({
198
+ project: mockProject,
196
199
  issues: [stuckIssue],
197
200
  cacheUsed: false,
198
201
  });
@@ -214,7 +217,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
214
217
 
215
218
  await useCase.run({
216
219
  projectUrl: 'https://github.com/user/repo',
217
- allowIssueCacheMinutes: 60,
218
220
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
219
221
  thresholdForAutoReject: 3,
220
222
  });
@@ -229,6 +231,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
229
231
  status: 'Preparation',
230
232
  });
231
233
  mockIssueRepository.getAllIssues.mockResolvedValue({
234
+ project: mockProject,
232
235
  issues: [stuckIssue],
233
236
  cacheUsed: false,
234
237
  });
@@ -253,7 +256,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
253
256
 
254
257
  await useCase.run({
255
258
  projectUrl: 'https://github.com/user/repo',
256
- allowIssueCacheMinutes: 60,
257
259
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
258
260
  thresholdForAutoReject: 3,
259
261
  });
@@ -268,6 +270,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
268
270
  status: 'Preparation',
269
271
  });
270
272
  mockIssueRepository.getAllIssues.mockResolvedValue({
273
+ project: mockProject,
271
274
  issues: [stuckIssue],
272
275
  cacheUsed: false,
273
276
  });
@@ -287,7 +290,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
287
290
 
288
291
  await useCase.run({
289
292
  projectUrl: 'https://github.com/user/repo',
290
- allowIssueCacheMinutes: 60,
291
293
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
292
294
  thresholdForAutoReject: 3,
293
295
  });
@@ -303,6 +305,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
303
305
  labels: ['llm-agent'],
304
306
  });
305
307
  mockIssueRepository.getAllIssues.mockResolvedValue({
308
+ project: mockProject,
306
309
  issues: [stuckIssue],
307
310
  cacheUsed: false,
308
311
  });
@@ -321,7 +324,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
321
324
 
322
325
  await useCase.run({
323
326
  projectUrl: 'https://github.com/user/repo',
324
- allowIssueCacheMinutes: 60,
325
327
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
326
328
  thresholdForAutoReject: 3,
327
329
  });
@@ -338,6 +340,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
338
340
  labels: ['story'],
339
341
  });
340
342
  mockIssueRepository.getAllIssues.mockResolvedValue({
343
+ project: mockProject,
341
344
  issues: [stuckIssue],
342
345
  cacheUsed: false,
343
346
  });
@@ -356,7 +359,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
356
359
 
357
360
  await useCase.run({
358
361
  projectUrl: 'https://github.com/user/repo',
359
- allowIssueCacheMinutes: 60,
360
362
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
361
363
  thresholdForAutoReject: 3,
362
364
  labelsAsLlmAgentName: ['story'],
@@ -374,6 +376,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
374
376
  labels: ['story'],
375
377
  });
376
378
  mockIssueRepository.getAllIssues.mockResolvedValue({
379
+ project: mockProject,
377
380
  issues: [stuckIssue],
378
381
  cacheUsed: false,
379
382
  });
@@ -393,7 +396,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
393
396
 
394
397
  await useCase.run({
395
398
  projectUrl: 'https://github.com/user/repo',
396
- allowIssueCacheMinutes: 60,
397
399
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
398
400
  thresholdForAutoReject: 3,
399
401
  labelsAsLlmAgentName: ['bug'],
@@ -410,6 +412,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
410
412
  status: 'Preparation',
411
413
  });
412
414
  mockIssueRepository.getAllIssues.mockResolvedValue({
415
+ project: mockProject,
413
416
  issues: [stuckIssue],
414
417
  cacheUsed: false,
415
418
  });
@@ -429,7 +432,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
429
432
 
430
433
  await useCase.run({
431
434
  projectUrl: 'https://github.com/user/repo',
432
- allowIssueCacheMinutes: 60,
433
435
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
434
436
  thresholdForAutoReject: 3,
435
437
  });
@@ -444,6 +446,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
444
446
  status: 'Preparation',
445
447
  });
446
448
  mockIssueRepository.getAllIssues.mockResolvedValue({
449
+ project: mockProject,
447
450
  issues: [stuckIssue],
448
451
  cacheUsed: false,
449
452
  });
@@ -463,7 +466,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
463
466
 
464
467
  await useCase.run({
465
468
  projectUrl: 'https://github.com/user/repo',
466
- allowIssueCacheMinutes: 60,
467
469
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
468
470
  thresholdForAutoReject: 3,
469
471
  });
@@ -478,6 +480,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
478
480
  status: 'Preparation',
479
481
  });
480
482
  mockIssueRepository.getAllIssues.mockResolvedValue({
483
+ project: mockProject,
481
484
  issues: [stuckIssue],
482
485
  cacheUsed: false,
483
486
  });
@@ -490,7 +493,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
490
493
 
491
494
  await useCase.run({
492
495
  projectUrl: 'https://github.com/user/repo',
493
- allowIssueCacheMinutes: 60,
494
496
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
495
497
  thresholdForAutoReject: 3,
496
498
  });
@@ -512,6 +514,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
512
514
  status: 'Preparation',
513
515
  });
514
516
  mockIssueRepository.getAllIssues.mockResolvedValue({
517
+ project: mockProject,
515
518
  issues: [inFlightIssue],
516
519
  cacheUsed: false,
517
520
  });
@@ -523,7 +526,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
523
526
 
524
527
  await useCase.run({
525
528
  projectUrl: 'https://github.com/user/repo',
526
- allowIssueCacheMinutes: 60,
527
529
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
528
530
  thresholdForAutoReject: 3,
529
531
  });
@@ -544,6 +546,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
544
546
  status: 'Awaiting Workspace',
545
547
  });
546
548
  mockIssueRepository.getAllIssues.mockResolvedValue({
549
+ project: mockProject,
547
550
  issues: [preparationIssue, awaitingIssue],
548
551
  cacheUsed: false,
549
552
  });
@@ -556,7 +559,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
556
559
 
557
560
  await useCase.run({
558
561
  projectUrl: 'https://github.com/user/repo',
559
- allowIssueCacheMinutes: 60,
560
562
  preparationProcessCheckCommand: 'check {URL}',
561
563
  thresholdForAutoReject: 3,
562
564
  });
@@ -582,6 +584,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
582
584
  status: 'Preparation',
583
585
  });
584
586
  mockIssueRepository.getAllIssues.mockResolvedValue({
587
+ project: mockProject,
585
588
  issues: [stuckIssue, inFlightIssue],
586
589
  cacheUsed: false,
587
590
  });
@@ -596,7 +599,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
596
599
 
597
600
  await useCase.run({
598
601
  projectUrl: 'https://github.com/user/repo',
599
- allowIssueCacheMinutes: 60,
600
602
  preparationProcessCheckCommand: 'check {URL}',
601
603
  thresholdForAutoReject: 3,
602
604
  });
@@ -611,7 +613,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
611
613
  await expect(
612
614
  useCase.run({
613
615
  projectUrl: 'https://github.com/user/repo',
614
- allowIssueCacheMinutes: 0,
615
616
  preparationProcessCheckCommand: 'check {URL}',
616
617
  thresholdForAutoReject: 3,
617
618
  }),
@@ -625,7 +626,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
625
626
  await expect(
626
627
  useCase.run({
627
628
  projectUrl: 'https://github.com/user/repo',
628
- allowIssueCacheMinutes: 0,
629
629
  preparationProcessCheckCommand: 'check {URL}',
630
630
  thresholdForAutoReject: 3,
631
631
  }),
@@ -650,6 +650,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
650
650
  projectWithoutAwaitingWorkspace,
651
651
  );
652
652
  mockIssueRepository.getAllIssues.mockResolvedValue({
653
+ project: mockProject,
653
654
  issues: [preparationIssue],
654
655
  cacheUsed: false,
655
656
  });
@@ -661,7 +662,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
661
662
 
662
663
  await useCase.run({
663
664
  projectUrl: 'https://github.com/user/repo',
664
- allowIssueCacheMinutes: 0,
665
665
  preparationProcessCheckCommand: 'check {URL}',
666
666
  thresholdForAutoReject: 3,
667
667
  });
@@ -671,6 +671,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
671
671
 
672
672
  it('should do nothing when there are no Preparation issues', async () => {
673
673
  mockIssueRepository.getAllIssues.mockResolvedValue({
674
+ project: mockProject,
674
675
  issues: [
675
676
  createMockIssue({ status: 'Awaiting Workspace' }),
676
677
  createMockIssue({ status: 'Done' }),
@@ -680,7 +681,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
680
681
 
681
682
  await useCase.run({
682
683
  projectUrl: 'https://github.com/user/repo',
683
- allowIssueCacheMinutes: 60,
684
684
  preparationProcessCheckCommand: 'check {URL}',
685
685
  thresholdForAutoReject: 3,
686
686
  });
@@ -698,6 +698,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
698
698
  status: 'Preparation',
699
699
  });
700
700
  mockIssueRepository.getAllIssues.mockResolvedValue({
701
+ project: mockProject,
701
702
  issues: [zombieIssue],
702
703
  cacheUsed: false,
703
704
  });
@@ -717,7 +718,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
717
718
 
718
719
  await useCase.run({
719
720
  projectUrl: 'https://github.com/user/repo',
720
- allowIssueCacheMinutes: 60,
721
721
  preparationProcessCheckCommand: 'pgrep -fa "Please handover {URL}"',
722
722
  thresholdForAutoReject: 3,
723
723
  awLogDirectoryPath: '/home/user/logs-aw',
@@ -758,6 +758,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
758
758
  status: 'Preparation',
759
759
  });
760
760
  mockIssueRepository.getAllIssues.mockResolvedValue({
761
+ project: mockProject,
761
762
  issues: [activeIssue],
762
763
  cacheUsed: false,
763
764
  });
@@ -780,7 +781,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
780
781
 
781
782
  await useCase.run({
782
783
  projectUrl: 'https://github.com/user/repo',
783
- allowIssueCacheMinutes: 60,
784
784
  preparationProcessCheckCommand: 'pgrep -fa "Please handover {URL}"',
785
785
  thresholdForAutoReject: 3,
786
786
  awLogDirectoryPath: '/home/user/logs-aw',
@@ -802,6 +802,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
802
802
  status: 'Preparation',
803
803
  });
804
804
  mockIssueRepository.getAllIssues.mockResolvedValue({
805
+ project: mockProject,
805
806
  issues: [newIssue],
806
807
  cacheUsed: false,
807
808
  });
@@ -815,7 +816,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
815
816
 
816
817
  await useCase.run({
817
818
  projectUrl: 'https://github.com/user/repo',
818
- allowIssueCacheMinutes: 60,
819
819
  preparationProcessCheckCommand: 'pgrep -fa "Please handover {URL}"',
820
820
  thresholdForAutoReject: 3,
821
821
  awLogDirectoryPath: '/home/user/logs-aw',
@@ -835,6 +835,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
835
835
  status: 'Preparation',
836
836
  });
837
837
  mockIssueRepository.getAllIssues.mockResolvedValue({
838
+ project: mockProject,
838
839
  issues: [inFlightIssue],
839
840
  cacheUsed: false,
840
841
  });
@@ -846,7 +847,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
846
847
 
847
848
  await useCase.run({
848
849
  projectUrl: 'https://github.com/user/repo',
849
- allowIssueCacheMinutes: 60,
850
850
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
851
851
  thresholdForAutoReject: 3,
852
852
  });
@@ -864,6 +864,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
864
864
  status: 'Preparation',
865
865
  });
866
866
  mockIssueRepository.getAllIssues.mockResolvedValue({
867
+ project: mockProject,
867
868
  issues: [stuckIssue],
868
869
  cacheUsed: false,
869
870
  });
@@ -876,7 +877,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
876
877
 
877
878
  await useCase.run({
878
879
  projectUrl: 'https://github.com/user/repo',
879
- allowIssueCacheMinutes: 60,
880
880
  preparationProcessCheckCommand: 'pgrep -fa "Please handover {URL}"',
881
881
  thresholdForAutoReject: 3,
882
882
  awLogDirectoryPath: '/home/user/logs-aw',
@@ -893,6 +893,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
893
893
  status: 'Preparation',
894
894
  });
895
895
  mockIssueRepository.getAllIssues.mockResolvedValue({
896
+ project: mockProject,
896
897
  issues: [issue],
897
898
  cacheUsed: false,
898
899
  });
@@ -904,7 +905,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
904
905
 
905
906
  await useCase.run({
906
907
  projectUrl: 'https://github.com/user/repo',
907
- allowIssueCacheMinutes: 0,
908
908
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
909
909
  thresholdForAutoReject: 3,
910
910
  });
@@ -926,6 +926,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
926
926
  isClosed: true,
927
927
  });
928
928
  mockIssueRepository.getAllIssues.mockResolvedValue({
929
+ project: mockProject,
929
930
  issues: [closedIssue],
930
931
  cacheUsed: false,
931
932
  });
@@ -937,7 +938,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
937
938
 
938
939
  await useCase.run({
939
940
  projectUrl: 'https://github.com/user/repo',
940
- allowIssueCacheMinutes: 60,
941
941
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
942
942
  thresholdForAutoReject: 3,
943
943
  });
@@ -956,6 +956,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
956
956
  status: 'Preparation',
957
957
  });
958
958
  mockIssueRepository.getAllIssues.mockResolvedValue({
959
+ project: mockProject,
959
960
  issues: [stuckIssue],
960
961
  cacheUsed: false,
961
962
  });
@@ -979,7 +980,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
979
980
 
980
981
  await useCase.run({
981
982
  projectUrl: 'https://github.com/user/repo',
982
- allowIssueCacheMinutes: 60,
983
983
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
984
984
  thresholdForAutoReject: 3,
985
985
  });
@@ -1003,6 +1003,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
1003
1003
  status: 'Preparation',
1004
1004
  });
1005
1005
  mockIssueRepository.getAllIssues.mockResolvedValue({
1006
+ project: mockProject,
1006
1007
  issues: [stuckIssue],
1007
1008
  cacheUsed: false,
1008
1009
  });
@@ -1021,7 +1022,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
1021
1022
 
1022
1023
  await useCase.run({
1023
1024
  projectUrl: 'https://github.com/user/repo',
1024
- allowIssueCacheMinutes: 60,
1025
1025
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
1026
1026
  thresholdForAutoReject: 3,
1027
1027
  });
@@ -1040,6 +1040,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
1040
1040
  status: 'Preparation',
1041
1041
  });
1042
1042
  mockIssueRepository.getAllIssues.mockResolvedValue({
1043
+ project: mockProject,
1043
1044
  issues: [stuckIssue],
1044
1045
  cacheUsed: false,
1045
1046
  });
@@ -1069,7 +1070,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
1069
1070
 
1070
1071
  await useCase.run({
1071
1072
  projectUrl: 'https://github.com/user/repo',
1072
- allowIssueCacheMinutes: 60,
1073
1073
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
1074
1074
  thresholdForAutoReject: 3,
1075
1075
  });
@@ -1088,6 +1088,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
1088
1088
  status: 'Preparation',
1089
1089
  });
1090
1090
  mockIssueRepository.getAllIssues.mockResolvedValue({
1091
+ project: mockProject,
1091
1092
  issues: [stuckIssue],
1092
1093
  cacheUsed: false,
1093
1094
  });
@@ -1109,7 +1110,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
1109
1110
 
1110
1111
  await useCase.run({
1111
1112
  projectUrl: 'https://github.com/user/repo',
1112
- allowIssueCacheMinutes: 60,
1113
1113
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
1114
1114
  thresholdForAutoReject: 3,
1115
1115
  });
@@ -1137,6 +1137,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
1137
1137
  status: 'Preparation',
1138
1138
  });
1139
1139
  mockIssueRepository.getAllIssues.mockResolvedValue({
1140
+ project: mockProject,
1140
1141
  issues: [stuckIssue],
1141
1142
  cacheUsed: false,
1142
1143
  });
@@ -1160,7 +1161,6 @@ describe('RevertOrphanedPreparationUseCase', () => {
1160
1161
 
1161
1162
  await useCase.run({
1162
1163
  projectUrl: 'https://github.com/user/repo',
1163
- allowIssueCacheMinutes: 60,
1164
1164
  preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
1165
1165
  thresholdForAutoReject: 3,
1166
1166
  });
@@ -38,7 +38,6 @@ export class RevertOrphanedPreparationUseCase {
38
38
 
39
39
  run = async (params: {
40
40
  projectUrl: string;
41
- allowIssueCacheMinutes: number;
42
41
  preparationProcessCheckCommand: string;
43
42
  thresholdForAutoReject: number;
44
43
  awLogDirectoryPath?: string;
@@ -58,10 +57,7 @@ export class RevertOrphanedPreparationUseCase {
58
57
  `Project not found. projectId: ${projectId} projectUrl: ${params.projectUrl}`,
59
58
  );
60
59
  }
61
- const { issues } = await this.issueRepository.getAllIssues(
62
- projectId,
63
- params.allowIssueCacheMinutes,
64
- );
60
+ const { issues } = await this.issueRepository.getAllIssues(projectId);
65
61
 
66
62
  const preparationIssues = issues.filter(
67
63
  (issue) => issue.status === PREPARATION_STATUS_NAME,
@@ -103,6 +103,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
103
103
  const project = buildProject(buildCanonicalStatuses());
104
104
  mockProjectRepository.getByUrl.mockResolvedValue(project);
105
105
  mockIssueRepository.getAllIssues.mockResolvedValue({
106
+ project: mock<Project>(),
106
107
  issues: [],
107
108
  cacheUsed: false,
108
109
  });
@@ -133,6 +134,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
133
134
  const project = buildProject(statuses);
134
135
  mockProjectRepository.getByUrl.mockResolvedValue(project);
135
136
  mockIssueRepository.getAllIssues.mockResolvedValue({
137
+ project: mock<Project>(),
136
138
  issues: [],
137
139
  cacheUsed: false,
138
140
  });
@@ -157,6 +159,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
157
159
  mockProjectRepository.getByUrl.mockResolvedValue(project);
158
160
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
159
161
  mockIssueRepository.getAllIssues.mockResolvedValue({
162
+ project: mock<Project>(),
160
163
  issues: [],
161
164
  cacheUsed: false,
162
165
  });
@@ -199,6 +202,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
199
202
  mockProjectRepository.getByUrl.mockResolvedValue(project);
200
203
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
201
204
  mockIssueRepository.getAllIssues.mockResolvedValue({
205
+ project: mock<Project>(),
202
206
  issues: [],
203
207
  cacheUsed: false,
204
208
  });
@@ -300,6 +304,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
300
304
  mockProjectRepository.getByUrl.mockResolvedValue(project);
301
305
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
302
306
  mockIssueRepository.getAllIssues.mockResolvedValue({
307
+ project: mock<Project>(),
303
308
  issues: [],
304
309
  cacheUsed: false,
305
310
  });
@@ -337,6 +342,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
337
342
  mockProjectRepository.getByUrl.mockResolvedValue(project);
338
343
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
339
344
  mockIssueRepository.getAllIssues.mockResolvedValue({
345
+ project: mock<Project>(),
340
346
  issues: [],
341
347
  cacheUsed: false,
342
348
  });
@@ -372,6 +378,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
372
378
  mockProjectRepository.getByUrl.mockResolvedValue(project);
373
379
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
374
380
  mockIssueRepository.getAllIssues.mockResolvedValue({
381
+ project: mock<Project>(),
375
382
  issues: [],
376
383
  cacheUsed: false,
377
384
  });
@@ -410,6 +417,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
410
417
  mockProjectRepository.getByUrl.mockResolvedValue(project);
411
418
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
412
419
  mockIssueRepository.getAllIssues.mockResolvedValue({
420
+ project: mock<Project>(),
413
421
  issues: [],
414
422
  cacheUsed: false,
415
423
  });
@@ -442,6 +450,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
442
450
  mockProjectRepository.getByUrl.mockResolvedValue(project);
443
451
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
444
452
  mockIssueRepository.getAllIssues.mockResolvedValue({
453
+ project: mock<Project>(),
445
454
  issues: [],
446
455
  cacheUsed: false,
447
456
  });
@@ -484,6 +493,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
484
493
  mockProjectRepository.getByUrl.mockResolvedValue(project);
485
494
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
486
495
  mockIssueRepository.getAllIssues.mockResolvedValue({
496
+ project: mock<Project>(),
487
497
  issues: [],
488
498
  cacheUsed: false,
489
499
  });
@@ -524,6 +534,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
524
534
  mockProjectRepository.getByUrl.mockResolvedValue(project);
525
535
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
526
536
  mockIssueRepository.getAllIssues.mockResolvedValue({
537
+ project: mock<Project>(),
527
538
  issues: [],
528
539
  cacheUsed: false,
529
540
  });
@@ -595,6 +606,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
595
606
  mockProjectRepository.getByUrl.mockResolvedValue(project);
596
607
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
597
608
  mockIssueRepository.getAllIssues.mockResolvedValue({
609
+ project: mock<Project>(),
598
610
  issues: [],
599
611
  cacheUsed: false,
600
612
  });
@@ -713,6 +725,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
713
725
  status: AWAITING_WORKSPACE_STATUS_NAME,
714
726
  });
715
727
  mockIssueRepository.getAllIssues.mockResolvedValue({
728
+ project: mock<Project>(),
716
729
  issues: [atbIssue1, atbIssue2, otherIssue],
717
730
  cacheUsed: false,
718
731
  });
@@ -724,10 +737,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
724
737
  );
725
738
  await useCase.run({ projectUrl: project.url });
726
739
 
727
- expect(mockIssueRepository.getAllIssues).toHaveBeenCalledWith(
728
- project.id,
729
- 0,
730
- );
740
+ expect(mockIssueRepository.getAllIssues).toHaveBeenCalledWith(project.id);
731
741
  expect(mockIssueRepository.updateStatus).toHaveBeenCalledTimes(2);
732
742
  expect(mockIssueRepository.updateStatus).toHaveBeenCalledWith(
733
743
  project,
@@ -769,6 +779,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
769
779
  const project = buildProject(buildCanonicalStatuses());
770
780
  mockProjectRepository.getByUrl.mockResolvedValue(project);
771
781
  mockIssueRepository.getAllIssues.mockResolvedValue({
782
+ project: mock<Project>(),
772
783
  issues: [],
773
784
  cacheUsed: false,
774
785
  });
@@ -801,6 +812,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
801
812
  mockProjectRepository.getByUrl.mockResolvedValue(project);
802
813
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
803
814
  mockIssueRepository.getAllIssues.mockResolvedValue({
815
+ project: mock<Project>(),
804
816
  issues: [],
805
817
  cacheUsed: false,
806
818
  });
@@ -883,6 +895,7 @@ describe('SetupTowerDefenceProjectUseCase', () => {
883
895
  mockProjectRepository.getByUrl.mockResolvedValue(project);
884
896
  mockProjectRepository.updateStatusList.mockResolvedValue([]);
885
897
  mockIssueRepository.getAllIssues.mockResolvedValue({
898
+ project: mock<Project>(),
886
899
  issues: [],
887
900
  cacheUsed: false,
888
901
  });
@@ -48,10 +48,7 @@ export class SetupTowerDefenceProjectUseCase {
48
48
  if (awaitingTaskBreakdownStatus) {
49
49
  const todoStatus = existing.find((s) => s.name === TODO_STATUS_NAME);
50
50
  if (todoStatus) {
51
- const { issues } = await this.issueRepository.getAllIssues(
52
- project.id,
53
- 0,
54
- );
51
+ const { issues } = await this.issueRepository.getAllIssues(project.id);
55
52
  const awaitingTaskBreakdownIssues = issues.filter(
56
53
  (issue) =>
57
54
  issue.status === LEGACY_AWAITING_TASK_BREAKDOWN_STATUS_NAME,
@@ -72,17 +72,14 @@ describe('StaleTmuxSessionKillUseCase', () => {
72
72
  let mockProject: Project;
73
73
  const now = new Date('2026-06-26T00:00:00Z');
74
74
  const nowEpochSeconds = Math.floor(now.getTime() / 1000);
75
- const allowCacheMinutes = 10;
76
75
 
77
76
  const runParams = (): {
78
77
  project: Project;
79
- allowCacheMinutes: number;
80
78
  excludedStatus: string;
81
79
  idleThresholdSeconds: number;
82
80
  now: Date;
83
81
  } => ({
84
82
  project: mockProject,
85
- allowCacheMinutes,
86
83
  excludedStatus: DEFAULT_EXCLUDED_STATUS,
87
84
  idleThresholdSeconds: DEFAULT_IDLE_THRESHOLD_SECONDS,
88
85
  now,
@@ -123,10 +120,7 @@ describe('StaleTmuxSessionKillUseCase', () => {
123
120
  expect(
124
121
  mockTmuxSessionRepository.listLiveSessionsWithActivity,
125
122
  ).toHaveBeenCalledTimes(1);
126
- expect(mockIssueRepository.getAllOpened).toHaveBeenCalledWith(
127
- mockProject,
128
- allowCacheMinutes,
129
- );
123
+ expect(mockIssueRepository.getAllOpened).toHaveBeenCalledWith(mockProject);
130
124
  });
131
125
 
132
126
  it('kills a session mapping to an open issue whose status is not the excluded status', async () => {
@@ -25,17 +25,13 @@ export class StaleTmuxSessionKillUseCase {
25
25
 
26
26
  run = async (params: {
27
27
  project: Project;
28
- allowCacheMinutes: number;
29
28
  excludedStatus: string;
30
29
  idleThresholdSeconds: number;
31
30
  now: Date;
32
31
  }): Promise<void> => {
33
32
  const liveSessions =
34
33
  await this.tmuxSessionRepository.listLiveSessionsWithActivity();
35
- const openIssues = await this.issueRepository.getAllOpened(
36
- params.project,
37
- params.allowCacheMinutes,
38
- );
34
+ const openIssues = await this.issueRepository.getAllOpened(params.project);
39
35
  const issueBySessionName = new Map<string, Issue>();
40
36
  for (const issue of openIssues) {
41
37
  issueBySessionName.set(toTmuxSessionName(issue.url), issue);