github-issue-tower-defence-management 1.166.6 → 1.168.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 (51) hide show
  1. package/.github/workflows/console-ui.yml +1 -0
  2. package/CHANGELOG.md +20 -0
  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/console/ui-dist/assets/index-DkAuY63u.js +86 -0
  6. package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
  7. package/bin/adapter/entry-points/console/ui-dist/sw.js +60 -0
  8. package/bin/domain/usecases/HandleScheduledEventUseCase.js +1 -0
  9. package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -1
  10. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +2 -26
  11. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
  12. package/bin/domain/usecases/StartPreparationUseCase.js +19 -0
  13. package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -1
  14. package/bin/domain/usecases/console/GenerateConsoleListsUseCase.js +7 -1
  15. package/bin/domain/usecases/console/GenerateConsoleListsUseCase.js.map +1 -1
  16. package/bin/domain/usecases/ensureAgentOptionAndGetId.js +31 -0
  17. package/bin/domain/usecases/ensureAgentOptionAndGetId.js.map +1 -0
  18. package/package.json +1 -1
  19. package/src/adapter/ci/consoleUiWorkflowTimeout.test.ts +61 -0
  20. package/src/adapter/entry-points/cli/index.test.ts +33 -0
  21. package/src/adapter/entry-points/cli/index.ts +1 -0
  22. package/src/adapter/entry-points/console/ui/public/sw.js +60 -0
  23. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleTabList.stories.tsx +9 -0
  24. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleTabList.test.tsx +31 -0
  25. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleTabList.tsx +8 -1
  26. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTabData.test.ts +111 -15
  27. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTabData.ts +100 -15
  28. package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.test.ts +70 -1
  29. package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.ts +42 -6
  30. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +2 -0
  31. package/src/adapter/entry-points/console/ui/src/main.tsx +6 -0
  32. package/src/adapter/entry-points/console/ui-dist/assets/index-DkAuY63u.js +86 -0
  33. package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
  34. package/src/adapter/entry-points/console/ui-dist/sw.js +60 -0
  35. package/src/domain/usecases/HandleScheduledEventUseCase.ts +1 -0
  36. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +4 -38
  37. package/src/domain/usecases/StartPreparationUseCase.test.ts +199 -4
  38. package/src/domain/usecases/StartPreparationUseCase.ts +50 -1
  39. package/src/domain/usecases/console/GenerateConsoleListsUseCase.test.ts +13 -0
  40. package/src/domain/usecases/console/GenerateConsoleListsUseCase.ts +6 -1
  41. package/src/domain/usecases/ensureAgentOptionAndGetId.ts +47 -0
  42. package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
  43. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -1
  44. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
  45. package/types/domain/usecases/StartPreparationUseCase.d.ts +3 -1
  46. package/types/domain/usecases/StartPreparationUseCase.d.ts.map +1 -1
  47. package/types/domain/usecases/console/GenerateConsoleListsUseCase.d.ts.map +1 -1
  48. package/types/domain/usecases/ensureAgentOptionAndGetId.d.ts +4 -0
  49. package/types/domain/usecases/ensureAgentOptionAndGetId.d.ts.map +1 -0
  50. package/bin/adapter/entry-points/console/ui-dist/assets/index-CrSqMAVR.js +0 -86
  51. package/src/adapter/entry-points/console/ui-dist/assets/index-CrSqMAVR.js +0 -86
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>TDPM Console</title>
7
- <script type="module" crossorigin src="/assets/index-CrSqMAVR.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-DkAuY63u.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-U8I8ESZj.css">
9
9
  </head>
10
10
  <body>
@@ -0,0 +1,60 @@
1
+ const SHELL_CACHE = 'console-shell-v1';
2
+
3
+ self.addEventListener('install', (event) => {
4
+ event.waitUntil(caches.open(SHELL_CACHE).then((cache) => cache.add('/')));
5
+ self.skipWaiting();
6
+ });
7
+
8
+ self.addEventListener('activate', (event) => {
9
+ event.waitUntil(
10
+ caches
11
+ .keys()
12
+ .then((names) =>
13
+ Promise.all(
14
+ names
15
+ .filter((name) => name !== SHELL_CACHE)
16
+ .map((name) => caches.delete(name)),
17
+ ),
18
+ ),
19
+ );
20
+ self.clients.claim();
21
+ });
22
+
23
+ self.addEventListener('fetch', (event) => {
24
+ if (event.request.method !== 'GET') {
25
+ return;
26
+ }
27
+ const url = new URL(event.request.url);
28
+ if (url.origin !== self.location.origin) {
29
+ return;
30
+ }
31
+ if (
32
+ url.pathname.startsWith('/projects/') ||
33
+ url.pathname.startsWith('/api/')
34
+ ) {
35
+ return;
36
+ }
37
+ event.respondWith(
38
+ fetch(event.request)
39
+ .then((response) => {
40
+ if (response.ok) {
41
+ caches
42
+ .open(SHELL_CACHE)
43
+ .then((cache) => cache.put(event.request, response.clone()))
44
+ .catch((e) => console.warn('Shell cache put failed:', e));
45
+ }
46
+ return response;
47
+ })
48
+ .catch(async () => {
49
+ const cached = await caches.match(event.request);
50
+ if (cached !== undefined) {
51
+ return cached;
52
+ }
53
+ const root = await caches.match('/');
54
+ if (root !== undefined) {
55
+ return root;
56
+ }
57
+ return Response.error();
58
+ }),
59
+ );
60
+ });
@@ -471,6 +471,7 @@ ${JSON.stringify(e)}
471
471
  manager: input.manager,
472
472
  codexHomeCandidates: input.startPreparation.codexHomeCandidates ?? null,
473
473
  labelsAsLlmAgentName,
474
+ agents: input.agents ?? null,
474
475
  });
475
476
  return { rotationOrder: preparationResult.rotationOrder };
476
477
  }
@@ -25,9 +25,8 @@ import {
25
25
  ConsoleTabName,
26
26
  } from './console/GenerateConsoleListsUseCase';
27
27
  import { Issue } from '../entities/Issue';
28
- import { FieldOption, Project } from '../entities/Project';
29
- import { normalizeProjectFieldName } from '../entities/ProjectFieldName';
30
- import { AGENT_FIELD_NAME } from '../entities/RequiredProjectField';
28
+ import { Project } from '../entities/Project';
29
+ import { ensureAgentOptionAndGetId } from './ensureAgentOptionAndGetId';
31
30
 
32
31
  export class IssueNotFoundError extends Error {
33
32
  constructor(issueUrl: string) {
@@ -566,41 +565,8 @@ export class NotifyFinishedIssuePreparationUseCase {
566
565
  private ensureAgentOptionAndGetId = async (
567
566
  project: Project,
568
567
  agentName: string,
569
- ): Promise<string | null> => {
570
- const normalizedTarget = normalizeProjectFieldName(agentName);
571
- if (!project.agent) {
572
- await this.projectRepository.createField(project, {
573
- name: AGENT_FIELD_NAME,
574
- dataType: 'SINGLE_SELECT',
575
- options: [{ name: agentName, color: 'GRAY' as const, description: '' }],
576
- });
577
- const refreshed = await this.projectRepository.getByUrl(project.url);
578
- const created = refreshed.agent?.options.find(
579
- (o) => normalizeProjectFieldName(o.name) === normalizedTarget,
580
- );
581
- return created?.id ?? null;
582
- }
583
- const existing = project.agent.options.find(
584
- (o) => normalizeProjectFieldName(o.name) === normalizedTarget,
585
- );
586
- if (existing) {
587
- return existing.id;
588
- }
589
- const mergedOptions: (Omit<FieldOption, 'id'> & {
590
- id: FieldOption['id'] | null;
591
- })[] = [
592
- ...project.agent.options.map((o) => ({ ...o })),
593
- { id: null, name: agentName, color: 'GRAY' as const, description: '' },
594
- ];
595
- const updatedOptions = await this.projectRepository.updateAgentList(
596
- project,
597
- mergedOptions,
598
- );
599
- const added = updatedOptions.find(
600
- (o) => normalizeProjectFieldName(o.name) === normalizedTarget,
601
- );
602
- return added?.id ?? null;
603
- };
568
+ ): Promise<string | null> =>
569
+ ensureAgentOptionAndGetId(this.projectRepository, project, agentName);
604
570
 
605
571
  private patchConsoleTab = async (issue: Issue): Promise<void> => {
606
572
  if (!this.consoleTabsRepository) return;
@@ -9,7 +9,7 @@ import { ClaudeTokenUsageRepository } from './adapter-interfaces/ClaudeTokenUsag
9
9
  import { TakeOwnershipSpawnRepository } from './adapter-interfaces/TakeOwnershipSpawnRepository';
10
10
  import { ClaudeTokenUsage } from '../entities/ClaudeTokenUsage';
11
11
  import { Issue } from '../entities/Issue';
12
- import { Project } from '../entities/Project';
12
+ import { FieldOption, Project } from '../entities/Project';
13
13
  import { StoryObjectMap } from '../entities/StoryObjectMap';
14
14
  type Mocked<T> = jest.Mocked<T> & jest.MockedObject<T>;
15
15
 
@@ -82,7 +82,9 @@ const createMockProject = (): Project => ({
82
82
 
83
83
  describe('StartPreparationUseCase', () => {
84
84
  let useCase: StartPreparationUseCase;
85
- let mockProjectRepository: Mocked<Pick<ProjectRepository, 'getByUrl'>>;
85
+ let mockProjectRepository: Mocked<
86
+ Pick<ProjectRepository, 'getByUrl' | 'createField' | 'updateAgentList'>
87
+ >;
86
88
  let mockIssueRepository: Mocked<
87
89
  Pick<
88
90
  IssueRepository,
@@ -94,6 +96,8 @@ describe('StartPreparationUseCase', () => {
94
96
  | 'closePullRequest'
95
97
  | 'deletePullRequestBranch'
96
98
  | 'createCommentByUrl'
99
+ | 'setIssueAgentField'
100
+ | 'removeLabel'
97
101
  >
98
102
  >;
99
103
  let mockLocalCommandRunner: Mocked<LocalCommandRunner>;
@@ -105,6 +109,8 @@ describe('StartPreparationUseCase', () => {
105
109
  mockProject = createMockProject();
106
110
  mockProjectRepository = {
107
111
  getByUrl: jest.fn(),
112
+ createField: jest.fn().mockResolvedValue(undefined),
113
+ updateAgentList: jest.fn().mockResolvedValue([]),
108
114
  };
109
115
  mockIssueRepository = {
110
116
  getStoryObjectMap: jest.fn().mockResolvedValue(new Map()),
@@ -115,6 +121,8 @@ describe('StartPreparationUseCase', () => {
115
121
  closePullRequest: jest.fn().mockResolvedValue(undefined),
116
122
  deletePullRequestBranch: jest.fn().mockResolvedValue(undefined),
117
123
  createCommentByUrl: jest.fn().mockResolvedValue(undefined),
124
+ setIssueAgentField: jest.fn().mockResolvedValue(undefined),
125
+ removeLabel: jest.fn().mockResolvedValue(undefined),
118
126
  };
119
127
  mockLocalCommandRunner = {
120
128
  runCommand: jest.fn(),
@@ -191,6 +199,181 @@ describe('StartPreparationUseCase', () => {
191
199
  ]);
192
200
  });
193
201
 
202
+ describe('agent designation label migration to the Agent project field', () => {
203
+ const projectWithAgentField = (options: FieldOption[]): Project => ({
204
+ ...createMockProject(),
205
+ agent: { name: 'Agent', fieldId: 'agent-field-id', options },
206
+ });
207
+ const runWithAgents = async (agents: string[] | null): Promise<void> => {
208
+ await useCase.run({
209
+ projectUrl: 'https://github.com/user/repo',
210
+ defaultAgentName: 'agent1',
211
+ defaultLlmModelName: 'claude-opus',
212
+ fallbackLlmModelName: null,
213
+ defaultLlmAgentName: null,
214
+ configFilePath: '/path/to/config.yml',
215
+ maximumPreparingIssuesCount: null,
216
+ utilizationPercentageThreshold: 90,
217
+ allowedIssueAuthors: ['testuser'],
218
+ manager: 'manager-user',
219
+ codexHomeCandidates: null,
220
+ labelsAsLlmAgentName: null,
221
+ agents,
222
+ });
223
+ };
224
+ const arrangeIssue = (project: Project, labels: string[]): void => {
225
+ mockProjectRepository.getByUrl.mockResolvedValue(project);
226
+ mockIssueRepository.getStoryObjectMap.mockResolvedValue(
227
+ createMockStoryObjectMap([
228
+ createMockIssue({
229
+ url: 'url1',
230
+ title: 'Issue 1',
231
+ labels,
232
+ status: 'Awaiting Workspace',
233
+ }),
234
+ ]),
235
+ );
236
+ mockLocalCommandRunner.runCommand.mockResolvedValue({
237
+ stdout: '',
238
+ stderr: '',
239
+ exitCode: 0,
240
+ });
241
+ };
242
+
243
+ it('sets the existing Agent field option and removes the label when a label matches a configured agent definition', async () => {
244
+ const project = projectWithAgentField([
245
+ {
246
+ id: 'agent-option-impl',
247
+ name: 'impl',
248
+ color: 'GRAY',
249
+ description: '',
250
+ },
251
+ {
252
+ id: 'agent-option-chore',
253
+ name: 'chore',
254
+ color: 'GRAY',
255
+ description: '',
256
+ },
257
+ ]);
258
+ arrangeIssue(project, ['chore']);
259
+
260
+ await runWithAgents(['impl', 'chore', 'accounting']);
261
+
262
+ expect(mockProjectRepository.updateAgentList.mock.calls).toHaveLength(0);
263
+ expect(mockIssueRepository.setIssueAgentField.mock.calls).toEqual([
264
+ ['url1', project, 'agent-option-chore'],
265
+ ]);
266
+ expect(mockIssueRepository.removeLabel.mock.calls).toHaveLength(1);
267
+ expect(mockIssueRepository.removeLabel.mock.calls[0][0]).toMatchObject({
268
+ url: 'url1',
269
+ });
270
+ expect(mockIssueRepository.removeLabel.mock.calls[0][1]).toBe('chore');
271
+ expect(mockLocalCommandRunner.runCommand.mock.calls[0][1][1]).toBe(
272
+ 'chore',
273
+ );
274
+ });
275
+
276
+ it('creates the missing Agent field option before setting it on the issue', async () => {
277
+ const project = projectWithAgentField([]);
278
+ arrangeIssue(project, ['impl']);
279
+ mockProjectRepository.updateAgentList.mockResolvedValue([
280
+ {
281
+ id: 'agent-option-impl',
282
+ name: 'impl',
283
+ color: 'GRAY',
284
+ description: '',
285
+ },
286
+ ]);
287
+
288
+ await runWithAgents(['impl']);
289
+
290
+ expect(mockProjectRepository.updateAgentList.mock.calls).toHaveLength(1);
291
+ expect(mockProjectRepository.updateAgentList.mock.calls[0][1]).toEqual([
292
+ { id: null, name: 'impl', color: 'GRAY', description: '' },
293
+ ]);
294
+ expect(mockIssueRepository.setIssueAgentField.mock.calls).toEqual([
295
+ ['url1', project, 'agent-option-impl'],
296
+ ]);
297
+ expect(mockIssueRepository.removeLabel.mock.calls).toHaveLength(1);
298
+ });
299
+
300
+ it('creates the Agent field when the project has none, then sets it and removes the label', async () => {
301
+ const project = createMockProject();
302
+ arrangeIssue(project, ['chore']);
303
+ mockProjectRepository.getByUrl.mockResolvedValueOnce(project);
304
+ mockProjectRepository.getByUrl.mockResolvedValueOnce(
305
+ projectWithAgentField([
306
+ {
307
+ id: 'agent-option-chore',
308
+ name: 'chore',
309
+ color: 'GRAY',
310
+ description: '',
311
+ },
312
+ ]),
313
+ );
314
+
315
+ await runWithAgents(['chore']);
316
+
317
+ expect(mockProjectRepository.createField.mock.calls).toHaveLength(1);
318
+ expect(mockProjectRepository.createField.mock.calls[0][1]).toEqual({
319
+ name: 'Agent',
320
+ dataType: 'SINGLE_SELECT',
321
+ options: [{ name: 'chore', color: 'GRAY', description: '' }],
322
+ });
323
+ expect(mockIssueRepository.setIssueAgentField.mock.calls).toEqual([
324
+ ['url1', project, 'agent-option-chore'],
325
+ ]);
326
+ expect(mockIssueRepository.removeLabel.mock.calls).toHaveLength(1);
327
+ expect(mockLocalCommandRunner.runCommand.mock.calls[0][1][1]).toBe(
328
+ 'chore',
329
+ );
330
+ });
331
+
332
+ it('keeps the label and still uses it as the agent when the Agent field option cannot be resolved', async () => {
333
+ const project = createMockProject();
334
+ arrangeIssue(project, ['chore']);
335
+ mockProjectRepository.getByUrl.mockResolvedValue(project);
336
+
337
+ await runWithAgents(['chore']);
338
+
339
+ expect(mockIssueRepository.setIssueAgentField.mock.calls).toHaveLength(0);
340
+ expect(mockIssueRepository.removeLabel.mock.calls).toHaveLength(0);
341
+ expect(mockLocalCommandRunner.runCommand.mock.calls[0][1][1]).toBe(
342
+ 'chore',
343
+ );
344
+ });
345
+
346
+ it('leaves the labels untouched when no label matches a configured agent definition', async () => {
347
+ const project = projectWithAgentField([
348
+ {
349
+ id: 'agent-option-impl',
350
+ name: 'impl',
351
+ color: 'GRAY',
352
+ description: '',
353
+ },
354
+ ]);
355
+ arrangeIssue(project, ['category:triager']);
356
+
357
+ await runWithAgents(['impl']);
358
+
359
+ expect(mockIssueRepository.setIssueAgentField.mock.calls).toHaveLength(0);
360
+ expect(mockIssueRepository.removeLabel.mock.calls).toHaveLength(0);
361
+ expect(mockLocalCommandRunner.runCommand.mock.calls[0][1][1]).toBe(
362
+ 'triager',
363
+ );
364
+ });
365
+
366
+ it('leaves the labels untouched when no agent definition is configured', async () => {
367
+ const project = projectWithAgentField([]);
368
+ arrangeIssue(project, ['chore']);
369
+
370
+ await runWithAgents(null);
371
+
372
+ expect(mockIssueRepository.setIssueAgentField.mock.calls).toHaveLength(0);
373
+ expect(mockIssueRepository.removeLabel.mock.calls).toHaveLength(0);
374
+ });
375
+ });
376
+
194
377
  it('keeps an issue out of Preparation when the aw command exits non-zero', async () => {
195
378
  const awaitingIssues: Issue[] = [
196
379
  createMockIssue({
@@ -6349,9 +6532,11 @@ describe('StartPreparationUseCase', () => {
6349
6532
 
6350
6533
  describe('StartPreparationUseCase.buildRotationOrder', () => {
6351
6534
  const mockProjectRepositoryForRotation: Mocked<
6352
- Pick<ProjectRepository, 'getByUrl'>
6535
+ Pick<ProjectRepository, 'getByUrl' | 'createField' | 'updateAgentList'>
6353
6536
  > = {
6354
6537
  getByUrl: jest.fn(),
6538
+ createField: jest.fn(),
6539
+ updateAgentList: jest.fn(),
6355
6540
  };
6356
6541
  const mockIssueRepositoryForRotation: Mocked<
6357
6542
  Pick<
@@ -6364,6 +6549,8 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
6364
6549
  | 'closePullRequest'
6365
6550
  | 'deletePullRequestBranch'
6366
6551
  | 'createCommentByUrl'
6552
+ | 'setIssueAgentField'
6553
+ | 'removeLabel'
6367
6554
  >
6368
6555
  > = {
6369
6556
  getStoryObjectMap: jest.fn(),
@@ -6374,6 +6561,8 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
6374
6561
  closePullRequest: jest.fn(),
6375
6562
  deletePullRequestBranch: jest.fn(),
6376
6563
  createCommentByUrl: jest.fn(),
6564
+ setIssueAgentField: jest.fn(),
6565
+ removeLabel: jest.fn(),
6377
6566
  };
6378
6567
  const mockLocalCommandRunnerForRotation: Mocked<LocalCommandRunner> = {
6379
6568
  runCommand: jest.fn(),
@@ -6666,7 +6855,11 @@ describe('StartPreparationUseCase.getTokenConcurrentLimit', () => {
6666
6855
  let useCase: StartPreparationUseCase;
6667
6856
  beforeEach(() => {
6668
6857
  useCase = new StartPreparationUseCase(
6669
- { getByUrl: jest.fn() },
6858
+ {
6859
+ getByUrl: jest.fn(),
6860
+ createField: jest.fn(),
6861
+ updateAgentList: jest.fn(),
6862
+ },
6670
6863
  {
6671
6864
  getStoryObjectMap: jest.fn(),
6672
6865
  getAllOpened: jest.fn(),
@@ -6676,6 +6869,8 @@ describe('StartPreparationUseCase.getTokenConcurrentLimit', () => {
6676
6869
  closePullRequest: jest.fn(),
6677
6870
  deletePullRequestBranch: jest.fn(),
6678
6871
  createCommentByUrl: jest.fn(),
6872
+ setIssueAgentField: jest.fn(),
6873
+ removeLabel: jest.fn(),
6679
6874
  },
6680
6875
  { runCommand: jest.fn() },
6681
6876
  {
@@ -9,6 +9,9 @@ import {
9
9
  AWAITING_WORKSPACE_STATUS_NAME,
10
10
  PREPARATION_STATUS_NAME,
11
11
  } from '../entities/WorkflowStatus';
12
+ import { ensureAgentOptionAndGetId } from './ensureAgentOptionAndGetId';
13
+ import { Issue } from '../entities/Issue';
14
+ import { Project } from '../entities/Project';
12
15
 
13
16
  const NORMAL_CONCURRENT_LIMIT = 6;
14
17
  const SEVEN_DAY_THROTTLE_START_THRESHOLD = 0.8;
@@ -32,7 +35,10 @@ export type RotationOrderEntry = {
32
35
 
33
36
  export class StartPreparationUseCase {
34
37
  constructor(
35
- private readonly projectRepository: Pick<ProjectRepository, 'getByUrl'>,
38
+ private readonly projectRepository: Pick<
39
+ ProjectRepository,
40
+ 'getByUrl' | 'createField' | 'updateAgentList'
41
+ >,
36
42
  private readonly issueRepository: Pick<
37
43
  IssueRepository,
38
44
  | 'getStoryObjectMap'
@@ -43,6 +49,8 @@ export class StartPreparationUseCase {
43
49
  | 'closePullRequest'
44
50
  | 'deletePullRequestBranch'
45
51
  | 'createCommentByUrl'
52
+ | 'setIssueAgentField'
53
+ | 'removeLabel'
46
54
  >,
47
55
  private readonly localCommandRunner: LocalCommandRunner,
48
56
  private readonly claudeTokenUsageRepository: ClaudeTokenUsageRepository,
@@ -302,6 +310,41 @@ export class StartPreparationUseCase {
302
310
  return [...selectedEntries, ...excluded];
303
311
  };
304
312
 
313
+ private migrateAgentDesignationLabelToProjectField = async (
314
+ issue: Issue,
315
+ project: Project,
316
+ configuredAgentNames: string[] | null,
317
+ ): Promise<void> => {
318
+ const agentLabel =
319
+ configuredAgentNames === null
320
+ ? undefined
321
+ : issue.labels.find((label: string) =>
322
+ configuredAgentNames.includes(label),
323
+ );
324
+ if (agentLabel === undefined) {
325
+ return;
326
+ }
327
+ issue.agent = agentLabel;
328
+ const agentOptionId = await ensureAgentOptionAndGetId(
329
+ this.projectRepository,
330
+ project,
331
+ agentLabel,
332
+ );
333
+ if (agentOptionId === null) {
334
+ console.warn(
335
+ `Agent field option '${agentLabel}' could not be resolved for ${issue.url}. Keeping the label as the agent designation.`,
336
+ );
337
+ return;
338
+ }
339
+ await this.issueRepository.setIssueAgentField(
340
+ issue.url,
341
+ project,
342
+ agentOptionId,
343
+ );
344
+ await this.issueRepository.removeLabel(issue, agentLabel);
345
+ issue.labels = issue.labels.filter((label) => label !== agentLabel);
346
+ };
347
+
305
348
  run = async (params: {
306
349
  projectUrl: string;
307
350
  defaultAgentName: string;
@@ -315,6 +358,7 @@ export class StartPreparationUseCase {
315
358
  manager: string;
316
359
  codexHomeCandidates: string[] | null;
317
360
  labelsAsLlmAgentName: string[] | null;
361
+ agents?: string[] | null;
318
362
  }): Promise<{ rotationOrder: RotationOrderEntry[] | null }> => {
319
363
  const tokenUsages =
320
364
  await this.claudeTokenUsageRepository.getAvailableTokenUsages();
@@ -476,6 +520,11 @@ export class StartPreparationUseCase {
476
520
  exclusionCounts.notAssignedToManager++;
477
521
  continue;
478
522
  }
523
+ await this.migrateAgentDesignationLabelToProjectField(
524
+ issue,
525
+ project,
526
+ params.agents ?? null,
527
+ );
479
528
  const mappedAgentFromLabel =
480
529
  params.labelsAsLlmAgentName !== null
481
530
  ? issue.labels.find((label: string) =>
@@ -616,6 +616,19 @@ describe('GenerateConsoleListsUseCase', () => {
616
616
  'second',
617
617
  ]);
618
618
  });
619
+
620
+ it('groups items of different unknown stories contiguously even when interleaved by original position', () => {
621
+ const result = run([
622
+ makeIssue({ status: 'Unread', story: 'Unknown Story A' }),
623
+ makeIssue({ status: 'Unread', story: 'Unknown Story B' }),
624
+ makeIssue({ status: 'Unread', story: 'Unknown Story A' }),
625
+ ]);
626
+ expect(result.unread.items.map((i) => i.story)).toEqual([
627
+ 'Unknown Story A',
628
+ 'Unknown Story A',
629
+ 'Unknown Story B',
630
+ ]);
631
+ });
619
632
  });
620
633
 
621
634
  describe('options construction', () => {
@@ -364,7 +364,12 @@ export class GenerateConsoleListsUseCase {
364
364
  position,
365
365
  sortKey: indexByStory.get(item.story) ?? UNKNOWN_STORY_SORT_INDEX,
366
366
  }))
367
- .sort((a, b) => a.sortKey - b.sortKey || a.position - b.position)
367
+ .sort((a, b) => {
368
+ if (a.sortKey !== b.sortKey) return a.sortKey - b.sortKey;
369
+ if (a.item.story !== b.item.story)
370
+ return a.item.story.localeCompare(b.item.story);
371
+ return a.position - b.position;
372
+ })
368
373
  .map((entry) => entry.item);
369
374
  };
370
375
  }
@@ -0,0 +1,47 @@
1
+ import { FieldOption, Project } from '../entities/Project';
2
+ import { normalizeProjectFieldName } from '../entities/ProjectFieldName';
3
+ import { AGENT_FIELD_NAME } from '../entities/RequiredProjectField';
4
+ import { ProjectRepository } from './adapter-interfaces/ProjectRepository';
5
+
6
+ export const ensureAgentOptionAndGetId = async (
7
+ projectRepository: Pick<
8
+ ProjectRepository,
9
+ 'createField' | 'getByUrl' | 'updateAgentList'
10
+ >,
11
+ project: Project,
12
+ agentName: string,
13
+ ): Promise<string | null> => {
14
+ const normalizedTarget = normalizeProjectFieldName(agentName);
15
+ if (!project.agent) {
16
+ await projectRepository.createField(project, {
17
+ name: AGENT_FIELD_NAME,
18
+ dataType: 'SINGLE_SELECT',
19
+ options: [{ name: agentName, color: 'GRAY' as const, description: '' }],
20
+ });
21
+ const refreshed = await projectRepository.getByUrl(project.url);
22
+ const created = refreshed.agent?.options.find(
23
+ (option) => normalizeProjectFieldName(option.name) === normalizedTarget,
24
+ );
25
+ return created?.id ?? null;
26
+ }
27
+ const existing = project.agent.options.find(
28
+ (option) => normalizeProjectFieldName(option.name) === normalizedTarget,
29
+ );
30
+ if (existing) {
31
+ return existing.id;
32
+ }
33
+ const mergedOptions: (Omit<FieldOption, 'id'> & {
34
+ id: FieldOption['id'] | null;
35
+ })[] = [
36
+ ...project.agent.options.map((option) => ({ ...option })),
37
+ { id: null, name: agentName, color: 'GRAY' as const, description: '' },
38
+ ];
39
+ const updatedOptions = await projectRepository.updateAgentList(
40
+ project,
41
+ mergedOptions,
42
+ );
43
+ const created = updatedOptions.find(
44
+ (option) => normalizeProjectFieldName(option.name) === normalizedTarget,
45
+ );
46
+ return created?.id ?? null;
47
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,UAAU,EACV,cAAc,EACd,wBAAwB,EACxB,YAAY,EACZ,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AA8LzB,eAAO,MAAM,OAAO,SAAgB,CAAC;AA6gCrC,eAAO,MAAM,uBAAuB,GAAI,OAAO,OAAO,KAAG,IAGxD,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EAAE,EACd,kBAAkB,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,KACzC,OAAO,CAAC,IAAI,CAMd,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,UAAU,EACV,cAAc,EACd,wBAAwB,EACxB,YAAY,EACZ,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AA8LzB,eAAO,MAAM,OAAO,SAAgB,CAAC;AA8gCrC,eAAO,MAAM,uBAAuB,GAAI,OAAO,OAAO,KAAG,IAGxD,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EAAE,EACd,kBAAkB,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,KACzC,OAAO,CAAC,IAAI,CAMd,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"HandleScheduledEventUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/HandleScheduledEventUseCase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"HandleScheduledEventUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/HandleScheduledEventUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AACnF,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,wCAAwC,EAAE,MAAM,4CAA4C,CAAC;AACtG,OAAO,EAAE,kCAAkC,EAAE,MAAM,sCAAsC,CAAC;AAC1F,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,wCAAwC,EAAE,MAAM,4CAA4C,CAAC;AACtG,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,yCAAyC,EAAE,MAAM,6CAA6C,CAAC;AACxG,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAC;AAChG,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACxB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAC;AAGhG,OAAO,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AACxF,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,4BAA4B,CAAC;AAEpC,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAuED,qBAAa,2BAA2B;IAEpC,QAAQ,CAAC,iCAAiC,EAAE,iCAAiC;IAC7E,QAAQ,CAAC,+BAA+B,EAAE,+BAA+B;IACzE,QAAQ,CAAC,yBAAyB,EAAE,yBAAyB;IAC7D,QAAQ,CAAC,wCAAwC,EAAE,wCAAwC;IAC3F,QAAQ,CAAC,0BAA0B,EAAE,kCAAkC;IACvE,QAAQ,CAAC,4BAA4B,EAAE,4BAA4B;IACnE,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB;IACrD,QAAQ,CAAC,4BAA4B,EAAE,4BAA4B;IACnE,QAAQ,CAAC,wCAAwC,EAAE,wCAAwC;IAC3F,QAAQ,CAAC,gCAAgC,EAAE,gCAAgC;IAC3E,QAAQ,CAAC,4BAA4B,EAAE,4BAA4B;IACnE,QAAQ,CAAC,yCAAyC,EAAE,yCAAyC;IAC7F,QAAQ,CAAC,+BAA+B,EAAE,+BAA+B;IACzE,QAAQ,CAAC,6BAA6B,EAAE,6BAA6B;IACrE,QAAQ,CAAC,4BAA4B,EAAE,4BAA4B;IACnE,QAAQ,CAAC,qCAAqC,EAAE,qCAAqC;IACrF,QAAQ,CAAC,+BAA+B,EAAE,+BAA+B;IACzE,QAAQ,CAAC,uBAAuB,EAAE,uBAAuB;IACzD,QAAQ,CAAC,gCAAgC,EAAE,gCAAgC;IAC3E,QAAQ,CAAC,qCAAqC,EAAE,qCAAqC;IACrF,QAAQ,CAAC,2BAA2B,EAAE,2BAA2B,GAAG,IAAI;IACxE,QAAQ,CAAC,wBAAwB,EAAE,wBAAwB,GAAG,IAAI;IAClE,QAAQ,CAAC,cAAc,EAAE,cAAc;IACvC,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB;IACrD,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB;IAC7C,QAAQ,CAAC,eAAe,EAAE,eAAe;gBAzBhC,iCAAiC,EAAE,iCAAiC,EACpE,+BAA+B,EAAE,+BAA+B,EAChE,yBAAyB,EAAE,yBAAyB,EACpD,wCAAwC,EAAE,wCAAwC,EAClF,0BAA0B,EAAE,kCAAkC,EAC9D,4BAA4B,EAAE,4BAA4B,EAC1D,qBAAqB,EAAE,qBAAqB,EAC5C,4BAA4B,EAAE,4BAA4B,EAC1D,wCAAwC,EAAE,wCAAwC,EAClF,gCAAgC,EAAE,gCAAgC,EAClE,4BAA4B,EAAE,4BAA4B,EAC1D,yCAAyC,EAAE,yCAAyC,EACpF,+BAA+B,EAAE,+BAA+B,EAChE,6BAA6B,EAAE,6BAA6B,EAC5D,4BAA4B,EAAE,4BAA4B,EAC1D,qCAAqC,EAAE,qCAAqC,EAC5E,+BAA+B,EAAE,+BAA+B,EAChE,uBAAuB,EAAE,uBAAuB,EAChD,gCAAgC,EAAE,gCAAgC,EAClE,qCAAqC,EAAE,qCAAqC,EAC5E,2BAA2B,EAAE,2BAA2B,GAAG,IAAI,EAC/D,wBAAwB,EAAE,wBAAwB,GAAG,IAAI,EACzD,cAAc,EAAE,cAAc,EAC9B,qBAAqB,EAAE,qBAAqB,EAC5C,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,eAAe;IAG3C,GAAG,GAAU,OAAO;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,aAAa,EAAE;YACb,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,cAAc,EAAE,MAAM,CAAC;SACxB,CAAC;QACF,cAAc,EAAE,MAAM,CAAC;QACvB,QAAQ,EAAE,OAAO,CAAC;QAClB,oBAAoB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACvC,6BAA6B,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAChD,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;QACxD,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACtC,wBAAwB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAC3C,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACzB,gBAAgB,CAAC,EAAE;YACjB,gBAAgB,EAAE,MAAM,CAAC;YACzB,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;YACpC,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;YACrC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;YACpC,cAAc,EAAE,MAAM,CAAC;YACvB,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;YAC3C,8BAA8B,CAAC,EAAE,MAAM,CAAC;YACxC,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;YACtC,8BAA8B,CAAC,EAAE,MAAM,CAAC;YACxC,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;YACtC,kBAAkB,CAAC,EAAE,MAAM,CAAC;YAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;YACpC,0BAA0B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;YAC3C,oBAAoB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;SACxC,GAAG,IAAI,CAAC;QACT,sBAAsB,CAAC,EAAE,MAAM,CAAC;QAChC,sCAAsC,CAAC,EAAE,OAAO,CAAC;QACjD,wBAAwB,CAAC,EAAE,OAAO,CAAC;QACnC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAClC,2BAA2B,CAAC,EAAE,OAAO,CAAC;QACtC,iBAAiB,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;KACpD,KAAG,OAAO,CAAC;QACV,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,IAAI,EAAE,CAAC;QACxB,WAAW,EAAE,cAAc,CAAC;QAC5B,aAAa,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAC;KAC5C,GAAG,IAAI,CAAC,CA+LP;IACF,eAAe,GACb,OAAO,UAAU,CAAC,2BAA2B,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EACxD,SAAS,OAAO,EAChB,QAAQ,KAAK,EAAE,EACf,WAAW,OAAO,EAClB,iBAAiB,IAAI,EAAE,EACvB,gBAAgB,cAAc,EAC9B,cAAc,OAAO,KACpB,OAAO,CAAC;QAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAA;KAAE,CAAC,CAsFxD;IACF,oBAAoB,GAClB,OAAO,UAAU,CAAC,2BAA2B,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EACxD,SAAS,OAAO,EAChB,QAAQ,KAAK,EAAE,EACf,WAAW,OAAO,EAClB,iBAAiB,IAAI,EAAE,EACvB,gBAAgB,cAAc,KAC7B,OAAO,CAAC,IAAI,CAAC,CAmGd;IACF,MAAM,CAAC,qBAAqB,GAAI,MAAM,IAAI,EAAE,IAAI,IAAI,KAAG,IAAI,EAAE,CAoB3D;IACF,uBAAuB,GAAU,CAAC,EAChC,WAAW,MAAM,GAAG,OAAO,EAC3B,gBAAgB,MAAM,EACtB,KAAK,MAAM,EACX,MAAM,MAAM,EACZ,SAAS,MAAM,CAAC,MAAM,CAAC,EACvB,QAAQ,MAAM,OAAO,CAAC,CAAC,CAAC,KACvB,OAAO,CAAC,CAAC,CAAC,CAkCX;IACF,4CAA4C,GAC1C,gBAAgB,MAAM,EACtB,KAAK,IAAI,EACT,KAAK,MAAM,EACX,MAAM,MAAM,EACZ,SAAS,MAAM,CAAC,MAAM,CAAC,KACtB,OAAO,CAAC,IAAI,EAAE,CAAC,CA4DhB;IACF,kBAAkB,GAChB,gBAAgB,MAAM,EACtB,KAAK,IAAI,EACT,KAAK,MAAM,EACX,MAAM,MAAM,EACZ,SAAS,MAAM,CAAC,MAAM,CAAC,KACtB,OAAO,CAAC,OAAO,CAAC,CAsDjB;IACF,WAAW,GAAU,OAAO;QAC1B,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;KACjB,KAAG,OAAO,CAAC,cAAc,CAAC,CAoBzB;CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"NotifyFinishedIssuePreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AA2BnF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,QAAQ,EAAE,MAAM;CAI7B;AACD,qBAAa,uBAAwB,SAAQ,KAAK;gBAE9C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,cAAc,EAAE,MAAM,GAAG,IAAI;CAOhC;AAID,qBAAa,qCAAqC;IAK9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAIlC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAgBhC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IAIvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAIlC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IAhCzC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA0B;IAClE,OAAO,CAAC,QAAQ,CAAC,+BAA+B,CAAkC;gBAG/D,iBAAiB,EAAE,IAAI,CACtC,iBAAiB,EACjB,UAAU,GAAG,iBAAiB,GAAG,aAAa,CAC/C,EACgB,eAAe,EAAE,IAAI,CACpC,eAAe,EACb,KAAK,GACL,QAAQ,GACR,cAAc,GACd,cAAc,GACd,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,GACnB,oBAAoB,GACpB,gCAAgC,GAChC,oBAAoB,GACpB,iCAAiC,GACjC,qBAAqB,GACrB,oBAAoB,CACvB,EACgB,sBAAsB,EAAE,IAAI,CAC3C,sBAAsB,EACtB,sBAAsB,GAAG,eAAe,CACzC,EACgB,iBAAiB,EAAE,IAAI,CACtC,iBAAiB,EACjB,gBAAgB,CACjB,EACgB,qBAAqB,CAAC,GAAE,qBAAqB,GAAG,IAAI,aAAA;IAQvE,GAAG,GAAU,QAAQ;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,iCAAiC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjD,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACtC,oBAAoB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACvC,6BAA6B,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAChD,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;QACxD,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;KAC1B,KAAG,OAAO,CAAC,IAAI,CAAC,CAkRf;IAEF,OAAO,CAAC,eAAe,CAIgD;IAEvE,OAAO,CAAC,iBAAiB,CAkDvB;IAEF,OAAO,CAAC,qBAAqB,CAuB3B;IAEF,OAAO,CAAC,gCAAgC,CAoBtC;IAEF,OAAO,CAAC,uBAAuB,CAQ7B;IAEF,OAAO,CAAC,+BAA+B,CAgCrC;IAEF,OAAO,CAAC,uBAAuB,CAO7B;IAEF,OAAO,CAAC,oBAAoB,CA0B1B;IAEF,OAAO,CAAC,yBAAyB,CAqC/B;IAEF,OAAO,CAAC,eAAe,CAmCrB;CACH"}
1
+ {"version":3,"file":"NotifyFinishedIssuePreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AA0BnF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,QAAQ,EAAE,MAAM;CAI7B;AACD,qBAAa,uBAAwB,SAAQ,KAAK;gBAE9C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,cAAc,EAAE,MAAM,GAAG,IAAI;CAOhC;AAID,qBAAa,qCAAqC;IAK9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAIlC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAgBhC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IAIvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAIlC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IAhCzC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA0B;IAClE,OAAO,CAAC,QAAQ,CAAC,+BAA+B,CAAkC;gBAG/D,iBAAiB,EAAE,IAAI,CACtC,iBAAiB,EACjB,UAAU,GAAG,iBAAiB,GAAG,aAAa,CAC/C,EACgB,eAAe,EAAE,IAAI,CACpC,eAAe,EACb,KAAK,GACL,QAAQ,GACR,cAAc,GACd,cAAc,GACd,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,GACnB,oBAAoB,GACpB,gCAAgC,GAChC,oBAAoB,GACpB,iCAAiC,GACjC,qBAAqB,GACrB,oBAAoB,CACvB,EACgB,sBAAsB,EAAE,IAAI,CAC3C,sBAAsB,EACtB,sBAAsB,GAAG,eAAe,CACzC,EACgB,iBAAiB,EAAE,IAAI,CACtC,iBAAiB,EACjB,gBAAgB,CACjB,EACgB,qBAAqB,CAAC,GAAE,qBAAqB,GAAG,IAAI,aAAA;IAQvE,GAAG,GAAU,QAAQ;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,iCAAiC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjD,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACtC,oBAAoB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACvC,6BAA6B,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAChD,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;QACxD,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;KAC1B,KAAG,OAAO,CAAC,IAAI,CAAC,CAkRf;IAEF,OAAO,CAAC,eAAe,CAIgD;IAEvE,OAAO,CAAC,iBAAiB,CAkDvB;IAEF,OAAO,CAAC,qBAAqB,CAuB3B;IAEF,OAAO,CAAC,gCAAgC,CAoBtC;IAEF,OAAO,CAAC,uBAAuB,CAQ7B;IAEF,OAAO,CAAC,+BAA+B,CAgCrC;IAEF,OAAO,CAAC,uBAAuB,CAO7B;IAEF,OAAO,CAAC,oBAAoB,CA0B1B;IAEF,OAAO,CAAC,yBAAyB,CAIuC;IAExE,OAAO,CAAC,eAAe,CAmCrB;CACH"}
@@ -20,7 +20,7 @@ export declare class StartPreparationUseCase {
20
20
  private readonly localCommandRunner;
21
21
  private readonly claudeTokenUsageRepository;
22
22
  private readonly takeOwnershipSpawnRepository;
23
- constructor(projectRepository: Pick<ProjectRepository, 'getByUrl'>, issueRepository: Pick<IssueRepository, 'getStoryObjectMap' | 'getAllOpened' | 'updateStatus' | 'findRelatedOpenPRs' | 'getOpenPullRequest' | 'closePullRequest' | 'deletePullRequestBranch' | 'createCommentByUrl'>, localCommandRunner: LocalCommandRunner, claudeTokenUsageRepository: ClaudeTokenUsageRepository, takeOwnershipSpawnRepository: TakeOwnershipSpawnRepository);
23
+ constructor(projectRepository: Pick<ProjectRepository, 'getByUrl' | 'createField' | 'updateAgentList'>, issueRepository: Pick<IssueRepository, 'getStoryObjectMap' | 'getAllOpened' | 'updateStatus' | 'findRelatedOpenPRs' | 'getOpenPullRequest' | 'closePullRequest' | 'deletePullRequestBranch' | 'createCommentByUrl' | 'setIssueAgentField' | 'removeLabel'>, localCommandRunner: LocalCommandRunner, claudeTokenUsageRepository: ClaudeTokenUsageRepository, takeOwnershipSpawnRepository: TakeOwnershipSpawnRepository);
24
24
  private weeklyLimitTypeForModel;
25
25
  private isWithinCooldown;
26
26
  private isModelWeeklyLimitRejected;
@@ -31,6 +31,7 @@ export declare class StartPreparationUseCase {
31
31
  getTokenConcurrentLimit: (fiveHourUtilization: number, sevenDayUtilization: number, selectionWeight?: number) => number;
32
32
  private selectRotationTokens;
33
33
  buildRotationOrder: (tokenUsages: ClaudeTokenUsage[], utilizationPercentageThreshold: number, modelName: string | null) => RotationOrderEntry[];
34
+ private migrateAgentDesignationLabelToProjectField;
34
35
  run: (params: {
35
36
  projectUrl: string;
36
37
  defaultAgentName: string;
@@ -44,6 +45,7 @@ export declare class StartPreparationUseCase {
44
45
  manager: string;
45
46
  codexHomeCandidates: string[] | null;
46
47
  labelsAsLlmAgentName: string[] | null;
48
+ agents?: string[] | null;
47
49
  }) => Promise<{
48
50
  rotationOrder: RotationOrderEntry[] | null;
49
51
  }>;