github-issue-tower-defence-management 1.184.1 → 1.185.1
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 +14 -0
- package/bin/adapter/entry-points/cli/index.js +31 -29
- package/bin/adapter/entry-points/cli/index.js.map +1 -1
- package/bin/adapter/entry-points/console/consoleOperationApi.js +26 -2
- package/bin/adapter/entry-points/console/consoleOperationApi.js.map +1 -1
- package/bin/adapter/entry-points/console/consoleProjectResolver.js +5 -1
- package/bin/adapter/entry-points/console/consoleProjectResolver.js.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-DQT4HL0G.js +86 -0
- package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/bin/adapter/entry-points/console/webServer.js +4 -0
- package/bin/adapter/entry-points/console/webServer.js.map +1 -1
- package/bin/adapter/repositories/ProcClaudeHandoverSessionRepository.js +40 -3
- package/bin/adapter/repositories/ProcClaudeHandoverSessionRepository.js.map +1 -1
- package/bin/domain/entities/Project.js +17 -0
- package/bin/domain/entities/Project.js.map +1 -1
- package/bin/domain/usecases/CreateNewStoryByLabelUseCase.js +5 -16
- package/bin/domain/usecases/CreateNewStoryByLabelUseCase.js.map +1 -1
- package/bin/domain/usecases/TokenExhaustionHandoverUseCase.js +9 -1
- package/bin/domain/usecases/TokenExhaustionHandoverUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/cli/index.ts +57 -52
- package/src/adapter/entry-points/console/consoleOperationApi.test.ts +242 -12
- package/src/adapter/entry-points/console/consoleOperationApi.ts +43 -7
- package/src/adapter/entry-points/console/consoleProjectResolver.test.ts +30 -10
- package/src/adapter/entry-points/console/consoleProjectResolver.ts +13 -2
- package/src/adapter/entry-points/console/ui/e2e/consoleScenario.spec.ts +37 -2
- package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +20 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStoryList.stories.tsx +4 -1
- package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStoryList.test.tsx +127 -8
- package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStoryList.tsx +119 -71
- package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.test.ts +26 -0
- package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.ts +20 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +12 -0
- package/src/adapter/entry-points/console/ui-dist/assets/index-DQT4HL0G.js +86 -0
- package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/src/adapter/entry-points/console/webServer.test.ts +74 -0
- package/src/adapter/entry-points/console/webServer.ts +8 -0
- package/src/adapter/repositories/ProcClaudeHandoverSessionRepository.test.ts +48 -0
- package/src/adapter/repositories/ProcClaudeHandoverSessionRepository.ts +55 -2
- package/src/domain/entities/ClaudeHandoverSession.ts +1 -0
- package/src/domain/entities/Project.ts +23 -0
- package/src/domain/usecases/CreateNewStoryByLabelUseCase.ts +16 -34
- package/src/domain/usecases/TokenExhaustionHandoverUseCase.test.ts +59 -1
- package/src/domain/usecases/TokenExhaustionHandoverUseCase.ts +14 -1
- package/types/adapter/entry-points/cli/index.d.ts +1 -1
- package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
- package/types/adapter/entry-points/console/consoleOperationApi.d.ts +8 -3
- package/types/adapter/entry-points/console/consoleOperationApi.d.ts.map +1 -1
- package/types/adapter/entry-points/console/consoleProjectResolver.d.ts +5 -1
- package/types/adapter/entry-points/console/consoleProjectResolver.d.ts.map +1 -1
- package/types/adapter/entry-points/console/webServer.d.ts +3 -1
- package/types/adapter/entry-points/console/webServer.d.ts.map +1 -1
- package/types/adapter/repositories/ProcClaudeHandoverSessionRepository.d.ts +1 -0
- package/types/adapter/repositories/ProcClaudeHandoverSessionRepository.d.ts.map +1 -1
- package/types/domain/entities/ClaudeHandoverSession.d.ts +1 -0
- package/types/domain/entities/ClaudeHandoverSession.d.ts.map +1 -1
- package/types/domain/entities/Project.d.ts +4 -0
- package/types/domain/entities/Project.d.ts.map +1 -1
- package/types/domain/usecases/CreateNewStoryByLabelUseCase.d.ts +6 -8
- package/types/domain/usecases/CreateNewStoryByLabelUseCase.d.ts.map +1 -1
- package/types/domain/usecases/TokenExhaustionHandoverUseCase.d.ts +1 -0
- package/types/domain/usecases/TokenExhaustionHandoverUseCase.d.ts.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-CMrnEYO1.js +0 -86
- package/src/adapter/entry-points/console/ui-dist/assets/index-CMrnEYO1.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-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-DQT4HL0G.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-8Ni5iu-C.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
@@ -1107,6 +1107,80 @@ describe('webServer new routes integration', () => {
|
|
|
1107
1107
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
1108
1108
|
}
|
|
1109
1109
|
});
|
|
1110
|
+
|
|
1111
|
+
it('routes POST /api/addstory to handleStoryAdd and calls updateStoryList', async () => {
|
|
1112
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'console-server-'));
|
|
1113
|
+
const updateStoryList = jest.fn().mockResolvedValue([]);
|
|
1114
|
+
const projectWithStory: Project = {
|
|
1115
|
+
...mock<Project>(),
|
|
1116
|
+
id: 'PVT_1',
|
|
1117
|
+
url: 'https://github.com/orgs/acme-labs/projects/1',
|
|
1118
|
+
status: {
|
|
1119
|
+
name: 'Status',
|
|
1120
|
+
fieldId: 'statusField',
|
|
1121
|
+
statuses: [
|
|
1122
|
+
{
|
|
1123
|
+
id: 'status_aw',
|
|
1124
|
+
name: 'Awaiting workspace',
|
|
1125
|
+
color: 'GRAY',
|
|
1126
|
+
description: '',
|
|
1127
|
+
},
|
|
1128
|
+
],
|
|
1129
|
+
},
|
|
1130
|
+
story: {
|
|
1131
|
+
name: 'Story',
|
|
1132
|
+
fieldId: 'storyField',
|
|
1133
|
+
databaseId: 1,
|
|
1134
|
+
stories: [
|
|
1135
|
+
{
|
|
1136
|
+
id: 'opt_blue',
|
|
1137
|
+
name: 'Existing story',
|
|
1138
|
+
color: 'BLUE',
|
|
1139
|
+
description: '',
|
|
1140
|
+
},
|
|
1141
|
+
],
|
|
1142
|
+
workflowManagementStory: { id: 'wms', name: 'workflow' },
|
|
1143
|
+
},
|
|
1144
|
+
};
|
|
1145
|
+
const issueRepository = mock<IssueRepository>();
|
|
1146
|
+
const server = await startWebServer({
|
|
1147
|
+
accessToken: testToken,
|
|
1148
|
+
uiDistDir: path.join(tmpDir, 'ui-dist'),
|
|
1149
|
+
consoleDataOutputDir: null,
|
|
1150
|
+
inTmuxDataDir: null,
|
|
1151
|
+
dashboardDir: null,
|
|
1152
|
+
dashboardDataDir: null,
|
|
1153
|
+
dashboardProjectNames: [],
|
|
1154
|
+
issueRepository,
|
|
1155
|
+
resolveProject: async (pjcode) =>
|
|
1156
|
+
pjcode === 'acme' ? { pjcode, project: projectWithStory } : null,
|
|
1157
|
+
isPjcodeConfigured: (pjcode) => pjcode === 'acme',
|
|
1158
|
+
resolveProjectRepository: () => ({ updateStoryList }),
|
|
1159
|
+
port: 0,
|
|
1160
|
+
});
|
|
1161
|
+
try {
|
|
1162
|
+
const response = await request(
|
|
1163
|
+
server,
|
|
1164
|
+
'POST',
|
|
1165
|
+
`/api/addstory?k=${testToken}`,
|
|
1166
|
+
{ pjcode: 'acme', storyName: 'My new story' },
|
|
1167
|
+
);
|
|
1168
|
+
expect(response.statusCode).toBe(200);
|
|
1169
|
+
expect(JSON.parse(response.body)).toEqual({ ok: true });
|
|
1170
|
+
expect(updateStoryList).toHaveBeenCalledWith(projectWithStory, [
|
|
1171
|
+
{
|
|
1172
|
+
id: 'opt_blue',
|
|
1173
|
+
name: 'Existing story',
|
|
1174
|
+
color: 'BLUE',
|
|
1175
|
+
description: '',
|
|
1176
|
+
},
|
|
1177
|
+
{ id: null, name: 'My new story', color: 'RED', description: '' },
|
|
1178
|
+
]);
|
|
1179
|
+
} finally {
|
|
1180
|
+
await closeServer(server);
|
|
1181
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
1182
|
+
}
|
|
1183
|
+
});
|
|
1110
1184
|
});
|
|
1111
1185
|
|
|
1112
1186
|
describe('resolveFlatInTmuxFilePath', () => {
|
|
@@ -24,7 +24,9 @@ import {
|
|
|
24
24
|
ConsoleIssueRepositoryResolver,
|
|
25
25
|
ConsoleOperationContext,
|
|
26
26
|
ConsolePjcodeValidator,
|
|
27
|
+
ConsoleProjectRepositoryResolver,
|
|
27
28
|
ConsoleProjectResolver,
|
|
29
|
+
handleStoryAdd,
|
|
28
30
|
handleAttachmentUpload,
|
|
29
31
|
handleComment,
|
|
30
32
|
handleCreateIssue,
|
|
@@ -233,6 +235,8 @@ export type WebServerOptions = {
|
|
|
233
235
|
resolveIssueRepository?: ConsoleIssueRepositoryResolver | null;
|
|
234
236
|
resolveProject?: ConsoleProjectResolver | null;
|
|
235
237
|
isPjcodeConfigured?: ConsolePjcodeValidator | null;
|
|
238
|
+
resolveProjectRepository?: ConsoleProjectRepositoryResolver | null;
|
|
239
|
+
invalidateProject?: ((pjcode: string) => void) | null;
|
|
236
240
|
issueAttachmentRepository?: IssueAttachmentRepository | null;
|
|
237
241
|
projectRepository?: Pick<ProjectRepository, 'updateStoryList'> | null;
|
|
238
242
|
issueTitleStateCache?: IssueTitleStateCache | null;
|
|
@@ -540,6 +544,8 @@ const dispatchOperation = (
|
|
|
540
544
|
return handleCreateIssue(context, body);
|
|
541
545
|
case '/api/reorderstory':
|
|
542
546
|
return handleReorderStory(context, body);
|
|
547
|
+
case '/api/addstory':
|
|
548
|
+
return handleStoryAdd(context, body);
|
|
543
549
|
default:
|
|
544
550
|
return null;
|
|
545
551
|
}
|
|
@@ -574,6 +580,8 @@ const handleOperationApi = async (
|
|
|
574
580
|
? (project, stories) =>
|
|
575
581
|
projectRepository.updateStoryList(project, stories)
|
|
576
582
|
: null,
|
|
583
|
+
resolveProjectRepository: options.resolveProjectRepository ?? null,
|
|
584
|
+
invalidateProject: options.invalidateProject ?? null,
|
|
577
585
|
};
|
|
578
586
|
const dispatched = dispatchOperation(context, requestPath, body);
|
|
579
587
|
if (dispatched === null) {
|
|
@@ -8,6 +8,7 @@ type FakeProcess = {
|
|
|
8
8
|
comm: string;
|
|
9
9
|
cmdline: string;
|
|
10
10
|
environ: Record<string, string>;
|
|
11
|
+
cgroup?: string;
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
const issueUrl = 'https://github.com/HiromiShikata/example/issues/1';
|
|
@@ -41,6 +42,12 @@ describe('ProcClaudeHandoverSessionRepository', () => {
|
|
|
41
42
|
.map(([key, value]) => `${key}=${value}\0`)
|
|
42
43
|
.join('');
|
|
43
44
|
fs.writeFileSync(path.join(processDirectory, 'environ'), environBuffer);
|
|
45
|
+
if (fakeProcess.cgroup !== undefined) {
|
|
46
|
+
fs.writeFileSync(
|
|
47
|
+
path.join(processDirectory, 'cgroup'),
|
|
48
|
+
`0::${fakeProcess.cgroup}\n`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
44
51
|
};
|
|
45
52
|
|
|
46
53
|
it('classifies an issue-URL leader from a cl --name url launch', () => {
|
|
@@ -61,6 +68,7 @@ describe('ProcClaudeHandoverSessionRepository', () => {
|
|
|
61
68
|
sessionName: issueUrl.replace(/[.:]/g, '_'),
|
|
62
69
|
name: issueUrl,
|
|
63
70
|
issueUrl,
|
|
71
|
+
runsUnderWorkspacePreparationScript: false,
|
|
64
72
|
},
|
|
65
73
|
]);
|
|
66
74
|
});
|
|
@@ -83,6 +91,7 @@ describe('ProcClaudeHandoverSessionRepository', () => {
|
|
|
83
91
|
sessionName: 'app',
|
|
84
92
|
name: 'app',
|
|
85
93
|
issueUrl: null,
|
|
94
|
+
runsUnderWorkspacePreparationScript: false,
|
|
86
95
|
},
|
|
87
96
|
]);
|
|
88
97
|
});
|
|
@@ -110,6 +119,7 @@ describe('ProcClaudeHandoverSessionRepository', () => {
|
|
|
110
119
|
sessionName: null,
|
|
111
120
|
name: null,
|
|
112
121
|
issueUrl,
|
|
122
|
+
runsUnderWorkspacePreparationScript: false,
|
|
113
123
|
},
|
|
114
124
|
]);
|
|
115
125
|
});
|
|
@@ -184,6 +194,44 @@ describe('ProcClaudeHandoverSessionRepository', () => {
|
|
|
184
194
|
});
|
|
185
195
|
});
|
|
186
196
|
|
|
197
|
+
it('marks a session whose cgroup scope is an aw scope as launched by the workspace preparation script', () => {
|
|
198
|
+
writeProcess({
|
|
199
|
+
pid: 209,
|
|
200
|
+
comm: 'claude',
|
|
201
|
+
cmdline: argv(
|
|
202
|
+
'claude',
|
|
203
|
+
'-p',
|
|
204
|
+
`Take ownership of ${issueUrl} and finish it`,
|
|
205
|
+
),
|
|
206
|
+
environ: { CLAUDE_CODE_OAUTH_TOKEN: 'token-h' },
|
|
207
|
+
cgroup:
|
|
208
|
+
'/user.slice/user-1000.slice/user@1000.service/aiagents.slice/aw-HiromiShikata-example-1-4005530.scope',
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const repository = new ProcClaudeHandoverSessionRepository(procDirectory);
|
|
212
|
+
|
|
213
|
+
expect(
|
|
214
|
+
repository.listHandoverSessions()[0].runsUnderWorkspacePreparationScript,
|
|
215
|
+
).toBe(true);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('does not mark a leader session whose cgroup scope is a cl scope as launched by the workspace preparation script', () => {
|
|
219
|
+
writeProcess({
|
|
220
|
+
pid: 210,
|
|
221
|
+
comm: 'claude',
|
|
222
|
+
cmdline: argv('claude', '--name', 'uminopm'),
|
|
223
|
+
environ: { CLAUDE_CODE_OAUTH_TOKEN: 'token-i' },
|
|
224
|
+
cgroup:
|
|
225
|
+
'/user.slice/user-1000.slice/user@1000.service/aiagents.slice/cl-uminopm.scope',
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const repository = new ProcClaudeHandoverSessionRepository(procDirectory);
|
|
229
|
+
|
|
230
|
+
expect(
|
|
231
|
+
repository.listHandoverSessions()[0].runsUnderWorkspacePreparationScript,
|
|
232
|
+
).toBe(false);
|
|
233
|
+
});
|
|
234
|
+
|
|
187
235
|
it('returns an empty list when the proc directory cannot be read', () => {
|
|
188
236
|
const repository = new ProcClaudeHandoverSessionRepository(
|
|
189
237
|
path.join(procDirectory, 'does-not-exist'),
|
|
@@ -13,6 +13,7 @@ const NAME_ARGUMENT_PREFIX = '--name=';
|
|
|
13
13
|
const PRINT_ARGUMENTS = ['-p', '--print'];
|
|
14
14
|
const PRINT_ARGUMENT_PREFIXES = ['-p=', '--print='];
|
|
15
15
|
const CLAUDE_COMM_PATTERN = /^claude(-agent)?$/;
|
|
16
|
+
const WORKSPACE_PREPARATION_SCOPE_PATTERN = /\/aw-[^/]*\.scope(\/|$)/;
|
|
16
17
|
const ISSUE_OR_PR_URL_PATTERN =
|
|
17
18
|
/https:\/\/github\.com\/[^\s\0]+?\/(?:issues|pull)\/\d+/;
|
|
18
19
|
|
|
@@ -69,6 +70,7 @@ const classifySession = (
|
|
|
69
70
|
pid: number,
|
|
70
71
|
commandArguments: string[],
|
|
71
72
|
token: string | null,
|
|
73
|
+
runsUnderWorkspacePreparationScript: boolean,
|
|
72
74
|
): ClaudeHandoverSession | null => {
|
|
73
75
|
if (token === null || token.length === 0) {
|
|
74
76
|
return null;
|
|
@@ -85,10 +87,19 @@ const classifySession = (
|
|
|
85
87
|
sessionName,
|
|
86
88
|
name,
|
|
87
89
|
issueUrl: extractIssueUrlFromText(name),
|
|
90
|
+
runsUnderWorkspacePreparationScript,
|
|
88
91
|
};
|
|
89
92
|
}
|
|
90
93
|
const kind: ClaudeHandoverSessionKind = 'bareNameLeader';
|
|
91
|
-
return {
|
|
94
|
+
return {
|
|
95
|
+
kind,
|
|
96
|
+
pid,
|
|
97
|
+
token,
|
|
98
|
+
sessionName,
|
|
99
|
+
name,
|
|
100
|
+
issueUrl: null,
|
|
101
|
+
runsUnderWorkspacePreparationScript,
|
|
102
|
+
};
|
|
92
103
|
}
|
|
93
104
|
const issueUrl = parseIssueUrlFromPrint(commandArguments);
|
|
94
105
|
if (issueUrl === null) {
|
|
@@ -101,6 +112,7 @@ const classifySession = (
|
|
|
101
112
|
sessionName: null,
|
|
102
113
|
name: null,
|
|
103
114
|
issueUrl,
|
|
115
|
+
runsUnderWorkspacePreparationScript,
|
|
104
116
|
};
|
|
105
117
|
};
|
|
106
118
|
|
|
@@ -146,7 +158,48 @@ export class ProcClaudeHandoverSessionRepository implements ClaudeHandoverSessio
|
|
|
146
158
|
return null;
|
|
147
159
|
}
|
|
148
160
|
const token = environ.get(OAUTH_TOKEN_ENVIRON_KEY) ?? null;
|
|
149
|
-
return classifySession(
|
|
161
|
+
return classifySession(
|
|
162
|
+
Number(processIdDirectory),
|
|
163
|
+
commandArguments,
|
|
164
|
+
token,
|
|
165
|
+
this.readRunsUnderWorkspacePreparationScript(processIdDirectory),
|
|
166
|
+
);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
private readRunsUnderWorkspacePreparationScript = (
|
|
170
|
+
processIdDirectory: string,
|
|
171
|
+
): boolean => {
|
|
172
|
+
const cgroupPath = path.join(
|
|
173
|
+
this.procDirectory,
|
|
174
|
+
processIdDirectory,
|
|
175
|
+
'cgroup',
|
|
176
|
+
);
|
|
177
|
+
let raw: string;
|
|
178
|
+
try {
|
|
179
|
+
raw = fs.readFileSync(cgroupPath, 'utf8');
|
|
180
|
+
} catch (error) {
|
|
181
|
+
console.error(
|
|
182
|
+
`ProcClaudeHandoverSessionRepository: could not read ${cgroupPath}: ${
|
|
183
|
+
error instanceof Error ? error.message : String(error)
|
|
184
|
+
}`,
|
|
185
|
+
);
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
for (const line of raw.split('\n')) {
|
|
189
|
+
const firstSeparatorIndex = line.indexOf(':');
|
|
190
|
+
if (firstSeparatorIndex < 0) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const secondSeparatorIndex = line.indexOf(':', firstSeparatorIndex + 1);
|
|
194
|
+
if (secondSeparatorIndex < 0) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const cgroupHierarchyPath = line.slice(secondSeparatorIndex + 1);
|
|
198
|
+
if (WORKSPACE_PREPARATION_SCOPE_PATTERN.test(cgroupHierarchyPath)) {
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
150
203
|
};
|
|
151
204
|
|
|
152
205
|
private readComm = (processIdDirectory: string): string | null => {
|
|
@@ -6,6 +6,29 @@ export type FieldOption = {
|
|
|
6
6
|
'GRAY' | 'BLUE' | 'GREEN' | 'YELLOW' | 'ORANGE' | 'RED' | 'PINK' | 'PURPLE';
|
|
7
7
|
description: string;
|
|
8
8
|
};
|
|
9
|
+
|
|
10
|
+
export type StoryListEntry = Omit<FieldOption, 'id'> & {
|
|
11
|
+
id: FieldOption['id'] | null;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const buildStoryListWithNew = (
|
|
15
|
+
existingStories: StoryListEntry[],
|
|
16
|
+
newName: string,
|
|
17
|
+
): StoryListEntry[] => {
|
|
18
|
+
if (existingStories.some((s) => s.name === newName)) {
|
|
19
|
+
return [...existingStories];
|
|
20
|
+
}
|
|
21
|
+
const newEntry: StoryListEntry = {
|
|
22
|
+
id: null,
|
|
23
|
+
name: newName,
|
|
24
|
+
color: 'RED',
|
|
25
|
+
description: '',
|
|
26
|
+
};
|
|
27
|
+
if (existingStories.length === 0) {
|
|
28
|
+
return [newEntry];
|
|
29
|
+
}
|
|
30
|
+
return [existingStories[0], newEntry, ...existingStories.slice(1)];
|
|
31
|
+
};
|
|
9
32
|
export type Project = {
|
|
10
33
|
id: string;
|
|
11
34
|
url: string;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import type { Issue } from '../entities/Issue';
|
|
2
|
+
import {
|
|
3
|
+
buildStoryListWithNew,
|
|
4
|
+
type Project,
|
|
5
|
+
type StoryListEntry,
|
|
6
|
+
} from '../entities/Project';
|
|
7
|
+
import type { StoryObjectMap } from '../entities/StoryObjectMap';
|
|
8
|
+
import type { IssueRepository } from './adapter-interfaces/IssueRepository';
|
|
9
|
+
import type { ProjectRepository } from './adapter-interfaces/ProjectRepository';
|
|
6
10
|
|
|
7
11
|
const LOG_PREFIX = '[CreateNewStoryByLabel]';
|
|
8
12
|
|
|
@@ -130,35 +134,13 @@ export class CreateNewStoryByLabelUseCase {
|
|
|
130
134
|
projectStory: NonNullable<Project['story']>,
|
|
131
135
|
storyObjectMap: StoryObjectMap,
|
|
132
136
|
issues: Issue[],
|
|
133
|
-
):
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
).filter((issue) => !existingStoryNames.has(issue.title));
|
|
141
|
-
const newStoryList: (Omit<FieldOption, 'id'> & {
|
|
142
|
-
id: FieldOption['id'] | null;
|
|
143
|
-
})[] = [];
|
|
144
|
-
if (projectStory.stories.length > 0) {
|
|
145
|
-
newStoryList.push(projectStory.stories[0]);
|
|
146
|
-
}
|
|
147
|
-
newStoryList.push(
|
|
148
|
-
...newStoryIssues.map(
|
|
149
|
-
(i): Omit<FieldOption, 'id'> & { id: FieldOption['id'] | null } => ({
|
|
150
|
-
id: null,
|
|
151
|
-
name: i.title,
|
|
152
|
-
color: 'RED',
|
|
153
|
-
description: '',
|
|
154
|
-
}),
|
|
155
|
-
),
|
|
156
|
-
);
|
|
157
|
-
if (projectStory.stories.length > 1) {
|
|
158
|
-
newStoryList.push(
|
|
159
|
-
...projectStory.stories.slice(1, projectStory.stories.length),
|
|
137
|
+
): StoryListEntry[] => {
|
|
138
|
+
const newStoryIssues = this.findNewStoryIssues(storyObjectMap, issues);
|
|
139
|
+
return [...newStoryIssues]
|
|
140
|
+
.reverse()
|
|
141
|
+
.reduce<StoryListEntry[]>(
|
|
142
|
+
(acc, issue) => buildStoryListWithNew(acc, issue.title),
|
|
143
|
+
[...projectStory.stories],
|
|
160
144
|
);
|
|
161
|
-
}
|
|
162
|
-
return newStoryList;
|
|
163
145
|
};
|
|
164
146
|
}
|
|
@@ -55,6 +55,7 @@ const issueUrlLeaderSession = (): ClaudeHandoverSession => ({
|
|
|
55
55
|
sessionName: ISSUE_URL_SESSION,
|
|
56
56
|
name: ISSUE_URL,
|
|
57
57
|
issueUrl: ISSUE_URL,
|
|
58
|
+
runsUnderWorkspacePreparationScript: false,
|
|
58
59
|
});
|
|
59
60
|
|
|
60
61
|
const bareNameLeaderSession = (): ClaudeHandoverSession => ({
|
|
@@ -64,6 +65,7 @@ const bareNameLeaderSession = (): ClaudeHandoverSession => ({
|
|
|
64
65
|
sessionName: BARE_NAME,
|
|
65
66
|
name: BARE_NAME,
|
|
66
67
|
issueUrl: null,
|
|
68
|
+
runsUnderWorkspacePreparationScript: false,
|
|
67
69
|
});
|
|
68
70
|
|
|
69
71
|
const implSubagentSession = (): ClaudeHandoverSession => ({
|
|
@@ -73,6 +75,12 @@ const implSubagentSession = (): ClaudeHandoverSession => ({
|
|
|
73
75
|
sessionName: null,
|
|
74
76
|
name: null,
|
|
75
77
|
issueUrl: ISSUE_URL,
|
|
78
|
+
runsUnderWorkspacePreparationScript: false,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const workspacePreparationSession = (): ClaudeHandoverSession => ({
|
|
82
|
+
...implSubagentSession(),
|
|
83
|
+
runsUnderWorkspacePreparationScript: true,
|
|
76
84
|
});
|
|
77
85
|
|
|
78
86
|
const defaultInput = (
|
|
@@ -161,7 +169,7 @@ describe('TokenExhaustionHandoverUseCase', () => {
|
|
|
161
169
|
await useCase.run(defaultInput({ enabled: false }));
|
|
162
170
|
|
|
163
171
|
expect(logSpy).toHaveBeenCalledWith(
|
|
164
|
-
'Token exhaustion handover: cycle summary evaluated=0 enabled=false signaled=0 killed=0 terminatedPids=0 relaunched=0 leftAlive=0',
|
|
172
|
+
'Token exhaustion handover: cycle summary evaluated=0 enabled=false signaled=0 killed=0 terminatedPids=0 relaunched=0 leftAlive=0 skippedWorkspacePreparation=0',
|
|
165
173
|
);
|
|
166
174
|
});
|
|
167
175
|
|
|
@@ -343,6 +351,56 @@ describe('TokenExhaustionHandoverUseCase', () => {
|
|
|
343
351
|
});
|
|
344
352
|
});
|
|
345
353
|
|
|
354
|
+
it('leaves a session launched by the workspace preparation script untouched instead of terminating it', async () => {
|
|
355
|
+
handoverSessionRepository.listHandoverSessions.mockReturnValue([
|
|
356
|
+
workspacePreparationSession(),
|
|
357
|
+
]);
|
|
358
|
+
snapshotRepository.listSnapshots.mockReturnValue([
|
|
359
|
+
snapshot(TOKEN_EXHAUSTED, { fiveHourUtilization: 0.95 }),
|
|
360
|
+
snapshot(TOKEN_FRESH),
|
|
361
|
+
]);
|
|
362
|
+
|
|
363
|
+
const result = await useCase.run(defaultInput());
|
|
364
|
+
|
|
365
|
+
expect(processSignalRepository.terminateProcess).not.toHaveBeenCalled();
|
|
366
|
+
expect(processSignalRepository.killProcess).not.toHaveBeenCalled();
|
|
367
|
+
expect(result.newlyHandoverSentSessionNames).toEqual([]);
|
|
368
|
+
expect(result.skippedWorkspacePreparationSessionNames).toEqual([
|
|
369
|
+
`pid:${IMPL_PID}`,
|
|
370
|
+
]);
|
|
371
|
+
expect(result.state.entries).toEqual({});
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('does not force-kill a workspace preparation session whose grace period has elapsed', async () => {
|
|
375
|
+
handoverSessionRepository.listHandoverSessions.mockReturnValue([
|
|
376
|
+
workspacePreparationSession(),
|
|
377
|
+
]);
|
|
378
|
+
snapshotRepository.listSnapshots.mockReturnValue([
|
|
379
|
+
snapshot(TOKEN_EXHAUSTED, { fiveHourUtilization: 0.95 }),
|
|
380
|
+
snapshot(TOKEN_FRESH),
|
|
381
|
+
]);
|
|
382
|
+
processSignalRepository.isProcessAlive.mockReturnValue(true);
|
|
383
|
+
|
|
384
|
+
const result = await useCase.run(
|
|
385
|
+
defaultInput({
|
|
386
|
+
state: {
|
|
387
|
+
entries: {
|
|
388
|
+
[`pid:${IMPL_PID}`]: {
|
|
389
|
+
signaledAtEpoch:
|
|
390
|
+
nowEpochSeconds -
|
|
391
|
+
DEFAULT_TOKEN_EXHAUSTION_GRACE_PERIOD_SECONDS -
|
|
392
|
+
1,
|
|
393
|
+
pid: IMPL_PID,
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
}),
|
|
398
|
+
);
|
|
399
|
+
|
|
400
|
+
expect(processSignalRepository.killProcess).not.toHaveBeenCalled();
|
|
401
|
+
expect(result.terminatedPids).toEqual([]);
|
|
402
|
+
});
|
|
403
|
+
|
|
346
404
|
it('does not treat an impl subagent as exhausted on seven-day utilization alone', async () => {
|
|
347
405
|
handoverSessionRepository.listHandoverSessions.mockReturnValue([
|
|
348
406
|
implSubagentSession(),
|
|
@@ -51,6 +51,7 @@ export type TokenExhaustionHandoverResult = {
|
|
|
51
51
|
terminatedPids: number[];
|
|
52
52
|
relaunchedLeaderNames: string[];
|
|
53
53
|
leftAliveSessionNames: string[];
|
|
54
|
+
skippedWorkspacePreparationSessionNames: string[];
|
|
54
55
|
state: TokenExhaustionHandoverState;
|
|
55
56
|
};
|
|
56
57
|
|
|
@@ -95,9 +96,20 @@ export class TokenExhaustionHandoverUseCase {
|
|
|
95
96
|
const terminatedPids: number[] = [];
|
|
96
97
|
const relaunchedLeaderNames: string[] = [];
|
|
97
98
|
const leftAliveSessionNames: string[] = [];
|
|
99
|
+
const skippedWorkspacePreparationSessionNames: string[] = [];
|
|
98
100
|
|
|
99
101
|
for (const session of sessions) {
|
|
100
102
|
try {
|
|
103
|
+
if (session.runsUnderWorkspacePreparationScript) {
|
|
104
|
+
console.log(
|
|
105
|
+
`Token exhaustion handover: skipping ${this.displayName(session)} kind=${session.kind} (launched by the workspace preparation script, which owns its own lifecycle)`,
|
|
106
|
+
);
|
|
107
|
+
skippedWorkspacePreparationSessionNames.push(
|
|
108
|
+
this.displayName(session),
|
|
109
|
+
);
|
|
110
|
+
delete nextEntries[this.stateKeyFor(session)];
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
101
113
|
const snapshot = snapshotByToken.get(session.token);
|
|
102
114
|
if (snapshot === undefined) {
|
|
103
115
|
continue;
|
|
@@ -200,7 +212,7 @@ export class TokenExhaustionHandoverUseCase {
|
|
|
200
212
|
}
|
|
201
213
|
|
|
202
214
|
console.log(
|
|
203
|
-
`Token exhaustion handover: cycle summary evaluated=${sessions.length} enabled=${input.enabled} signaled=${newlyHandoverSentSessionNames.length} killed=${killedSessionNames.length} terminatedPids=${terminatedPids.length} relaunched=${relaunchedLeaderNames.length} leftAlive=${leftAliveSessionNames.length}`,
|
|
215
|
+
`Token exhaustion handover: cycle summary evaluated=${sessions.length} enabled=${input.enabled} signaled=${newlyHandoverSentSessionNames.length} killed=${killedSessionNames.length} terminatedPids=${terminatedPids.length} relaunched=${relaunchedLeaderNames.length} leftAlive=${leftAliveSessionNames.length} skippedWorkspacePreparation=${skippedWorkspacePreparationSessionNames.length}`,
|
|
204
216
|
);
|
|
205
217
|
|
|
206
218
|
return {
|
|
@@ -209,6 +221,7 @@ export class TokenExhaustionHandoverUseCase {
|
|
|
209
221
|
terminatedPids,
|
|
210
222
|
relaunchedLeaderNames,
|
|
211
223
|
leftAliveSessionNames,
|
|
224
|
+
skippedWorkspacePreparationSessionNames,
|
|
212
225
|
state: { entries: nextEntries },
|
|
213
226
|
};
|
|
214
227
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
-
export { ConfigFile,
|
|
3
|
+
export { ConfigFile, fetchProjectReadme, loadConfigFile, mergeConfigs, parseProjectReadmeConfig, } from './projectConfig';
|
|
4
4
|
export declare const program: Command;
|
|
5
5
|
export declare const reportFatalErrorAndExit: (error: unknown) => void;
|
|
6
6
|
export declare const runCliProgram: (argv: string[], handleFatalError: (error: unknown) => void) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AAmMzB,eAAO,MAAM,OAAO,SAAgB,CAAC;AAuiCrC,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,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { IssueAttachmentRepository } from '../../../domain/usecases/adapter-interfaces/IssueAttachmentRepository';
|
|
3
|
-
import {
|
|
1
|
+
import { type FieldOption, type Project } from '../../../domain/entities/Project';
|
|
2
|
+
import type { IssueAttachmentRepository } from '../../../domain/usecases/adapter-interfaces/IssueAttachmentRepository';
|
|
3
|
+
import type { IssueRepository } from '../../../domain/usecases/adapter-interfaces/IssueRepository';
|
|
4
|
+
import type { ProjectRepository } from '../../../domain/usecases/adapter-interfaces/ProjectRepository';
|
|
4
5
|
export declare const AWAITING_WORKSPACE_STATUS_NAME = "awaiting workspace";
|
|
5
6
|
export declare const IN_TMUX_BY_HUMAN_STATUS_NAME = "in tmux by human";
|
|
6
7
|
export declare const CHORE_LABEL_NAME = "chore";
|
|
@@ -11,6 +12,7 @@ export type ConsoleProjectBinding = {
|
|
|
11
12
|
export type ConsoleProjectResolver = (pjcode: string) => Promise<ConsoleProjectBinding | null>;
|
|
12
13
|
export type ConsolePjcodeValidator = (pjcode: string) => boolean;
|
|
13
14
|
export type ConsoleIssueRepositoryResolver = (issueOrPullRequestUrl: string) => IssueRepository;
|
|
15
|
+
export type ConsoleProjectRepositoryResolver = (projectUrl: string) => Pick<ProjectRepository, 'updateStoryList'>;
|
|
14
16
|
export type ConsoleOperationContext = {
|
|
15
17
|
resolveIssueRepository: ConsoleIssueRepositoryResolver;
|
|
16
18
|
resolveProject: ConsoleProjectResolver;
|
|
@@ -18,6 +20,8 @@ export type ConsoleOperationContext = {
|
|
|
18
20
|
consoleDataOutputDir: string | null;
|
|
19
21
|
issueAttachmentRepository: IssueAttachmentRepository | null;
|
|
20
22
|
updateStoryList: ((project: Project, stories: FieldOption[]) => Promise<FieldOption[]>) | null;
|
|
23
|
+
resolveProjectRepository: ConsoleProjectRepositoryResolver | null;
|
|
24
|
+
invalidateProject: ((pjcode: string) => void) | null;
|
|
21
25
|
};
|
|
22
26
|
export type ConsoleOperationResponse = {
|
|
23
27
|
statusCode: number;
|
|
@@ -31,4 +35,5 @@ export declare const handleCreateIssue: (context: ConsoleOperationContext, body:
|
|
|
31
35
|
export declare const handleReviewComment: (context: ConsoleOperationContext, body: Record<string, unknown>) => Promise<ConsoleOperationResponse>;
|
|
32
36
|
export declare const handleIntmux: (context: ConsoleOperationContext, body: Record<string, unknown>) => Promise<ConsoleOperationResponse>;
|
|
33
37
|
export declare const handleReorderStory: (context: ConsoleOperationContext, body: Record<string, unknown>) => Promise<ConsoleOperationResponse>;
|
|
38
|
+
export declare const handleStoryAdd: (context: ConsoleOperationContext, body: Record<string, unknown>) => Promise<ConsoleOperationResponse>;
|
|
34
39
|
//# sourceMappingURL=consoleOperationApi.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consoleOperationApi.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/consoleOperationApi.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"consoleOperationApi.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/consoleOperationApi.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,5 +8,9 @@ export type ConsoleProjectIdAndProjectReader = {
|
|
|
8
8
|
export declare const createConsoleProjectLoader: (resolveProjectRepository: (projectUrl: string) => ConsoleProjectIdAndProjectReader, getCachedProject: (projectId: string) => Promise<Project | null>, reportLoadFailure: (message: string) => void) => ConsoleProjectLoader;
|
|
9
9
|
export declare const buildPjcodeToProjectUrl: (defaultPjcode: string, defaultProjectUrl: string, consoleProjects: Record<string, string> | null) => Record<string, string>;
|
|
10
10
|
export declare const createPjcodeConfigChecker: (pjcodeToProjectUrl: Record<string, string>) => ConsolePjcodeValidator;
|
|
11
|
-
export
|
|
11
|
+
export type ConsoleProjectResolverBundle = {
|
|
12
|
+
resolve: ConsoleProjectResolver;
|
|
13
|
+
invalidate: (pjcode: string) => void;
|
|
14
|
+
};
|
|
15
|
+
export declare const createConsoleProjectResolver: (pjcodeToProjectUrl: Record<string, string>, loadProject: ConsoleProjectLoader) => ConsoleProjectResolverBundle;
|
|
12
16
|
//# sourceMappingURL=consoleProjectResolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consoleProjectResolver.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/consoleProjectResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EACL,sBAAsB,EAEtB,sBAAsB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,MAAM,oBAAoB,GAAG,CACjC,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;AAE7B,MAAM,MAAM,gCAAgC,GAAG;IAC7C,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACnE,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CAC5D,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,0BAA0B,CACxB,UAAU,EAAE,MAAM,KACf,gCAAgC,EACrC,kBAAkB,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,EAChE,mBAAmB,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,KAC3C,oBAmBF,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,eAAe,MAAM,EACrB,mBAAmB,MAAM,EACzB,iBAAiB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,KAC7C,MAAM,CAAC,MAAM,EAAE,MAAM,CAWvB,CAAC;AAKF,eAAO,MAAM,yBAAyB,GACpC,oBAAoB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACzC,sBAGF,CAAC;AAEF,eAAO,MAAM,4BAA4B,GACvC,oBAAoB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC1C,aAAa,oBAAoB,KAChC,
|
|
1
|
+
{"version":3,"file":"consoleProjectResolver.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/consoleProjectResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EACL,sBAAsB,EAEtB,sBAAsB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,MAAM,oBAAoB,GAAG,CACjC,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;AAE7B,MAAM,MAAM,gCAAgC,GAAG;IAC7C,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACnE,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CAC5D,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,0BAA0B,CACxB,UAAU,EAAE,MAAM,KACf,gCAAgC,EACrC,kBAAkB,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,EAChE,mBAAmB,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,KAC3C,oBAmBF,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,eAAe,MAAM,EACrB,mBAAmB,MAAM,EACzB,iBAAiB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,KAC7C,MAAM,CAAC,MAAM,EAAE,MAAM,CAWvB,CAAC;AAKF,eAAO,MAAM,yBAAyB,GACpC,oBAAoB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACzC,sBAGF,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,OAAO,EAAE,sBAAsB,CAAC;IAChC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC,CAAC;AAEF,eAAO,MAAM,4BAA4B,GACvC,oBAAoB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC1C,aAAa,oBAAoB,KAChC,4BAyBF,CAAC"}
|
|
@@ -3,7 +3,7 @@ import { IssueAttachmentRepository } from '../../../domain/usecases/adapter-inte
|
|
|
3
3
|
import { IssueRepository } from '../../../domain/usecases/adapter-interfaces/IssueRepository';
|
|
4
4
|
import { ProjectRepository } from '../../../domain/usecases/adapter-interfaces/ProjectRepository';
|
|
5
5
|
import { IssueTitleStateCache, PullRequestStatusCache } from './consoleReadApi';
|
|
6
|
-
import { ConsoleIssueRepositoryResolver, ConsolePjcodeValidator, ConsoleProjectResolver } from './consoleOperationApi';
|
|
6
|
+
import { ConsoleIssueRepositoryResolver, ConsolePjcodeValidator, ConsoleProjectRepositoryResolver, ConsoleProjectResolver } from './consoleOperationApi';
|
|
7
7
|
import { ImageFetcher } from './consoleImageProxy';
|
|
8
8
|
import { ConsoleGithubTokenResolver } from './consoleGithubTokenResolver';
|
|
9
9
|
export declare const DEFAULT_WEB_PORT = 9980;
|
|
@@ -32,6 +32,8 @@ export type WebServerOptions = {
|
|
|
32
32
|
resolveIssueRepository?: ConsoleIssueRepositoryResolver | null;
|
|
33
33
|
resolveProject?: ConsoleProjectResolver | null;
|
|
34
34
|
isPjcodeConfigured?: ConsolePjcodeValidator | null;
|
|
35
|
+
resolveProjectRepository?: ConsoleProjectRepositoryResolver | null;
|
|
36
|
+
invalidateProject?: ((pjcode: string) => void) | null;
|
|
35
37
|
issueAttachmentRepository?: IssueAttachmentRepository | null;
|
|
36
38
|
projectRepository?: Pick<ProjectRepository, 'updateStoryList'> | null;
|
|
37
39
|
issueTitleStateCache?: IssueTitleStateCache | null;
|