github-issue-tower-defence-management 1.46.0 → 1.48.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 (99) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +70 -25
  3. package/bin/adapter/entry-points/cli/index.js +2 -104
  4. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  5. package/bin/adapter/entry-points/cli/projectConfig.js +0 -15
  6. package/bin/adapter/entry-points/cli/projectConfig.js.map +1 -1
  7. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +28 -62
  8. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  9. package/bin/adapter/entry-points/handlers/situationFileWriter.js +98 -0
  10. package/bin/adapter/entry-points/handlers/situationFileWriter.js.map +1 -0
  11. package/bin/adapter/repositories/GraphqlProjectRepository.js +37 -0
  12. package/bin/adapter/repositories/GraphqlProjectRepository.js.map +1 -1
  13. package/bin/domain/entities/WorkflowStatus.js +36 -0
  14. package/bin/domain/entities/WorkflowStatus.js.map +1 -0
  15. package/bin/domain/usecases/AnalyzeStoriesUseCase.js +2 -1
  16. package/bin/domain/usecases/AnalyzeStoriesUseCase.js.map +1 -1
  17. package/bin/domain/usecases/ChangeStatusByStoryColorUseCase.js +4 -3
  18. package/bin/domain/usecases/ChangeStatusByStoryColorUseCase.js.map +1 -1
  19. package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js +2 -1
  20. package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js.map +1 -1
  21. package/bin/domain/usecases/CreateEstimationIssueUseCase.js +2 -1
  22. package/bin/domain/usecases/CreateEstimationIssueUseCase.js.map +1 -1
  23. package/bin/domain/usecases/CreateNewStoryByLabelUseCase.js.map +1 -1
  24. package/bin/domain/usecases/HandleScheduledEventUseCase.js +9 -17
  25. package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -1
  26. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +13 -15
  27. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
  28. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js +4 -5
  29. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js.map +1 -1
  30. package/bin/domain/usecases/SetupTowerDefenceProjectUseCase.js +47 -0
  31. package/bin/domain/usecases/SetupTowerDefenceProjectUseCase.js.map +1 -0
  32. package/bin/domain/usecases/StartPreparationUseCase.js +7 -8
  33. package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -1
  34. package/bin/domain/usecases/UpdateIssueStatusByLabelUseCase.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/adapter/entry-points/cli/index.test.ts +8 -258
  37. package/src/adapter/entry-points/cli/index.ts +6 -106
  38. package/src/adapter/entry-points/cli/projectConfig.ts +0 -33
  39. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.test.ts +24 -58
  40. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +36 -41
  41. package/src/adapter/entry-points/handlers/situationFileWriter.test.ts +417 -0
  42. package/src/adapter/entry-points/handlers/situationFileWriter.ts +168 -0
  43. package/src/adapter/repositories/GraphqlProjectRepository.ts +55 -1
  44. package/src/domain/entities/WorkflowStatus.ts +41 -0
  45. package/src/domain/usecases/AnalyzeStoriesUseCase.ts +2 -2
  46. package/src/domain/usecases/ChangeStatusByStoryColorUseCase.test.ts +5 -10
  47. package/src/domain/usecases/ChangeStatusByStoryColorUseCase.ts +4 -4
  48. package/src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.test.ts +0 -11
  49. package/src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.ts +2 -2
  50. package/src/domain/usecases/CreateEstimationIssueUseCase.ts +2 -2
  51. package/src/domain/usecases/CreateNewStoryByLabelUseCase.test.ts +0 -4
  52. package/src/domain/usecases/CreateNewStoryByLabelUseCase.ts +0 -1
  53. package/src/domain/usecases/HandleScheduledEventUseCase.test.ts +4 -41
  54. package/src/domain/usecases/HandleScheduledEventUseCase.ts +9 -27
  55. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.test.ts +0 -202
  56. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +18 -31
  57. package/src/domain/usecases/RevertOrphanedPreparationUseCase.test.ts +13 -101
  58. package/src/domain/usecases/RevertOrphanedPreparationUseCase.ts +10 -10
  59. package/src/domain/usecases/SetupTowerDefenceProjectUseCase.test.ts +187 -0
  60. package/src/domain/usecases/SetupTowerDefenceProjectUseCase.ts +69 -0
  61. package/src/domain/usecases/StartPreparationUseCase.test.ts +1 -151
  62. package/src/domain/usecases/StartPreparationUseCase.ts +11 -20
  63. package/src/domain/usecases/UpdateIssueStatusByLabelUseCase.test.ts +2 -47
  64. package/src/domain/usecases/UpdateIssueStatusByLabelUseCase.ts +1 -5
  65. package/src/domain/usecases/adapter-interfaces/ProjectRepository.ts +6 -1
  66. package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
  67. package/types/adapter/entry-points/cli/projectConfig.d.ts +0 -3
  68. package/types/adapter/entry-points/cli/projectConfig.d.ts.map +1 -1
  69. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
  70. package/types/adapter/entry-points/handlers/situationFileWriter.d.ts +30 -0
  71. package/types/adapter/entry-points/handlers/situationFileWriter.d.ts.map +1 -0
  72. package/types/adapter/repositories/GraphqlProjectRepository.d.ts +4 -1
  73. package/types/adapter/repositories/GraphqlProjectRepository.d.ts.map +1 -1
  74. package/types/domain/entities/WorkflowStatus.d.ts +13 -0
  75. package/types/domain/entities/WorkflowStatus.d.ts.map +1 -0
  76. package/types/domain/usecases/AnalyzeStoriesUseCase.d.ts +0 -1
  77. package/types/domain/usecases/AnalyzeStoriesUseCase.d.ts.map +1 -1
  78. package/types/domain/usecases/ChangeStatusByStoryColorUseCase.d.ts +0 -1
  79. package/types/domain/usecases/ChangeStatusByStoryColorUseCase.d.ts.map +1 -1
  80. package/types/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.d.ts +0 -1
  81. package/types/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.d.ts.map +1 -1
  82. package/types/domain/usecases/CreateEstimationIssueUseCase.d.ts +0 -1
  83. package/types/domain/usecases/CreateEstimationIssueUseCase.d.ts.map +1 -1
  84. package/types/domain/usecases/CreateNewStoryByLabelUseCase.d.ts +0 -1
  85. package/types/domain/usecases/CreateNewStoryByLabelUseCase.d.ts.map +1 -1
  86. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts +3 -8
  87. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -1
  88. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts +1 -4
  89. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
  90. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts +0 -3
  91. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts.map +1 -1
  92. package/types/domain/usecases/SetupTowerDefenceProjectUseCase.d.ts +10 -0
  93. package/types/domain/usecases/SetupTowerDefenceProjectUseCase.d.ts.map +1 -0
  94. package/types/domain/usecases/StartPreparationUseCase.d.ts +1 -3
  95. package/types/domain/usecases/StartPreparationUseCase.d.ts.map +1 -1
  96. package/types/domain/usecases/UpdateIssueStatusByLabelUseCase.d.ts +0 -1
  97. package/types/domain/usecases/UpdateIssueStatusByLabelUseCase.d.ts.map +1 -1
  98. package/types/domain/usecases/adapter-interfaces/ProjectRepository.d.ts +3 -1
  99. package/types/domain/usecases/adapter-interfaces/ProjectRepository.d.ts.map +1 -1
@@ -66,10 +66,7 @@ describe('CLI', () => {
66
66
 
67
67
  const defaultConfig = {
68
68
  projectUrl: 'https://github.com/orgs/test/projects/1',
69
- awaitingWorkspaceStatus: 'Awaiting',
70
- preparationStatus: 'Preparing',
71
69
  defaultAgentName: 'agent1',
72
- awaitingQualityCheckStatus: 'Awaiting QC',
73
70
  projectName: 'test-project',
74
71
  };
75
72
 
@@ -128,8 +125,6 @@ describe('CLI', () => {
128
125
  it('should load config from YAML file', () => {
129
126
  const config = {
130
127
  projectUrl: 'https://github.com/orgs/test/projects/1',
131
- awaitingWorkspaceStatus: 'Awaiting',
132
- preparationStatus: 'Preparing',
133
128
  defaultAgentName: 'agent1',
134
129
  defaultLlmModelName: 'claude-opus-4-5',
135
130
  defaultLlmAgentName: 'aw',
@@ -137,7 +132,6 @@ describe('CLI', () => {
137
132
  allowIssueCacheMinutes: 5,
138
133
  utilizationPercentageThreshold: 80,
139
134
  allowedIssueAuthors: 'user1,user2',
140
- awaitingQualityCheckStatus: 'Awaiting QC',
141
135
  thresholdForAutoReject: 5,
142
136
  workflowBlockerResolvedWebhookUrl: 'https://example.com/webhook',
143
137
  projectName: 'test-project',
@@ -197,14 +191,14 @@ describe('CLI', () => {
197
191
  it('should ignore non-string values for string fields', () => {
198
192
  const config = {
199
193
  projectUrl: 123,
200
- awaitingWorkspaceStatus: true,
194
+ defaultAgentName: true,
201
195
  };
202
196
  writeConfig(config);
203
197
 
204
198
  const result = loadConfigFile(configFilePath);
205
199
 
206
200
  expect(result.projectUrl).toBeUndefined();
207
- expect(result.awaitingWorkspaceStatus).toBeUndefined();
201
+ expect(result.defaultAgentName).toBeUndefined();
208
202
  });
209
203
 
210
204
  it('should ignore non-number values for number fields', () => {
@@ -263,16 +257,14 @@ describe('CLI', () => {
263
257
  Some description
264
258
  <details>
265
259
  <summary>config</summary>
266
- awaitingWorkspaceStatus: 'Custom Awaiting'
267
- preparationStatus: 'Custom Preparing'
268
260
  defaultAgentName: 'readme-agent'
261
+ defaultLlmModelName: 'claude-opus-4-5'
269
262
  </details>`;
270
263
 
271
264
  const result = parseProjectReadmeConfig(readme);
272
265
 
273
- expect(result.awaitingWorkspaceStatus).toBe('Custom Awaiting');
274
- expect(result.preparationStatus).toBe('Custom Preparing');
275
266
  expect(result.defaultAgentName).toBe('readme-agent');
267
+ expect(result.defaultLlmModelName).toBe('claude-opus-4-5');
276
268
  });
277
269
 
278
270
  it('should return empty config when no details/summary section exists', () => {
@@ -506,8 +498,6 @@ codexHomeCandidates:
506
498
  expect(mockRun).toHaveBeenCalledTimes(1);
507
499
  expect(mockRun).toHaveBeenCalledWith({
508
500
  projectUrl: 'https://github.com/orgs/test/projects/1',
509
- awaitingWorkspaceStatus: 'Awaiting',
510
- preparationStatus: 'Preparing',
511
501
  defaultAgentName: 'agent1',
512
502
  defaultLlmModelName: null,
513
503
  defaultLlmAgentName: null,
@@ -548,8 +538,6 @@ codexHomeCandidates:
548
538
  expect(mockRun).toHaveBeenCalledTimes(1);
549
539
  expect(mockRun).toHaveBeenCalledWith({
550
540
  projectUrl: 'https://github.com/orgs/override/projects/2',
551
- awaitingWorkspaceStatus: 'Awaiting',
552
- preparationStatus: 'Preparing',
553
541
  defaultAgentName: 'override-agent',
554
542
  defaultLlmModelName: null,
555
543
  defaultLlmAgentName: null,
@@ -750,8 +738,6 @@ codexHomeCandidates:
750
738
 
751
739
  it('should exit with error when projectUrl is missing from both CLI and config', async () => {
752
740
  const configWithoutProjectUrl = {
753
- awaitingWorkspaceStatus: 'Awaiting',
754
- preparationStatus: 'Preparing',
755
741
  defaultAgentName: 'agent1',
756
742
  };
757
743
  writeConfig(configWithoutProjectUrl);
@@ -782,79 +768,9 @@ codexHomeCandidates:
782
768
  processExitSpy.mockRestore();
783
769
  });
784
770
 
785
- it('should exit with error when awaitingWorkspaceStatus is missing', async () => {
786
- const configMissing = {
787
- projectUrl: 'https://github.com/orgs/test/projects/1',
788
- preparationStatus: 'Preparing',
789
- defaultAgentName: 'agent1',
790
- };
791
- writeConfig(configMissing);
792
-
793
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
794
- const processExitSpy = jest
795
- .spyOn(process, 'exit')
796
- .mockImplementation(() => {
797
- throw new Error('process.exit called');
798
- });
799
-
800
- await expect(
801
- program.parseAsync([
802
- 'node',
803
- 'test',
804
- 'startDaemon',
805
- '--configFilePath',
806
- configFilePath,
807
- ]),
808
- ).rejects.toThrow('process.exit called');
809
-
810
- expect(consoleErrorSpy).toHaveBeenCalledWith(
811
- 'awaitingWorkspaceStatus is required. Provide via --awaitingWorkspaceStatus, config file, or project README.',
812
- );
813
- expect(processExitSpy).toHaveBeenCalledWith(1);
814
-
815
- consoleErrorSpy.mockRestore();
816
- processExitSpy.mockRestore();
817
- });
818
-
819
- it('should exit with error when preparationStatus is missing', async () => {
820
- const configMissing = {
821
- projectUrl: 'https://github.com/orgs/test/projects/1',
822
- awaitingWorkspaceStatus: 'Awaiting',
823
- defaultAgentName: 'agent1',
824
- };
825
- writeConfig(configMissing);
826
-
827
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
828
- const processExitSpy = jest
829
- .spyOn(process, 'exit')
830
- .mockImplementation(() => {
831
- throw new Error('process.exit called');
832
- });
833
-
834
- await expect(
835
- program.parseAsync([
836
- 'node',
837
- 'test',
838
- 'startDaemon',
839
- '--configFilePath',
840
- configFilePath,
841
- ]),
842
- ).rejects.toThrow('process.exit called');
843
-
844
- expect(consoleErrorSpy).toHaveBeenCalledWith(
845
- 'preparationStatus is required. Provide via --preparationStatus, config file, or project README.',
846
- );
847
- expect(processExitSpy).toHaveBeenCalledWith(1);
848
-
849
- consoleErrorSpy.mockRestore();
850
- processExitSpy.mockRestore();
851
- });
852
-
853
771
  it('should exit with error when defaultAgentName is missing', async () => {
854
772
  const configMissing = {
855
773
  projectUrl: 'https://github.com/orgs/test/projects/1',
856
- awaitingWorkspaceStatus: 'Awaiting',
857
- preparationStatus: 'Preparing',
858
774
  };
859
775
  writeConfig(configMissing);
860
776
 
@@ -1068,52 +984,6 @@ codexHomeCandidates:
1068
984
  }),
1069
985
  );
1070
986
  });
1071
-
1072
- it('should write runtimeConfig-{projectId}.json atomically after useCase run', async () => {
1073
- const configWithNumericValues = {
1074
- ...defaultConfig,
1075
- maximumPreparingIssuesCount: 10,
1076
- utilizationPercentageThreshold: 97,
1077
- allowIssueCacheMinutes: 5,
1078
- thresholdForAutoReject: 30,
1079
- };
1080
- writeConfig(configWithNumericValues);
1081
-
1082
- const mockRun = jest.fn().mockResolvedValue(undefined);
1083
- const MockedStartPreparationUseCase = jest.mocked(
1084
- StartPreparationUseCase,
1085
- );
1086
- MockedStartPreparationUseCase.mockImplementation(function (
1087
- this: StartPreparationUseCase,
1088
- ) {
1089
- this.run = mockRun;
1090
- return this;
1091
- });
1092
-
1093
- await program.parseAsync([
1094
- 'node',
1095
- 'test',
1096
- 'startDaemon',
1097
- '--configFilePath',
1098
- configFilePath,
1099
- ]);
1100
-
1101
- const cacheDir = path.join(process.cwd(), 'tmp/cache/test-project');
1102
- const runtimeConfigPath = path.join(
1103
- cacheDir,
1104
- 'runtimeConfig-PVT_kwHOtest456.json',
1105
- );
1106
- expect(fs.existsSync(runtimeConfigPath)).toBe(true);
1107
- const written: unknown = JSON.parse(
1108
- fs.readFileSync(runtimeConfigPath, 'utf-8'),
1109
- );
1110
- expect(written).toMatchObject({
1111
- maximumPreparingIssuesCount: 10,
1112
- utilizationPercentageThreshold: 97,
1113
- allowIssueCacheMinutes: 5,
1114
- thresholdForAutoReject: 30,
1115
- });
1116
- });
1117
987
  });
1118
988
 
1119
989
  describe('notifyFinishedIssuePreparation', () => {
@@ -1144,9 +1014,6 @@ codexHomeCandidates:
1144
1014
  expect(mockRun).toHaveBeenCalledWith({
1145
1015
  projectUrl: 'https://github.com/orgs/test/projects/1',
1146
1016
  issueUrl: 'https://github.com/test/repo/issues/1',
1147
- preparationStatus: 'Preparing',
1148
- awaitingWorkspaceStatus: 'Awaiting',
1149
- awaitingQualityCheckStatus: 'Awaiting QC',
1150
1017
  thresholdForAutoReject: 3,
1151
1018
  workflowBlockerResolvedWebhookUrl: null,
1152
1019
  });
@@ -1175,16 +1042,11 @@ codexHomeCandidates:
1175
1042
  'https://github.com/test/repo/issues/1',
1176
1043
  '--projectUrl',
1177
1044
  'https://github.com/orgs/override/projects/2',
1178
- '--awaitingQualityCheckStatus',
1179
- 'Override QC',
1180
1045
  ]);
1181
1046
 
1182
1047
  expect(mockRun).toHaveBeenCalledWith({
1183
1048
  projectUrl: 'https://github.com/orgs/override/projects/2',
1184
1049
  issueUrl: 'https://github.com/test/repo/issues/1',
1185
- preparationStatus: 'Preparing',
1186
- awaitingWorkspaceStatus: 'Awaiting',
1187
- awaitingQualityCheckStatus: 'Override QC',
1188
1050
  thresholdForAutoReject: 3,
1189
1051
  workflowBlockerResolvedWebhookUrl: null,
1190
1052
  });
@@ -1320,11 +1182,7 @@ codexHomeCandidates:
1320
1182
  });
1321
1183
 
1322
1184
  it('should exit with error when projectUrl is missing', async () => {
1323
- const configMissing = {
1324
- preparationStatus: 'Preparing',
1325
- awaitingWorkspaceStatus: 'Awaiting',
1326
- awaitingQualityCheckStatus: 'Awaiting QC',
1327
- };
1185
+ const configMissing = {};
1328
1186
  writeConfig(configMissing);
1329
1187
 
1330
1188
  const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
@@ -1355,114 +1213,6 @@ codexHomeCandidates:
1355
1213
  processExitSpy.mockRestore();
1356
1214
  });
1357
1215
 
1358
- it('should exit with error when preparationStatus is missing', async () => {
1359
- const configMissing = {
1360
- projectUrl: 'https://github.com/orgs/test/projects/1',
1361
- awaitingWorkspaceStatus: 'Awaiting',
1362
- awaitingQualityCheckStatus: 'Awaiting QC',
1363
- };
1364
- writeConfig(configMissing);
1365
-
1366
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
1367
- const processExitSpy = jest
1368
- .spyOn(process, 'exit')
1369
- .mockImplementation(() => {
1370
- throw new Error('process.exit called');
1371
- });
1372
-
1373
- await expect(
1374
- program.parseAsync([
1375
- 'node',
1376
- 'test',
1377
- 'notifyFinishedIssuePreparation',
1378
- '--configFilePath',
1379
- configFilePath,
1380
- '--issueUrl',
1381
- 'https://github.com/test/repo/issues/1',
1382
- ]),
1383
- ).rejects.toThrow('process.exit called');
1384
-
1385
- expect(consoleErrorSpy).toHaveBeenCalledWith(
1386
- 'preparationStatus is required. Provide via --preparationStatus, config file, or project README.',
1387
- );
1388
- expect(processExitSpy).toHaveBeenCalledWith(1);
1389
-
1390
- consoleErrorSpy.mockRestore();
1391
- processExitSpy.mockRestore();
1392
- });
1393
-
1394
- it('should exit with error when awaitingWorkspaceStatus is missing', async () => {
1395
- const configMissing = {
1396
- projectUrl: 'https://github.com/orgs/test/projects/1',
1397
- preparationStatus: 'Preparing',
1398
- awaitingQualityCheckStatus: 'Awaiting QC',
1399
- };
1400
- writeConfig(configMissing);
1401
-
1402
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
1403
- const processExitSpy = jest
1404
- .spyOn(process, 'exit')
1405
- .mockImplementation(() => {
1406
- throw new Error('process.exit called');
1407
- });
1408
-
1409
- await expect(
1410
- program.parseAsync([
1411
- 'node',
1412
- 'test',
1413
- 'notifyFinishedIssuePreparation',
1414
- '--configFilePath',
1415
- configFilePath,
1416
- '--issueUrl',
1417
- 'https://github.com/test/repo/issues/1',
1418
- ]),
1419
- ).rejects.toThrow('process.exit called');
1420
-
1421
- expect(consoleErrorSpy).toHaveBeenCalledWith(
1422
- 'awaitingWorkspaceStatus is required. Provide via --awaitingWorkspaceStatus, config file, or project README.',
1423
- );
1424
- expect(processExitSpy).toHaveBeenCalledWith(1);
1425
-
1426
- consoleErrorSpy.mockRestore();
1427
- processExitSpy.mockRestore();
1428
- });
1429
-
1430
- it('should exit with error when awaitingQualityCheckStatus is missing', async () => {
1431
- const configMissing = {
1432
- projectUrl: 'https://github.com/orgs/test/projects/1',
1433
- preparationStatus: 'Preparing',
1434
- awaitingWorkspaceStatus: 'Awaiting',
1435
- };
1436
- writeConfig(configMissing);
1437
-
1438
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
1439
- const processExitSpy = jest
1440
- .spyOn(process, 'exit')
1441
- .mockImplementation(() => {
1442
- throw new Error('process.exit called');
1443
- });
1444
-
1445
- await expect(
1446
- program.parseAsync([
1447
- 'node',
1448
- 'test',
1449
- 'notifyFinishedIssuePreparation',
1450
- '--configFilePath',
1451
- configFilePath,
1452
- '--issueUrl',
1453
- 'https://github.com/test/repo/issues/1',
1454
- ]),
1455
- ).rejects.toThrow('process.exit called');
1456
-
1457
- expect(consoleErrorSpy).toHaveBeenCalledWith(
1458
- 'awaitingQualityCheckStatus is required. Provide via --awaitingQualityCheckStatus, config file, or project README.',
1459
- );
1460
- expect(processExitSpy).toHaveBeenCalledWith(1);
1461
-
1462
- consoleErrorSpy.mockRestore();
1463
- processExitSpy.mockRestore();
1464
- });
1465
-
1466
1216
  it('should pass workflowBlockerResolvedWebhookUrl from config file', async () => {
1467
1217
  const configWithWebhook = {
1468
1218
  ...defaultConfig,
@@ -1501,12 +1251,12 @@ codexHomeCandidates:
1501
1251
  );
1502
1252
  });
1503
1253
 
1504
- it('should apply README config overrides', async () => {
1254
+ it('should apply README config overrides for thresholdForAutoReject', async () => {
1505
1255
  const readmeContent = [
1506
1256
  '# Project',
1507
1257
  '<details>',
1508
1258
  '<summary>config</summary>',
1509
- "awaitingQualityCheckStatus: 'README QC'",
1259
+ 'thresholdForAutoReject: 9',
1510
1260
  '</details>',
1511
1261
  ].join('\n');
1512
1262
  mockFetchReturningReadme(readmeContent);
@@ -1535,7 +1285,7 @@ codexHomeCandidates:
1535
1285
 
1536
1286
  expect(mockRun).toHaveBeenCalledWith(
1537
1287
  expect.objectContaining({
1538
- awaitingQualityCheckStatus: 'README QC',
1288
+ thresholdForAutoReject: 9,
1539
1289
  }),
1540
1290
  );
1541
1291
  });
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import * as fs from 'fs';
3
2
  import { Command } from 'commander';
4
3
  import { HandleScheduledEventUseCaseHandler } from '../handlers/HandleScheduledEventUseCaseHandler';
5
4
  export {
@@ -31,12 +30,9 @@ import { OauthAPIProxyClaudeRepository } from '../../repositories/OauthAPIProxyC
31
30
  import { GitHubIssueCommentRepository } from '../../repositories/GitHubIssueCommentRepository';
32
31
  import { FetchWebhookRepository } from '../../repositories/FetchWebhookRepository';
33
32
  import { RevertOrphanedPreparationUseCase } from '../../../domain/usecases/RevertOrphanedPreparationUseCase';
34
- import { Project } from '../../../domain/entities/Project';
35
33
 
36
34
  type StartDaemonOptions = {
37
35
  projectUrl?: string;
38
- awaitingWorkspaceStatus?: string;
39
- preparationStatus?: string;
40
36
  defaultAgentName?: string;
41
37
  defaultLlmModelName?: string;
42
38
  defaultLlmAgentName?: string;
@@ -51,9 +47,6 @@ type StartDaemonOptions = {
51
47
  type NotifyFinishedOptions = {
52
48
  issueUrl: string;
53
49
  projectUrl?: string;
54
- preparationStatus?: string;
55
- awaitingWorkspaceStatus?: string;
56
- awaitingQualityCheckStatus?: string;
57
50
  thresholdForAutoReject?: string;
58
51
  workflowBlockerResolvedWebhookUrl?: string;
59
52
  configFilePath: string;
@@ -115,11 +108,6 @@ program
115
108
  'Path to config file for tower defence management',
116
109
  )
117
110
  .option('--projectUrl <url>', 'GitHub project URL')
118
- .option(
119
- '--awaitingWorkspaceStatus <status>',
120
- 'Status for issues awaiting workspace',
121
- )
122
- .option('--preparationStatus <status>', 'Status for issues in preparation')
123
111
  .option('--defaultAgentName <name>', 'Default agent name')
124
112
  .option('--defaultLlmModelName <name>', 'Default LLM model name')
125
113
  .option('--defaultLlmAgentName <name>', 'Default LLM agent name')
@@ -154,8 +142,6 @@ program
154
142
 
155
143
  const cliOverrides: ConfigFile = {
156
144
  projectUrl: options.projectUrl,
157
- awaitingWorkspaceStatus: options.awaitingWorkspaceStatus,
158
- preparationStatus: options.preparationStatus,
159
145
  defaultAgentName: options.defaultAgentName,
160
146
  defaultLlmModelName: options.defaultLlmModelName,
161
147
  defaultLlmAgentName: options.defaultLlmAgentName,
@@ -190,8 +176,6 @@ program
190
176
  );
191
177
 
192
178
  const projectUrl = config.projectUrl;
193
- const awaitingWorkspaceStatus = config.awaitingWorkspaceStatus;
194
- const preparationStatus = config.preparationStatus;
195
179
  const defaultAgentName = config.defaultAgentName;
196
180
 
197
181
  if (!projectUrl) {
@@ -200,18 +184,6 @@ program
200
184
  );
201
185
  process.exit(1);
202
186
  }
203
- if (!awaitingWorkspaceStatus) {
204
- console.error(
205
- 'awaitingWorkspaceStatus is required. Provide via --awaitingWorkspaceStatus, config file, or project README.',
206
- );
207
- process.exit(1);
208
- }
209
- if (!preparationStatus) {
210
- console.error(
211
- 'preparationStatus is required. Provide via --preparationStatus, config file, or project README.',
212
- );
213
- process.exit(1);
214
- }
215
187
  if (!defaultAgentName) {
216
188
  console.error(
217
189
  'defaultAgentName is required. Provide via --defaultAgentName, config file, or project README.',
@@ -254,16 +226,9 @@ program
254
226
  cachePath,
255
227
  token,
256
228
  );
257
- const projectRepository = {
258
- ...new GraphqlProjectRepository(...githubRepositoryParams),
259
-
260
- prepareStatus: async (
261
- _name: string,
262
- project: Project,
263
- ): Promise<Project> => {
264
- return project;
265
- },
266
- };
229
+ const projectRepository = new GraphqlProjectRepository(
230
+ ...githubRepositoryParams,
231
+ );
267
232
  const apiV3IssueRepository = new ApiV3IssueRepository(
268
233
  ...githubRepositoryParams,
269
234
  );
@@ -297,9 +262,6 @@ program
297
262
  );
298
263
  await revertUseCase.run({
299
264
  projectUrl,
300
- preparationStatus,
301
- awaitingWorkspaceStatus,
302
- awaitingQualityCheckStatus: config.awaitingQualityCheckStatus,
303
265
  allowIssueCacheMinutes,
304
266
  preparationProcessCheckCommand,
305
267
  awLogDirectoryPath: config.awLogDirectoryPath,
@@ -329,8 +291,6 @@ program
329
291
 
330
292
  await useCase.run({
331
293
  projectUrl,
332
- awaitingWorkspaceStatus,
333
- preparationStatus,
334
294
  defaultAgentName,
335
295
  defaultLlmModelName: config.defaultLlmModelName ?? null,
336
296
  defaultLlmAgentName: config.defaultLlmAgentName ?? null,
@@ -342,23 +302,6 @@ program
342
302
  codexHomeCandidates,
343
303
  allowIssueCacheMinutes,
344
304
  });
345
-
346
- const projectId = await projectRepository.findProjectIdByUrl(projectUrl);
347
- if (projectId) {
348
- const runtimeConfig = {
349
- resolvedAt: new Date().toISOString(),
350
- maximumPreparingIssuesCount: maximumPreparingIssuesCount,
351
- utilizationPercentageThreshold:
352
- config.utilizationPercentageThreshold ?? 90,
353
- allowIssueCacheMinutes: allowIssueCacheMinutes,
354
- thresholdForAutoReject: config.thresholdForAutoReject ?? 3,
355
- };
356
- const finalPath = `${cachePath}/runtimeConfig-${projectId}.json`;
357
- const tmpPath = `${finalPath}.tmp`;
358
- fs.mkdirSync(cachePath, { recursive: true });
359
- fs.writeFileSync(tmpPath, JSON.stringify(runtimeConfig));
360
- fs.renameSync(tmpPath, finalPath);
361
- }
362
305
  });
363
306
 
364
307
  program
@@ -370,15 +313,6 @@ program
370
313
  )
371
314
  .requiredOption('--issueUrl <url>', 'GitHub issue URL')
372
315
  .option('--projectUrl <url>', 'GitHub project URL')
373
- .option('--preparationStatus <status>', 'Status for issues in preparation')
374
- .option(
375
- '--awaitingWorkspaceStatus <status>',
376
- 'Status for issues awaiting workspace',
377
- )
378
- .option(
379
- '--awaitingQualityCheckStatus <status>',
380
- 'Status for issues awaiting quality check',
381
- )
382
316
  .option(
383
317
  '--thresholdForAutoReject <count>',
384
318
  'Threshold for auto-escalation after consecutive rejections (default: 3)',
@@ -398,9 +332,6 @@ program
398
332
 
399
333
  const cliOverrides: ConfigFile = {
400
334
  projectUrl: options.projectUrl,
401
- preparationStatus: options.preparationStatus,
402
- awaitingWorkspaceStatus: options.awaitingWorkspaceStatus,
403
- awaitingQualityCheckStatus: options.awaitingQualityCheckStatus,
404
335
  thresholdForAutoReject: options.thresholdForAutoReject
405
336
  ? Number(options.thresholdForAutoReject)
406
337
  : undefined,
@@ -426,9 +357,6 @@ program
426
357
  );
427
358
 
428
359
  const projectUrl = config.projectUrl;
429
- const preparationStatus = config.preparationStatus;
430
- const awaitingWorkspaceStatus = config.awaitingWorkspaceStatus;
431
- const awaitingQualityCheckStatus = config.awaitingQualityCheckStatus;
432
360
 
433
361
  if (!projectUrl) {
434
362
  console.error(
@@ -436,24 +364,6 @@ program
436
364
  );
437
365
  process.exit(1);
438
366
  }
439
- if (!preparationStatus) {
440
- console.error(
441
- 'preparationStatus is required. Provide via --preparationStatus, config file, or project README.',
442
- );
443
- process.exit(1);
444
- }
445
- if (!awaitingWorkspaceStatus) {
446
- console.error(
447
- 'awaitingWorkspaceStatus is required. Provide via --awaitingWorkspaceStatus, config file, or project README.',
448
- );
449
- process.exit(1);
450
- }
451
- if (!awaitingQualityCheckStatus) {
452
- console.error(
453
- 'awaitingQualityCheckStatus is required. Provide via --awaitingQualityCheckStatus, config file, or project README.',
454
- );
455
- process.exit(1);
456
- }
457
367
 
458
368
  let thresholdForAutoReject = 3;
459
369
  const rawThreshold = config.thresholdForAutoReject;
@@ -487,16 +397,9 @@ program
487
397
  cachePath,
488
398
  token,
489
399
  );
490
- const projectRepository = {
491
- ...new GraphqlProjectRepository(...githubRepositoryParams),
492
-
493
- prepareStatus: async (
494
- _name: string,
495
- project: Project,
496
- ): Promise<Project> => {
497
- return project;
498
- },
499
- };
400
+ const projectRepository = new GraphqlProjectRepository(
401
+ ...githubRepositoryParams,
402
+ );
500
403
  const apiV3IssueRepository = new ApiV3IssueRepository(
501
404
  ...githubRepositoryParams,
502
405
  );
@@ -526,9 +429,6 @@ program
526
429
  await useCase.run({
527
430
  projectUrl,
528
431
  issueUrl: options.issueUrl,
529
- preparationStatus,
530
- awaitingWorkspaceStatus,
531
- awaitingQualityCheckStatus,
532
432
  thresholdForAutoReject,
533
433
  workflowBlockerResolvedWebhookUrl,
534
434
  });