github-issue-tower-defence-management 1.80.1 → 1.82.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 (67) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +5 -2
  3. package/bin/adapter/entry-points/cli/index.js +1 -0
  4. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  5. package/bin/adapter/entry-points/cli/projectConfig.js +20 -0
  6. package/bin/adapter/entry-points/cli/projectConfig.js.map +1 -1
  7. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +48 -20
  8. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  9. package/bin/adapter/proxy/RateLimitCache.js +32 -4
  10. package/bin/adapter/proxy/RateLimitCache.js.map +1 -1
  11. package/bin/adapter/proxy/proxyEntry.js +1 -1
  12. package/bin/adapter/proxy/proxyEntry.js.map +1 -1
  13. package/bin/adapter/repositories/ProxyClaudeTokenUsageRepository.js +3 -0
  14. package/bin/adapter/repositories/ProxyClaudeTokenUsageRepository.js.map +1 -1
  15. package/bin/domain/usecases/ChangeTargetPullRequestApprover.js +9 -5
  16. package/bin/domain/usecases/ChangeTargetPullRequestApprover.js.map +1 -1
  17. package/bin/domain/usecases/HandleScheduledEventUseCase.js +1 -0
  18. package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -1
  19. package/bin/domain/usecases/IssueRejectionEvaluator.js +1 -1
  20. package/bin/domain/usecases/IssueRejectionEvaluator.js.map +1 -1
  21. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +1 -1
  22. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
  23. package/bin/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.js +1 -1
  24. package/bin/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.js.map +1 -1
  25. package/bin/domain/usecases/StartPreparationUseCase.js +8 -0
  26. package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/adapter/entry-points/cli/index.test.ts +18 -0
  29. package/src/adapter/entry-points/cli/index.ts +1 -0
  30. package/src/adapter/entry-points/cli/projectConfig.ts +32 -0
  31. package/src/adapter/entry-points/handlers/rotationOrderFileWriter.test.ts +4 -0
  32. package/src/adapter/proxy/RateLimitCache.test.ts +103 -0
  33. package/src/adapter/proxy/RateLimitCache.ts +44 -2
  34. package/src/adapter/proxy/proxyEntry.test.ts +17 -0
  35. package/src/adapter/proxy/proxyEntry.ts +5 -1
  36. package/src/adapter/repositories/ProxyClaudeTokenUsageRepository.test.ts +14 -0
  37. package/src/adapter/repositories/ProxyClaudeTokenUsageRepository.ts +3 -0
  38. package/src/domain/entities/ClaudeTokenUsage.ts +1 -0
  39. package/src/domain/usecases/ChangeTargetPullRequestApprover.test.ts +78 -0
  40. package/src/domain/usecases/ChangeTargetPullRequestApprover.ts +14 -4
  41. package/src/domain/usecases/HandleScheduledEventUseCase.ts +2 -0
  42. package/src/domain/usecases/IssueRejectionEvaluator.test.ts +18 -0
  43. package/src/domain/usecases/IssueRejectionEvaluator.ts +1 -1
  44. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.test.ts +61 -0
  45. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +2 -0
  46. package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.test.ts +36 -0
  47. package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.ts +2 -0
  48. package/src/domain/usecases/StartPreparationUseCase.test.ts +190 -0
  49. package/src/domain/usecases/StartPreparationUseCase.ts +14 -0
  50. package/types/adapter/entry-points/cli/projectConfig.d.ts +1 -0
  51. package/types/adapter/entry-points/cli/projectConfig.d.ts.map +1 -1
  52. package/types/adapter/proxy/RateLimitCache.d.ts +4 -1
  53. package/types/adapter/proxy/RateLimitCache.d.ts.map +1 -1
  54. package/types/adapter/proxy/proxyEntry.d.ts.map +1 -1
  55. package/types/adapter/repositories/ProxyClaudeTokenUsageRepository.d.ts.map +1 -1
  56. package/types/domain/entities/ClaudeTokenUsage.d.ts +1 -0
  57. package/types/domain/entities/ClaudeTokenUsage.d.ts.map +1 -1
  58. package/types/domain/usecases/ChangeTargetPullRequestApprover.d.ts +1 -1
  59. package/types/domain/usecases/ChangeTargetPullRequestApprover.d.ts.map +1 -1
  60. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts +1 -0
  61. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -1
  62. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts +1 -0
  63. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
  64. package/types/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.d.ts +1 -0
  65. package/types/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.d.ts.map +1 -1
  66. package/types/domain/usecases/StartPreparationUseCase.d.ts +2 -0
  67. package/types/domain/usecases/StartPreparationUseCase.d.ts.map +1 -1
@@ -3013,5 +3013,66 @@ describe('NotifyFinishedIssuePreparationUseCase', () => {
3013
3013
  'https://github.com/user/repo/pull/1',
3014
3014
  );
3015
3015
  });
3016
+
3017
+ it('should normalize leading slashes in change-target label paths', async () => {
3018
+ setupApprovedPrScenario({ labels: ['change-target:/src/domain'] });
3019
+ mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([
3020
+ 'src/domain/entities/Foo.ts',
3021
+ ]);
3022
+
3023
+ await useCase.run({
3024
+ projectUrl: 'https://github.com/users/user/projects/1',
3025
+ issueUrl: 'https://github.com/user/repo/issues/1',
3026
+ thresholdForAutoReject: 3,
3027
+ workflowBlockerResolvedWebhookUrl: null,
3028
+ allowedIssueAuthors: null,
3029
+ });
3030
+
3031
+ expect(mockIssueRepository.approvePullRequest).toHaveBeenCalledWith(
3032
+ 'https://github.com/user/repo/pull/1',
3033
+ );
3034
+ });
3035
+
3036
+ it('should expand changeTargetPathAliases when alias matches a change-target label', async () => {
3037
+ setupApprovedPrScenario({ labels: ['change-target:adapters'] });
3038
+ mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([
3039
+ 'src/domain/usecases/adapter-interfaces/IssueRepository.ts',
3040
+ ]);
3041
+
3042
+ await useCase.run({
3043
+ projectUrl: 'https://github.com/users/user/projects/1',
3044
+ issueUrl: 'https://github.com/user/repo/issues/1',
3045
+ thresholdForAutoReject: 3,
3046
+ workflowBlockerResolvedWebhookUrl: null,
3047
+ allowedIssueAuthors: null,
3048
+ changeTargetPathAliases: {
3049
+ adapters: 'src/domain/usecases/adapter-interfaces',
3050
+ },
3051
+ });
3052
+
3053
+ expect(mockIssueRepository.approvePullRequest).toHaveBeenCalledWith(
3054
+ 'https://github.com/user/repo/pull/1',
3055
+ );
3056
+ });
3057
+
3058
+ it('should not approve when file is outside the alias-expanded path', async () => {
3059
+ setupApprovedPrScenario({ labels: ['change-target:adapters'] });
3060
+ mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([
3061
+ 'src/domain/usecases/SomeOtherUseCase.ts',
3062
+ ]);
3063
+
3064
+ await useCase.run({
3065
+ projectUrl: 'https://github.com/users/user/projects/1',
3066
+ issueUrl: 'https://github.com/user/repo/issues/1',
3067
+ thresholdForAutoReject: 3,
3068
+ workflowBlockerResolvedWebhookUrl: null,
3069
+ allowedIssueAuthors: null,
3070
+ changeTargetPathAliases: {
3071
+ adapters: 'src/domain/usecases/adapter-interfaces',
3072
+ },
3073
+ });
3074
+
3075
+ expect(mockIssueRepository.approvePullRequest).not.toHaveBeenCalled();
3076
+ });
3016
3077
  });
3017
3078
  });
@@ -78,6 +78,7 @@ export class NotifyFinishedIssuePreparationUseCase {
78
78
  workflowBlockerResolvedWebhookUrl: string | null;
79
79
  allowedIssueAuthors?: string[] | null;
80
80
  labelsAsLlmAgentName?: string[] | null;
81
+ changeTargetPathAliases?: Record<string, string> | null;
81
82
  }): Promise<void> => {
82
83
  const project = await this.projectRepository.getByUrl(params.projectUrl);
83
84
 
@@ -238,6 +239,7 @@ export class NotifyFinishedIssuePreparationUseCase {
238
239
  await this.changeTargetPullRequestApprover.approveIfConfined(
239
240
  issue.labels,
240
241
  approvedPrUrl,
242
+ params.changeTargetPathAliases,
241
243
  );
242
244
  issue.status = AWAITING_QUALITY_CHECK_STATUS_NAME;
243
245
  await this.issueRepository.update(issue, project);
@@ -762,6 +762,42 @@ describe('RevertNotReadyReviewQueueIssueUseCase', () => {
762
762
  'https://github.com/user/repo/pull/1',
763
763
  );
764
764
  });
765
+
766
+ it('should expand changeTargetPathAliases when alias matches a change-target label', async () => {
767
+ setupReadyIssue(['change-target:adapters']);
768
+ mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([
769
+ 'src/domain/usecases/adapter-interfaces/IssueRepository.ts',
770
+ ]);
771
+
772
+ await useCase.run({
773
+ projectUrl: 'https://github.com/users/user/projects/1',
774
+ allowIssueCacheMinutes: 10,
775
+ changeTargetPathAliases: {
776
+ adapters: 'src/domain/usecases/adapter-interfaces',
777
+ },
778
+ });
779
+
780
+ expect(mockIssueRepository.approvePullRequest).toHaveBeenCalledWith(
781
+ 'https://github.com/user/repo/pull/1',
782
+ );
783
+ });
784
+
785
+ it('should not approve when file is outside the alias-expanded path', async () => {
786
+ setupReadyIssue(['change-target:adapters']);
787
+ mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([
788
+ 'src/domain/usecases/SomeOtherUseCase.ts',
789
+ ]);
790
+
791
+ await useCase.run({
792
+ projectUrl: 'https://github.com/users/user/projects/1',
793
+ allowIssueCacheMinutes: 10,
794
+ changeTargetPathAliases: {
795
+ adapters: 'src/domain/usecases/adapter-interfaces',
796
+ },
797
+ });
798
+
799
+ expect(mockIssueRepository.approvePullRequest).not.toHaveBeenCalled();
800
+ });
765
801
  });
766
802
  });
767
803
 
@@ -44,6 +44,7 @@ export class RevertNotReadyReviewQueueIssueUseCase {
44
44
  projectUrl: string;
45
45
  allowIssueCacheMinutes: number;
46
46
  labelsAsLlmAgentName?: string[] | null;
47
+ changeTargetPathAliases?: Record<string, string> | null;
47
48
  }): Promise<void> => {
48
49
  const projectId = await this.projectRepository.findProjectIdByUrl(
49
50
  params.projectUrl,
@@ -103,6 +104,7 @@ export class RevertNotReadyReviewQueueIssueUseCase {
103
104
  await this.changeTargetPullRequestApprover.approveIfConfined(
104
105
  issue.labels,
105
106
  approvedPrUrl,
107
+ params.changeTargetPathAliases,
106
108
  );
107
109
  }
108
110