github-issue-tower-defence-management 1.67.6 → 1.68.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [1.68.0](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.67.6...v1.68.0) (2026-05-29)
2
+
3
+
4
+ ### Features
5
+
6
+ * **rotation:** prefer tokens with shortest remaining 7d window so weekly quota is not wasted at reset ([ae6dc73](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/ae6dc73f457e2b79a0b2bc29832037379227512c)), closes [#710](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/710)
7
+
1
8
  ## [1.67.6](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.67.5...v1.67.6) (2026-05-29)
2
9
 
3
10
 
package/README.md CHANGED
@@ -213,7 +213,7 @@ When `claudeCodeOauthTokenListJsonPath` is set, `startDaemon` distributes prepar
213
213
 
214
214
  2. Local reverse proxy (`127.0.0.1:8787`): on each `startDaemon` run, the daemon TCP-probes the port. If nothing responds, it spawns a detached child running `bin/adapter/proxy/proxyEntry.js`. The proxy forwards every request to `api.anthropic.com`, observes the `anthropic-ratelimit-unified-*` response headers, and writes them to a per-token cache file at `${XDG_CACHE_HOME:-~/.cache}/tdpm/ratelimit/<sha256-of-token>.json`. The cache file stores the latest 5-hour and 7-day utilization, reset epochs, and the unified, 5-hour, and 7-day statuses (used to detect `blocked` and `rejected` state per window). In addition to the unified headers, the proxy inspects the streamed response body for `rate_limit` events (objects carrying `rateLimitType`, `status`, and `resetsAt`) and records the model-specific weekly limits — at minimum `seven_day_sonnet` and `seven_day` — per token. These model-specific weekly limits are exposed only in the response body, never in the unified headers, so a token can appear healthy on `anthropic-ratelimit-unified-7d-*` while its Sonnet weekly limit is exhausted.
215
215
 
216
- 3. Selection: before spawning each `aw` job, the daemon reads every token's cache file. A cached observation is treated as expired once its reset epoch has passed: when the current time is past the 5-hour reset, that token's 5-hour utilization is treated as `0` and any 5-hour-window rejection is cleared; likewise, when the 7-day reset has passed, the 7-day utilization is treated as `0` and any 7-day-window rejection is cleared; a model-specific weekly limit rejection is cleared once that limit's `resetsAt` has passed. This stale-reset expiry prevents a token that has actually recovered from being locked out of rotation forever (an excluded token receives no new requests, so the proxy never re-observes it). After expiry normalization, tokens whose status is `blocked`, whose remaining (non-expired) rejection is still active, whose 5-hour utilization meets or exceeds the configured threshold, or whose weekly limit for the model that will be used is rejected are excluded. The model name maps to a limit type: a model name containing `sonnet` maps to `seven_day_sonnet`, one containing `opus` maps to `seven_day_opus`, otherwise `seven_day`; the generic `seven_day` rejection also excludes regardless of model. The remaining eligible tokens are sorted by 7-day utilization ascending (lowest weekly load first). Each token's per-run concurrent preparation slot count is determined by its 7-day utilization: at or below 80%, the token receives the full six concurrent slots; above 80%, the slot count is reduced proportionally — specifically `ceil(6 × (1 − 7d_util) / 0.2)` — with a minimum of 1 slot at any utilization level, so near-exhausted tokens still participate rather than being cut off entirely. Tokens are dispatched round-robin across their available slots, with the token that has the lowest 7-day utilization selected preferentially. The effective preparation limit for a run is the lesser of the sum of all eligible tokens' slot counts and the explicit `maximumPreparingIssuesCount` (which defaults to 6). When a token list is configured but no eligible token remains after filtering, preparation is skipped for that run. The selected token and the proxy URL (`http://127.0.0.1:8787`) are passed to the child `aw` process as `CLAUDE_CODE_OAUTH_TOKEN` and `ANTHROPIC_BASE_URL` environment variables. The child inherits the parent process's environment, so no further wiring is required inside `aw`.
216
+ 3. Selection: before spawning each `aw` job, the daemon reads every token's cache file. A cached observation is treated as expired once its reset epoch has passed: when the current time is past the 5-hour reset, that token's 5-hour utilization is treated as `0` and any 5-hour-window rejection is cleared; likewise, when the 7-day reset has passed, the 7-day utilization is treated as `0` and any 7-day-window rejection is cleared; a model-specific weekly limit rejection is cleared once that limit's `resetsAt` has passed. This stale-reset expiry prevents a token that has actually recovered from being locked out of rotation forever (an excluded token receives no new requests, so the proxy never re-observes it). After expiry normalization, tokens whose status is `blocked`, whose remaining (non-expired) rejection is still active, whose 5-hour utilization meets or exceeds the configured threshold, or whose weekly limit for the model that will be used is rejected are excluded. The model name maps to a limit type: a model name containing `sonnet` maps to `seven_day_sonnet`, one containing `opus` maps to `seven_day_opus`, otherwise `seven_day`; the generic `seven_day` rejection also excludes regardless of model. The remaining eligible tokens are sorted by time until the 7-day reset deadline ascending (soonest 7-day reset first, so quota that would otherwise expire unused is consumed first), with 5-hour utilization ascending as the tiebreaker. The 7-day reset deadline for a given spawn is read from the per-model weekly limit entry in `modelWeeklyLimits` matching the model that will be used (`seven_day_sonnet`, `seven_day_opus`, or the generic `seven_day`); when no such entry is present on a token, that token is treated as having an infinite deadline and sorts last. Each token's per-run concurrent preparation slot count is determined by its 7-day utilization: at or below 80%, the token receives the full six concurrent slots; above 80%, the slot count is reduced proportionally — specifically `ceil(6 × (1 − 7d_util) / 0.2)` — with a minimum of 1 slot at any utilization level, so near-exhausted tokens still participate rather than being cut off entirely. Tokens are dispatched round-robin across their available slots, with the token whose 7-day reset is soonest selected preferentially. The effective preparation limit for a run is the lesser of the sum of all eligible tokens' slot counts and the explicit `maximumPreparingIssuesCount` (which defaults to 6). When a token list is configured but no eligible token remains after filtering, preparation is skipped for that run. The selected token and the proxy URL (`http://127.0.0.1:8787`) are passed to the child `aw` process as `CLAUDE_CODE_OAUTH_TOKEN` and `ANTHROPIC_BASE_URL` environment variables. The child inherits the parent process's environment, so no further wiring is required inside `aw`.
217
217
 
218
218
  When `claudeCodeOauthTokenListJsonPath` is unset, no proxy is started and `aw` runs with whatever `CLAUDE_CODE_OAUTH_TOKEN` and `ANTHROPIC_BASE_URL` are already in the environment.
219
219
 
@@ -25,6 +25,25 @@ class StartPreparationUseCase {
25
25
  const general = usage.modelWeeklyLimits['seven_day'];
26
26
  return general !== undefined && general.rejected;
27
27
  };
28
+ this.secondsUntilSevenDayReset = (usage, weeklyLimitType, nowEpochSeconds) => {
29
+ const specific = usage.modelWeeklyLimits[weeklyLimitType];
30
+ if (specific !== undefined) {
31
+ return specific.resetsAt - nowEpochSeconds;
32
+ }
33
+ const general = usage.modelWeeklyLimits['seven_day'];
34
+ if (general !== undefined) {
35
+ return general.resetsAt - nowEpochSeconds;
36
+ }
37
+ return Number.POSITIVE_INFINITY;
38
+ };
39
+ this.compareBySevenDayDeadlineThenUtilization = (a, b, weeklyLimitType, nowEpochSeconds) => {
40
+ const aSecondsUntilReset = this.secondsUntilSevenDayReset(a, weeklyLimitType, nowEpochSeconds);
41
+ const bSecondsUntilReset = this.secondsUntilSevenDayReset(b, weeklyLimitType, nowEpochSeconds);
42
+ if (aSecondsUntilReset !== bSecondsUntilReset) {
43
+ return aSecondsUntilReset - bSecondsUntilReset;
44
+ }
45
+ return a.fiveHourUtilization - b.fiveHourUtilization;
46
+ };
28
47
  this.getTokenConcurrentLimit = (sevenDayUtilization) => {
29
48
  if (sevenDayUtilization < SEVEN_DAY_THROTTLE_START_THRESHOLD) {
30
49
  return SEVEN_DAY_NORMAL_CONCURRENT_LIMIT;
@@ -34,12 +53,13 @@ class StartPreparationUseCase {
34
53
  };
35
54
  this.selectRotationTokens = (tokenUsages, utilizationPercentageThreshold, modelName, maxConcurrent) => {
36
55
  const weeklyLimitType = this.weeklyLimitTypeForModel(modelName);
56
+ const nowEpochSeconds = Date.now() / 1000;
37
57
  const eligibleTokens = tokenUsages
38
58
  .filter((usage) => !usage.blocked)
39
59
  .filter((usage) => !usage.rejected)
40
60
  .filter((usage) => !this.isModelWeeklyLimitRejected(usage, weeklyLimitType))
41
61
  .filter((usage) => usage.fiveHourUtilization * 100 < utilizationPercentageThreshold)
42
- .sort((a, b) => a.sevenDayUtilization - b.sevenDayUtilization);
62
+ .sort((a, b) => this.compareBySevenDayDeadlineThenUtilization(a, b, weeklyLimitType, nowEpochSeconds));
43
63
  if (eligibleTokens.length === 0) {
44
64
  return { tokens: [], effectiveCap: 0 };
45
65
  }
@@ -62,12 +82,13 @@ class StartPreparationUseCase {
62
82
  };
63
83
  this.buildRotationOrder = (tokenUsages, utilizationPercentageThreshold, modelName) => {
64
84
  const weeklyLimitType = this.weeklyLimitTypeForModel(modelName);
85
+ const nowEpochSeconds = Date.now() / 1000;
65
86
  const selectedTokens = tokenUsages
66
87
  .filter((usage) => !usage.blocked)
67
88
  .filter((usage) => !usage.rejected)
68
89
  .filter((usage) => !this.isModelWeeklyLimitRejected(usage, weeklyLimitType))
69
90
  .filter((usage) => usage.fiveHourUtilization * 100 < utilizationPercentageThreshold)
70
- .sort((a, b) => a.sevenDayUtilization - b.sevenDayUtilization);
91
+ .sort((a, b) => this.compareBySevenDayDeadlineThenUtilization(a, b, weeklyLimitType, nowEpochSeconds));
71
92
  const selectedTokenValues = new Set(selectedTokens.map((u) => u.token));
72
93
  const excluded = tokenUsages
73
94
  .filter((usage) => !selectedTokenValues.has(usage.token))
@@ -1 +1 @@
1
- {"version":3,"file":"StartPreparationUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/StartPreparationUseCase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StartPreparationUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/StartPreparationUseCase.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-issue-tower-defence-management",
3
- "version": "1.67.6",
3
+ "version": "1.68.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "scripts": {
@@ -6,6 +6,7 @@ import {
6
6
  import { ProjectRepository } from './adapter-interfaces/ProjectRepository';
7
7
  import { LocalCommandRunner } from './adapter-interfaces/LocalCommandRunner';
8
8
  import { ClaudeTokenUsageRepository } from './adapter-interfaces/ClaudeTokenUsageRepository';
9
+ import { ClaudeTokenUsage } from '../entities/ClaudeTokenUsage';
9
10
  import { Issue } from '../entities/Issue';
10
11
  import { Project } from '../entities/Project';
11
12
  import { StoryObjectMap } from '../entities/StoryObjectMap';
@@ -2450,7 +2451,7 @@ describe('StartPreparationUseCase', () => {
2450
2451
  ).toHaveLength(0);
2451
2452
  });
2452
2453
 
2453
- it('should pick the token with the lowest 7-day utilization first', async () => {
2454
+ it('should pick the token with the soonest 7-day reset deadline first', async () => {
2454
2455
  const awaitingIssue = createMockIssue({
2455
2456
  url: 'url1',
2456
2457
  title: 'Issue 1',
@@ -2468,24 +2469,35 @@ describe('StartPreparationUseCase', () => {
2468
2469
  stderr: '',
2469
2470
  exitCode: 0,
2470
2471
  });
2472
+ const nowEpochSeconds = Math.floor(Date.now() / 1000);
2471
2473
  mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
2472
2474
  {
2473
- name: 'token-high-7d',
2474
- token: 'token-high-7d',
2475
+ name: 'token-far-reset',
2476
+ token: 'token-far-reset',
2475
2477
  fiveHourUtilization: 0.1,
2476
2478
  sevenDayUtilization: 0.7,
2477
2479
  blocked: false,
2478
2480
  rejected: false,
2479
- modelWeeklyLimits: {},
2481
+ modelWeeklyLimits: {
2482
+ seven_day_opus: {
2483
+ rejected: false,
2484
+ resetsAt: nowEpochSeconds + 100 * 3600,
2485
+ },
2486
+ },
2480
2487
  },
2481
2488
  {
2482
- name: 'token-low-7d',
2483
- token: 'token-low-7d',
2489
+ name: 'token-soon-reset',
2490
+ token: 'token-soon-reset',
2484
2491
  fiveHourUtilization: 0.5,
2485
2492
  sevenDayUtilization: 0.2,
2486
2493
  blocked: false,
2487
2494
  rejected: false,
2488
- modelWeeklyLimits: {},
2495
+ modelWeeklyLimits: {
2496
+ seven_day_opus: {
2497
+ rejected: false,
2498
+ resetsAt: nowEpochSeconds + 20 * 3600,
2499
+ },
2500
+ },
2489
2501
  },
2490
2502
  ]);
2491
2503
 
@@ -2505,7 +2517,7 @@ describe('StartPreparationUseCase', () => {
2505
2517
  expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
2506
2518
  expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toEqual({
2507
2519
  env: {
2508
- CLAUDE_CODE_OAUTH_TOKEN: 'token-low-7d',
2520
+ CLAUDE_CODE_OAUTH_TOKEN: 'token-soon-reset',
2509
2521
  ANTHROPIC_BASE_URL: 'http://127.0.0.1:8787',
2510
2522
  },
2511
2523
  });
@@ -2706,7 +2718,7 @@ describe('StartPreparationUseCase', () => {
2706
2718
  consoleWarnSpy.mockRestore();
2707
2719
  });
2708
2720
 
2709
- it('should sort tokens by 7-day utilization ascending when all have full process capacity', async () => {
2721
+ it('should sort tokens by 7-day reset deadline ascending when all have full process capacity', async () => {
2710
2722
  const awaitingIssues: Issue[] = [
2711
2723
  createMockIssue({
2712
2724
  url: 'url1',
@@ -2742,33 +2754,49 @@ describe('StartPreparationUseCase', () => {
2742
2754
  stderr: '',
2743
2755
  exitCode: 0,
2744
2756
  });
2757
+ const nowEpochSeconds = Math.floor(Date.now() / 1000);
2745
2758
  mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
2746
2759
  {
2747
- name: 'token-7d-mid',
2748
- token: 'token-7d-mid',
2760
+ name: 'token-7d-mid-reset',
2761
+ token: 'token-7d-mid-reset',
2749
2762
  fiveHourUtilization: 0.1,
2750
2763
  sevenDayUtilization: 0.5,
2751
2764
  blocked: false,
2752
2765
  rejected: false,
2753
- modelWeeklyLimits: {},
2766
+ modelWeeklyLimits: {
2767
+ seven_day_opus: {
2768
+ rejected: false,
2769
+ resetsAt: nowEpochSeconds + 50 * 3600,
2770
+ },
2771
+ },
2754
2772
  },
2755
2773
  {
2756
- name: 'token-7d-low',
2757
- token: 'token-7d-low',
2774
+ name: 'token-7d-soon-reset',
2775
+ token: 'token-7d-soon-reset',
2758
2776
  fiveHourUtilization: 0.5,
2759
2777
  sevenDayUtilization: 0.1,
2760
2778
  blocked: false,
2761
2779
  rejected: false,
2762
- modelWeeklyLimits: {},
2780
+ modelWeeklyLimits: {
2781
+ seven_day_opus: {
2782
+ rejected: false,
2783
+ resetsAt: nowEpochSeconds + 10 * 3600,
2784
+ },
2785
+ },
2763
2786
  },
2764
2787
  {
2765
- name: 'token-7d-high',
2766
- token: 'token-7d-high',
2788
+ name: 'token-7d-far-reset',
2789
+ token: 'token-7d-far-reset',
2767
2790
  fiveHourUtilization: 0.3,
2768
2791
  sevenDayUtilization: 0.7,
2769
2792
  blocked: false,
2770
2793
  rejected: false,
2771
- modelWeeklyLimits: {},
2794
+ modelWeeklyLimits: {
2795
+ seven_day_opus: {
2796
+ rejected: false,
2797
+ resetsAt: nowEpochSeconds + 150 * 3600,
2798
+ },
2799
+ },
2772
2800
  },
2773
2801
  ]);
2774
2802
 
@@ -2787,13 +2815,13 @@ describe('StartPreparationUseCase', () => {
2787
2815
 
2788
2816
  expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(3);
2789
2817
  expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toMatchObject({
2790
- env: { CLAUDE_CODE_OAUTH_TOKEN: 'token-7d-low' },
2818
+ env: { CLAUDE_CODE_OAUTH_TOKEN: 'token-7d-soon-reset' },
2791
2819
  });
2792
2820
  expect(mockLocalCommandRunner.runCommand.mock.calls[1][2]).toMatchObject({
2793
- env: { CLAUDE_CODE_OAUTH_TOKEN: 'token-7d-mid' },
2821
+ env: { CLAUDE_CODE_OAUTH_TOKEN: 'token-7d-mid-reset' },
2794
2822
  });
2795
2823
  expect(mockLocalCommandRunner.runCommand.mock.calls[2][2]).toMatchObject({
2796
- env: { CLAUDE_CODE_OAUTH_TOKEN: 'token-7d-high' },
2824
+ env: { CLAUDE_CODE_OAUTH_TOKEN: 'token-7d-far-reset' },
2797
2825
  });
2798
2826
  });
2799
2827
 
@@ -3399,6 +3427,294 @@ describe('StartPreparationUseCase', () => {
3399
3427
  },
3400
3428
  });
3401
3429
  });
3430
+
3431
+ it('should pick the token whose 7-day reset is sooner before the token whose 7-day reset is farther', async () => {
3432
+ const awaitingIssue = createMockIssue({
3433
+ url: 'url1',
3434
+ title: 'Issue 1',
3435
+ labels: ['category:impl'],
3436
+ status: 'Awaiting Workspace',
3437
+ number: 1,
3438
+ itemId: 'item-1',
3439
+ });
3440
+ mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
3441
+ mockIssueRepository.getStoryObjectMap.mockResolvedValue(
3442
+ createMockStoryObjectMap([awaitingIssue]),
3443
+ );
3444
+ mockLocalCommandRunner.runCommand.mockResolvedValue({
3445
+ stdout: '',
3446
+ stderr: '',
3447
+ exitCode: 0,
3448
+ });
3449
+ const nowEpochSeconds = Math.floor(Date.now() / 1000);
3450
+ mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
3451
+ {
3452
+ name: 'token-b-far-reset',
3453
+ token: 'token-b-far-reset',
3454
+ fiveHourUtilization: 0.1,
3455
+ sevenDayUtilization: 0.1,
3456
+ blocked: false,
3457
+ rejected: false,
3458
+ modelWeeklyLimits: {
3459
+ seven_day_opus: {
3460
+ rejected: false,
3461
+ resetsAt: nowEpochSeconds + 100 * 3600,
3462
+ },
3463
+ },
3464
+ },
3465
+ {
3466
+ name: 'token-a-soon-reset',
3467
+ token: 'token-a-soon-reset',
3468
+ fiveHourUtilization: 0.1,
3469
+ sevenDayUtilization: 0.1,
3470
+ blocked: false,
3471
+ rejected: false,
3472
+ modelWeeklyLimits: {
3473
+ seven_day_opus: {
3474
+ rejected: false,
3475
+ resetsAt: nowEpochSeconds + 20 * 3600,
3476
+ },
3477
+ },
3478
+ },
3479
+ ]);
3480
+
3481
+ await useCase.run({
3482
+ projectUrl: 'https://github.com/user/repo',
3483
+ defaultAgentName: 'agent1',
3484
+ defaultLlmModelName: 'claude-opus',
3485
+ defaultLlmAgentName: null,
3486
+ configFilePath: '/path/to/config.yml',
3487
+ maximumPreparingIssuesCount: null,
3488
+ utilizationPercentageThreshold: 90,
3489
+ allowedIssueAuthors: null,
3490
+ codexHomeCandidates: null,
3491
+ allowIssueCacheMinutes: 0,
3492
+ });
3493
+
3494
+ expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
3495
+ expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toEqual({
3496
+ env: {
3497
+ CLAUDE_CODE_OAUTH_TOKEN: 'token-a-soon-reset',
3498
+ ANTHROPIC_BASE_URL: 'http://127.0.0.1:8787',
3499
+ },
3500
+ });
3501
+ });
3502
+
3503
+ it('should exclude a blocked token even when it has a sooner 7-day reset than an eligible token', async () => {
3504
+ const awaitingIssue = createMockIssue({
3505
+ url: 'url1',
3506
+ title: 'Issue 1',
3507
+ labels: ['category:impl'],
3508
+ status: 'Awaiting Workspace',
3509
+ number: 1,
3510
+ itemId: 'item-1',
3511
+ });
3512
+ mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
3513
+ mockIssueRepository.getStoryObjectMap.mockResolvedValue(
3514
+ createMockStoryObjectMap([awaitingIssue]),
3515
+ );
3516
+ mockLocalCommandRunner.runCommand.mockResolvedValue({
3517
+ stdout: '',
3518
+ stderr: '',
3519
+ exitCode: 0,
3520
+ });
3521
+ const nowEpochSeconds = Math.floor(Date.now() / 1000);
3522
+ mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
3523
+ {
3524
+ name: 'token-a-blocked-soon-reset',
3525
+ token: 'token-a-blocked-soon-reset',
3526
+ fiveHourUtilization: 0.1,
3527
+ sevenDayUtilization: 0.1,
3528
+ blocked: true,
3529
+ rejected: false,
3530
+ modelWeeklyLimits: {
3531
+ seven_day_opus: {
3532
+ rejected: false,
3533
+ resetsAt: nowEpochSeconds + 20 * 3600,
3534
+ },
3535
+ },
3536
+ },
3537
+ {
3538
+ name: 'token-b-far-reset',
3539
+ token: 'token-b-far-reset',
3540
+ fiveHourUtilization: 0.1,
3541
+ sevenDayUtilization: 0.1,
3542
+ blocked: false,
3543
+ rejected: false,
3544
+ modelWeeklyLimits: {
3545
+ seven_day_opus: {
3546
+ rejected: false,
3547
+ resetsAt: nowEpochSeconds + 100 * 3600,
3548
+ },
3549
+ },
3550
+ },
3551
+ ]);
3552
+
3553
+ await useCase.run({
3554
+ projectUrl: 'https://github.com/user/repo',
3555
+ defaultAgentName: 'agent1',
3556
+ defaultLlmModelName: 'claude-opus',
3557
+ defaultLlmAgentName: null,
3558
+ configFilePath: '/path/to/config.yml',
3559
+ maximumPreparingIssuesCount: null,
3560
+ utilizationPercentageThreshold: 90,
3561
+ allowedIssueAuthors: null,
3562
+ codexHomeCandidates: null,
3563
+ allowIssueCacheMinutes: 0,
3564
+ });
3565
+
3566
+ expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
3567
+ expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toEqual({
3568
+ env: {
3569
+ CLAUDE_CODE_OAUTH_TOKEN: 'token-b-far-reset',
3570
+ ANTHROPIC_BASE_URL: 'http://127.0.0.1:8787',
3571
+ },
3572
+ });
3573
+ });
3574
+
3575
+ it('should place a token whose 7-day reset is unknown after a token whose 7-day reset is known', async () => {
3576
+ const awaitingIssues: Issue[] = [
3577
+ createMockIssue({
3578
+ url: 'url1',
3579
+ title: 'Issue 1',
3580
+ labels: ['category:impl'],
3581
+ status: 'Awaiting Workspace',
3582
+ number: 1,
3583
+ itemId: 'item-1',
3584
+ }),
3585
+ createMockIssue({
3586
+ url: 'url2',
3587
+ title: 'Issue 2',
3588
+ labels: ['category:impl'],
3589
+ status: 'Awaiting Workspace',
3590
+ number: 2,
3591
+ itemId: 'item-2',
3592
+ }),
3593
+ ];
3594
+ mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
3595
+ mockIssueRepository.getStoryObjectMap.mockResolvedValue(
3596
+ createMockStoryObjectMap(awaitingIssues),
3597
+ );
3598
+ mockLocalCommandRunner.runCommand.mockResolvedValue({
3599
+ stdout: '',
3600
+ stderr: '',
3601
+ exitCode: 0,
3602
+ });
3603
+ const nowEpochSeconds = Math.floor(Date.now() / 1000);
3604
+ mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
3605
+ {
3606
+ name: 'token-a-unknown-reset',
3607
+ token: 'token-a-unknown-reset',
3608
+ fiveHourUtilization: 0.1,
3609
+ sevenDayUtilization: 0.1,
3610
+ blocked: false,
3611
+ rejected: false,
3612
+ modelWeeklyLimits: {},
3613
+ },
3614
+ {
3615
+ name: 'token-b-known-soon-reset',
3616
+ token: 'token-b-known-soon-reset',
3617
+ fiveHourUtilization: 0.1,
3618
+ sevenDayUtilization: 0.1,
3619
+ blocked: false,
3620
+ rejected: false,
3621
+ modelWeeklyLimits: {
3622
+ seven_day_opus: {
3623
+ rejected: false,
3624
+ resetsAt: nowEpochSeconds + 20 * 3600,
3625
+ },
3626
+ },
3627
+ },
3628
+ ]);
3629
+
3630
+ await useCase.run({
3631
+ projectUrl: 'https://github.com/user/repo',
3632
+ defaultAgentName: 'agent1',
3633
+ defaultLlmModelName: 'claude-opus',
3634
+ defaultLlmAgentName: null,
3635
+ configFilePath: '/path/to/config.yml',
3636
+ maximumPreparingIssuesCount: null,
3637
+ utilizationPercentageThreshold: 90,
3638
+ allowedIssueAuthors: null,
3639
+ codexHomeCandidates: null,
3640
+ allowIssueCacheMinutes: 0,
3641
+ });
3642
+
3643
+ expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(2);
3644
+ expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toMatchObject({
3645
+ env: { CLAUDE_CODE_OAUTH_TOKEN: 'token-b-known-soon-reset' },
3646
+ });
3647
+ expect(mockLocalCommandRunner.runCommand.mock.calls[1][2]).toMatchObject({
3648
+ env: { CLAUDE_CODE_OAUTH_TOKEN: 'token-a-unknown-reset' },
3649
+ });
3650
+ });
3651
+
3652
+ it('should fall back to 5-hour utilization ascending as tiebreaker when 7-day reset deadlines are identical', async () => {
3653
+ const awaitingIssue = createMockIssue({
3654
+ url: 'url1',
3655
+ title: 'Issue 1',
3656
+ labels: ['category:impl'],
3657
+ status: 'Awaiting Workspace',
3658
+ number: 1,
3659
+ itemId: 'item-1',
3660
+ });
3661
+ mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
3662
+ mockIssueRepository.getStoryObjectMap.mockResolvedValue(
3663
+ createMockStoryObjectMap([awaitingIssue]),
3664
+ );
3665
+ mockLocalCommandRunner.runCommand.mockResolvedValue({
3666
+ stdout: '',
3667
+ stderr: '',
3668
+ exitCode: 0,
3669
+ });
3670
+ const nowEpochSeconds = Math.floor(Date.now() / 1000);
3671
+ const sharedResetsAt = nowEpochSeconds + 50 * 3600;
3672
+ mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
3673
+ {
3674
+ name: 'token-busy-5h',
3675
+ token: 'token-busy-5h',
3676
+ fiveHourUtilization: 0.6,
3677
+ sevenDayUtilization: 0.1,
3678
+ blocked: false,
3679
+ rejected: false,
3680
+ modelWeeklyLimits: {
3681
+ seven_day_opus: { rejected: false, resetsAt: sharedResetsAt },
3682
+ },
3683
+ },
3684
+ {
3685
+ name: 'token-idle-5h',
3686
+ token: 'token-idle-5h',
3687
+ fiveHourUtilization: 0.1,
3688
+ sevenDayUtilization: 0.1,
3689
+ blocked: false,
3690
+ rejected: false,
3691
+ modelWeeklyLimits: {
3692
+ seven_day_opus: { rejected: false, resetsAt: sharedResetsAt },
3693
+ },
3694
+ },
3695
+ ]);
3696
+
3697
+ await useCase.run({
3698
+ projectUrl: 'https://github.com/user/repo',
3699
+ defaultAgentName: 'agent1',
3700
+ defaultLlmModelName: 'claude-opus',
3701
+ defaultLlmAgentName: null,
3702
+ configFilePath: '/path/to/config.yml',
3703
+ maximumPreparingIssuesCount: null,
3704
+ utilizationPercentageThreshold: 90,
3705
+ allowedIssueAuthors: null,
3706
+ codexHomeCandidates: null,
3707
+ allowIssueCacheMinutes: 0,
3708
+ });
3709
+
3710
+ expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
3711
+ expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toEqual({
3712
+ env: {
3713
+ CLAUDE_CODE_OAUTH_TOKEN: 'token-idle-5h',
3714
+ ANTHROPIC_BASE_URL: 'http://127.0.0.1:8787',
3715
+ },
3716
+ });
3717
+ });
3402
3718
  });
3403
3719
 
3404
3720
  describe('StartPreparationUseCase.buildRotationOrder', () => {
@@ -3444,25 +3760,36 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
3444
3760
  mockClaudeTokenUsageRepositoryForRotation,
3445
3761
  );
3446
3762
 
3447
- it('lists selected tokens first in ascending 7-day utilization order then excluded tokens', () => {
3448
- const tokenUsages = [
3763
+ it('lists selected tokens first in ascending 7-day reset deadline order then excluded tokens', () => {
3764
+ const nowEpochSeconds = Math.floor(Date.now() / 1000);
3765
+ const tokenUsages: ClaudeTokenUsage[] = [
3449
3766
  {
3450
- name: 'high-7d-util',
3451
- token: 'sk-ant-high',
3767
+ name: 'far-7d-reset',
3768
+ token: 'sk-ant-far',
3452
3769
  fiveHourUtilization: 0.1,
3453
3770
  sevenDayUtilization: 0.8,
3454
3771
  blocked: false,
3455
3772
  rejected: false,
3456
- modelWeeklyLimits: {},
3773
+ modelWeeklyLimits: {
3774
+ seven_day: {
3775
+ rejected: false,
3776
+ resetsAt: nowEpochSeconds + 100 * 3600,
3777
+ },
3778
+ },
3457
3779
  },
3458
3780
  {
3459
- name: 'low-7d-util',
3460
- token: 'sk-ant-low',
3781
+ name: 'soon-7d-reset',
3782
+ token: 'sk-ant-soon',
3461
3783
  fiveHourUtilization: 0.5,
3462
3784
  sevenDayUtilization: 0.1,
3463
3785
  blocked: false,
3464
3786
  rejected: false,
3465
- modelWeeklyLimits: {},
3787
+ modelWeeklyLimits: {
3788
+ seven_day: {
3789
+ rejected: false,
3790
+ resetsAt: nowEpochSeconds + 20 * 3600,
3791
+ },
3792
+ },
3466
3793
  },
3467
3794
  {
3468
3795
  name: 'blocked-token',
@@ -3476,8 +3803,8 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
3476
3803
  ];
3477
3804
  const result = useCase.buildRotationOrder(tokenUsages, 90, null);
3478
3805
 
3479
- expect(result[0].name).toBe('low-7d-util');
3480
- expect(result[1].name).toBe('high-7d-util');
3806
+ expect(result[0].name).toBe('soon-7d-reset');
3807
+ expect(result[1].name).toBe('far-7d-reset');
3481
3808
  expect(result[2].name).toBe('blocked-token');
3482
3809
  expect(result[2].blocked).toBe(true);
3483
3810
  expect(result[2].thresholdExcluded).toBe(false);
@@ -53,6 +53,44 @@ export class StartPreparationUseCase {
53
53
  return general !== undefined && general.rejected;
54
54
  };
55
55
 
56
+ private secondsUntilSevenDayReset = (
57
+ usage: ClaudeTokenUsage,
58
+ weeklyLimitType: string,
59
+ nowEpochSeconds: number,
60
+ ): number => {
61
+ const specific = usage.modelWeeklyLimits[weeklyLimitType];
62
+ if (specific !== undefined) {
63
+ return specific.resetsAt - nowEpochSeconds;
64
+ }
65
+ const general = usage.modelWeeklyLimits['seven_day'];
66
+ if (general !== undefined) {
67
+ return general.resetsAt - nowEpochSeconds;
68
+ }
69
+ return Number.POSITIVE_INFINITY;
70
+ };
71
+
72
+ private compareBySevenDayDeadlineThenUtilization = (
73
+ a: ClaudeTokenUsage,
74
+ b: ClaudeTokenUsage,
75
+ weeklyLimitType: string,
76
+ nowEpochSeconds: number,
77
+ ): number => {
78
+ const aSecondsUntilReset = this.secondsUntilSevenDayReset(
79
+ a,
80
+ weeklyLimitType,
81
+ nowEpochSeconds,
82
+ );
83
+ const bSecondsUntilReset = this.secondsUntilSevenDayReset(
84
+ b,
85
+ weeklyLimitType,
86
+ nowEpochSeconds,
87
+ );
88
+ if (aSecondsUntilReset !== bSecondsUntilReset) {
89
+ return aSecondsUntilReset - bSecondsUntilReset;
90
+ }
91
+ return a.fiveHourUtilization - b.fiveHourUtilization;
92
+ };
93
+
56
94
  private getTokenConcurrentLimit = (sevenDayUtilization: number): number => {
57
95
  if (sevenDayUtilization < SEVEN_DAY_THROTTLE_START_THRESHOLD) {
58
96
  return SEVEN_DAY_NORMAL_CONCURRENT_LIMIT;
@@ -72,6 +110,7 @@ export class StartPreparationUseCase {
72
110
  maxConcurrent: number,
73
111
  ): { tokens: string[]; effectiveCap: number } => {
74
112
  const weeklyLimitType = this.weeklyLimitTypeForModel(modelName);
113
+ const nowEpochSeconds = Date.now() / 1000;
75
114
  const eligibleTokens = tokenUsages
76
115
  .filter((usage) => !usage.blocked)
77
116
  .filter((usage) => !usage.rejected)
@@ -82,7 +121,14 @@ export class StartPreparationUseCase {
82
121
  (usage) =>
83
122
  usage.fiveHourUtilization * 100 < utilizationPercentageThreshold,
84
123
  )
85
- .sort((a, b) => a.sevenDayUtilization - b.sevenDayUtilization);
124
+ .sort((a, b) =>
125
+ this.compareBySevenDayDeadlineThenUtilization(
126
+ a,
127
+ b,
128
+ weeklyLimitType,
129
+ nowEpochSeconds,
130
+ ),
131
+ );
86
132
 
87
133
  if (eligibleTokens.length === 0) {
88
134
  return { tokens: [], effectiveCap: 0 };
@@ -115,6 +161,7 @@ export class StartPreparationUseCase {
115
161
  modelName: string | null,
116
162
  ): RotationOrderEntry[] => {
117
163
  const weeklyLimitType = this.weeklyLimitTypeForModel(modelName);
164
+ const nowEpochSeconds = Date.now() / 1000;
118
165
  const selectedTokens = tokenUsages
119
166
  .filter((usage) => !usage.blocked)
120
167
  .filter((usage) => !usage.rejected)
@@ -125,7 +172,14 @@ export class StartPreparationUseCase {
125
172
  (usage) =>
126
173
  usage.fiveHourUtilization * 100 < utilizationPercentageThreshold,
127
174
  )
128
- .sort((a, b) => a.sevenDayUtilization - b.sevenDayUtilization);
175
+ .sort((a, b) =>
176
+ this.compareBySevenDayDeadlineThenUtilization(
177
+ a,
178
+ b,
179
+ weeklyLimitType,
180
+ nowEpochSeconds,
181
+ ),
182
+ );
129
183
  const selectedTokenValues = new Set(selectedTokens.map((u) => u.token));
130
184
  const excluded: RotationOrderEntry[] = tokenUsages
131
185
  .filter((usage) => !selectedTokenValues.has(usage.token))
@@ -18,6 +18,8 @@ export declare class StartPreparationUseCase {
18
18
  constructor(projectRepository: Pick<ProjectRepository, 'getByUrl'>, issueRepository: Pick<IssueRepository, 'getStoryObjectMap' | 'updateStatus' | 'findRelatedOpenPRs' | 'getOpenPullRequest' | 'closePullRequest' | 'deletePullRequestBranch' | 'createCommentByUrl'>, localCommandRunner: LocalCommandRunner, claudeTokenUsageRepository: ClaudeTokenUsageRepository);
19
19
  private weeklyLimitTypeForModel;
20
20
  private isModelWeeklyLimitRejected;
21
+ private secondsUntilSevenDayReset;
22
+ private compareBySevenDayDeadlineThenUtilization;
21
23
  private getTokenConcurrentLimit;
22
24
  private selectRotationTokens;
23
25
  buildRotationOrder: (tokenUsages: ClaudeTokenUsage[], utilizationPercentageThreshold: number, modelName: string | null) => RotationOrderEntry[];
@@ -1 +1 @@
1
- {"version":3,"file":"StartPreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/StartPreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,0BAA0B,EAAE,MAAM,iDAAiD,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAShE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAUhC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,0BAA0B;gBAZ1B,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,EACtD,eAAe,EAAE,IAAI,CACpC,eAAe,EACb,mBAAmB,GACnB,cAAc,GACd,oBAAoB,GACpB,oBAAoB,GACpB,kBAAkB,GAClB,yBAAyB,GACzB,oBAAoB,CACvB,EACgB,kBAAkB,EAAE,kBAAkB,EACtC,0BAA0B,EAAE,0BAA0B;IAGzE,OAAO,CAAC,uBAAuB,CAK7B;IAEF,OAAO,CAAC,0BAA0B,CAQhC;IAEF,OAAO,CAAC,uBAAuB,CAU7B;IAEF,OAAO,CAAC,oBAAoB,CA0C1B;IAEF,kBAAkB,GAChB,aAAa,gBAAgB,EAAE,EAC/B,gCAAgC,MAAM,EACtC,WAAW,MAAM,GAAG,IAAI,KACvB,kBAAkB,EAAE,CAqCrB;IAEF,GAAG,GAAU,QAAQ;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,gBAAgB,EAAE,MAAM,CAAC;QACzB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,cAAc,EAAE,MAAM,CAAC;QACvB,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3C,8BAA8B,EAAE,MAAM,CAAC;QACvC,mBAAmB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACrC,mBAAmB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACrC,sBAAsB,EAAE,MAAM,CAAC;KAChC,KAAG,OAAO,CAAC;QAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAA;KAAE,CAAC,CAmPzD;CACH"}
1
+ {"version":3,"file":"StartPreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/StartPreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,0BAA0B,EAAE,MAAM,iDAAiD,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAShE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAUhC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,0BAA0B;gBAZ1B,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,EACtD,eAAe,EAAE,IAAI,CACpC,eAAe,EACb,mBAAmB,GACnB,cAAc,GACd,oBAAoB,GACpB,oBAAoB,GACpB,kBAAkB,GAClB,yBAAyB,GACzB,oBAAoB,CACvB,EACgB,kBAAkB,EAAE,kBAAkB,EACtC,0BAA0B,EAAE,0BAA0B;IAGzE,OAAO,CAAC,uBAAuB,CAK7B;IAEF,OAAO,CAAC,0BAA0B,CAQhC;IAEF,OAAO,CAAC,yBAAyB,CAc/B;IAEF,OAAO,CAAC,wCAAwC,CAoB9C;IAEF,OAAO,CAAC,uBAAuB,CAU7B;IAEF,OAAO,CAAC,oBAAoB,CAkD1B;IAEF,kBAAkB,GAChB,aAAa,gBAAgB,EAAE,EAC/B,gCAAgC,MAAM,EACtC,WAAW,MAAM,GAAG,IAAI,KACvB,kBAAkB,EAAE,CA6CrB;IAEF,GAAG,GAAU,QAAQ;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,gBAAgB,EAAE,MAAM,CAAC;QACzB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,cAAc,EAAE,MAAM,CAAC;QACvB,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3C,8BAA8B,EAAE,MAAM,CAAC;QACvC,mBAAmB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACrC,mBAAmB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACrC,sBAAsB,EAAE,MAAM,CAAC;KAChC,KAAG,OAAO,CAAC;QAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAA;KAAE,CAAC,CAmPzD;CACH"}