engineering-memory 1.11.20 → 1.11.21
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/bin/engineering-memory.mjs +14 -24
- package/install/localization.generated.mjs +18 -0
- package/package.json +1 -1
- package/runtime/build.json +1 -1
- package/runtime/dist/src/auth/browser-auth.js +15 -4
- package/runtime/dist/src/config.js +1 -0
- package/runtime/dist/src/git/git-inspector.js +10 -0
- package/runtime/dist/src/localization/catalogue.generated.js +786 -0
- package/runtime/dist/src/mcp/delivery-tools.js +15 -48
- package/runtime/dist/src/mcp/onboarding-tools.js +289 -618
- package/runtime/dist/src/mcp/questionnaire-tools.js +23 -26
- package/runtime/dist/src/mcp/status-meaning-tools.js +12 -86
- package/runtime/dist/src/mcp/status-remap-tools.js +252 -0
- package/runtime/dist/src/mcp/tool-annotations.js +1 -0
- package/runtime/dist/src/mcp/tool-definitions.js +33 -55
- package/runtime/dist/src/mcp/workflow-tools.js +17 -108
- package/runtime/dist/src/mcp/worktree-tools.js +168 -250
- package/runtime/dist/src/runtime/bridge-service.js +100 -94
- package/runtime/dist/src/runtime/create-bridge-service.js +4 -2
- package/runtime/dist/src/runtime/language-store.js +6 -0
- package/runtime/dist/src/runtime/release-notes.js +6 -6
- package/runtime/dist/src/runtime/release-report.js +30 -30
- package/runtime/dist/src/runtime/task-start.js +75 -73
- package/runtime/dist/src/runtime/texts.js +135 -0
- package/runtime/dist/src/runtime/worktree-pool.js +30 -5
- package/runtime/dist/src/runtime/worktree-preparation.js +3 -2
- package/runtime/dist/src/utilities/process.js +7 -0
- package/skill/references/lifecycle.md +21 -3
- package/skill/references/project-onboarding.md +5 -2
- package/skill/references/questionnaires.md +3 -1
|
@@ -7,6 +7,7 @@ import { sha256, stableStringify } from '../utilities/hash.js';
|
|
|
7
7
|
import { unreadableWorktree } from '../runtime/worktree-pool.js';
|
|
8
8
|
import { askFailed, askQuestionnaire } from './questionnaire-tools.js';
|
|
9
9
|
import { languageTag } from '../runtime/questionnaire-store.js';
|
|
10
|
+
import { copies, format } from '../runtime/texts.js';
|
|
10
11
|
const repo = z.string().min(1);
|
|
11
12
|
const branch = z.string().min(1).max(255);
|
|
12
13
|
const remote = z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$/);
|
|
@@ -51,170 +52,76 @@ const policy = {
|
|
|
51
52
|
heartbeatSeconds: z.number().int().min(5).max(300),
|
|
52
53
|
inactivitySeconds: z.number().int().min(60).max(86400),
|
|
53
54
|
};
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
};
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
keep: 'Takip etmeye devam et',
|
|
125
|
-
kept: 'Hiçbir şey değişmez. Kayıt durur ve sınıra sayılmaya devam eder.',
|
|
126
|
-
},
|
|
127
|
-
};
|
|
128
|
-
const retireCopy = {
|
|
129
|
-
en: {
|
|
130
|
-
missing: (folder) => `The ${folder} folder is gone but its worktree record is still here. Remove the record?`,
|
|
131
|
-
message: (folder, branch) => `${folder} is a worktree left in the old location (branch ${branch}). Remove the folder?`,
|
|
132
|
-
context: (missing) => 'Folders in the old location are no longer part of the pool: they are never reused and do not count toward the limit.' +
|
|
133
|
-
(missing
|
|
134
|
-
? ' Only the record is left, so there is no folder to remove and no file is read or deleted.'
|
|
135
|
-
: ' The branch and its commits stay. Git removes only a clean folder, and the files it ignores go with it.'),
|
|
136
|
-
example: (folder, branch, missing) => missing
|
|
137
|
-
? `After this, ${folder} is gone from the worktree list and nothing on disk changes.`
|
|
138
|
-
: `After this, ${folder} is gone from the worktree list and branch ${branch} still holds every commit made on it.`,
|
|
139
|
-
retire: 'Remove the folder',
|
|
140
|
-
retired: (missing) => missing
|
|
141
|
-
? 'The stale record is removed. Nothing on disk changes.'
|
|
142
|
-
: 'Git removes the folder and Engineering Memory drops its record. The branch and its commits stay.',
|
|
143
|
-
keep: 'Keep it',
|
|
144
|
-
kept: 'Nothing changes. The folder and its record stay exactly as they are.',
|
|
145
|
-
},
|
|
146
|
-
tr: {
|
|
147
|
-
missing: (folder) => `${folder} klasörü artık yok ama worktree kaydı duruyor. Kayıt silinsin mi?`,
|
|
148
|
-
message: (folder, branch) => `${folder}, eski konumda kalmış bir worktree (dal ${branch}). Klasör kaldırılsın mı?`,
|
|
149
|
-
context: (missing) => 'Eski konumdaki klasörler artık havuzun parçası değil: yeniden kullanılmıyorlar ve sınıra da sayılmıyorlar.' +
|
|
150
|
-
(missing
|
|
151
|
-
? ' Geriye yalnızca kayıt kaldı; kaldırılacak bir klasör yok, hiçbir dosya okunmaz veya silinmez.'
|
|
152
|
-
: ' Dal ve üzerindeki commit’ler kalır. Git yalnızca temiz bir klasörü kaldırır; kaldırırken .gitignore kapsamındaki dosyalar da gider.'),
|
|
153
|
-
example: (folder, branch, missing) => missing
|
|
154
|
-
? `Bundan sonra ${folder} worktree listesinde görünmez; diskte hiçbir şey değişmez.`
|
|
155
|
-
: `Bundan sonra ${folder} worktree listesinde görünmez; ${branch} dalındaki commit’ler ise yerinde durur.`,
|
|
156
|
-
retire: 'Klasörü kaldır',
|
|
157
|
-
retired: (missing) => missing
|
|
158
|
-
? 'Boşta kalan kayıt silinir. Diskte hiçbir şey değişmez.'
|
|
159
|
-
: 'Git klasörü kaldırır, Engineering Memory de kaydını siler. Dal ve commit’ler kalır.',
|
|
160
|
-
keep: 'Kalsın',
|
|
161
|
-
kept: 'Hiçbir şey değişmez. Klasör de kaydı da olduğu gibi kalır.',
|
|
162
|
-
},
|
|
163
|
-
};
|
|
164
|
-
const unownedCopy = {
|
|
165
|
-
en: {
|
|
166
|
-
message: (folder) => `Nobody is recorded as using the ${folder} folder. If the agent that worked there has stopped and its delivery is finished, should the clean checkout become reusable?`,
|
|
167
|
-
context: 'This checkout was found without an ownership record, so it is protected and handed to no task. Releasing it runs the safety checks again first: a folder with uncommitted work is refused. No file and no branch is ever deleted.',
|
|
168
|
-
example: (commit) => `Once it is released, the next task can start in that folder, and the work committed at ${commit} stays on its branch.`,
|
|
169
|
-
release: 'Prior work finished; release after safety checks',
|
|
170
|
-
released: 'The safety checks run and, if they pass, the folder returns to the pool.',
|
|
171
|
-
preserve: 'Keep protected',
|
|
172
|
-
preserved: 'Nothing changes. The folder stays protected and is given to no task.',
|
|
173
|
-
},
|
|
174
|
-
tr: {
|
|
175
|
-
message: (folder) => `${folder} klasörünü kimin kullandığı kayıtlı değil. Burada çalışan ajan durduysa ve teslimi bittiyse, temiz klasör yeniden kullanılabilir hâle gelsin mi?`,
|
|
176
|
-
context: 'Bu çalışma kopyası sahiplik kaydı olmadan bulundu; bu yüzden korunuyor ve hiçbir göreve verilmiyor. Serbest bırakmadan önce güvenlik kontrolleri yeniden çalışır: kaydedilmemiş iş varsa işlem yapılmaz. Hiçbir dosya ve hiçbir dal silinmez.',
|
|
177
|
-
example: (commit) => `Serbest bırakılırsa sıradaki görev bu klasörde başlayabilir; ${commit} commit’ine kaydedilmiş iş dalında durmaya devam eder.`,
|
|
178
|
-
release: 'Önceki iş bitti; güvenlik kontrollerinden sonra kullanılabilir yap',
|
|
179
|
-
released: 'Güvenlik kontrolleri çalışır; geçerse klasör havuza döner.',
|
|
180
|
-
preserve: 'Korumaya devam et',
|
|
181
|
-
preserved: 'Hiçbir şey değişmez. Klasör korunur ve hiçbir göreve verilmez.',
|
|
182
|
-
},
|
|
183
|
-
};
|
|
184
|
-
const cancelCopy = {
|
|
185
|
-
en: {
|
|
186
|
-
message: (task) => `${task} will not be delivered. What should happen to this folder?`,
|
|
187
|
-
context: (clean, managed) => 'A cancelled delivery leaves the folder reserved for this task until you say what happens to it, and a reserved folder keeps counting against the worktree limit. The branch and every commit on it stay either way.' +
|
|
188
|
-
(clean
|
|
189
|
-
? ''
|
|
190
|
-
: managed
|
|
191
|
-
? ' The folder has uncommitted changes; saving writes them to a Git ref they can be restored from.'
|
|
192
|
-
: ' The folder has uncommitted changes; this is your own folder, so its files are never touched when it is freed.'),
|
|
193
|
-
example: 'Freeing the folder lets the next task start in it; keeping it leaves it reserved.',
|
|
194
|
-
release: 'Free the folder; the branch stays',
|
|
195
|
-
released: 'The folder returns to the pool. Its files are left alone and the branch stays.',
|
|
196
|
-
save: 'Save the changes and free the folder',
|
|
197
|
-
saved: 'The uncommitted changes are written to a Git ref first, then the folder is freed. They can be restored from that ref.',
|
|
198
|
-
keep: 'Keep the folder as it is',
|
|
199
|
-
kept: 'Nothing changes. The folder stays reserved for this task.',
|
|
200
|
-
},
|
|
201
|
-
tr: {
|
|
202
|
-
message: (task) => `${task} teslim edilmeyecek. Bu klasör ne olsun?`,
|
|
203
|
-
context: (clean, managed) => 'Teslimi iptal edilen bir klasör, sen ne olacağını söyleyene kadar bu göreve ayrılmış kalır ve ayrılmış klasör worktree sınırına sayılmaya devam eder. Dal ve üzerindeki commit’ler her hâlükârda durur.' +
|
|
204
|
-
(clean
|
|
205
|
-
? ''
|
|
206
|
-
: managed
|
|
207
|
-
? ' Klasörde kaydedilmemiş değişiklikler var; kaydedilirse bir Git ref’ine yazılır ve oradan geri alınabilir.'
|
|
208
|
-
: ' Klasörde kaydedilmemiş değişiklikler var; burası senin kendi klasörün olduğu için boşaltılsa da dosyalara dokunulmaz.'),
|
|
209
|
-
example: 'Klasör boşaltılırsa sıradaki görev burada başlayabilir; kalsın dersen bu göreve ayrılmış hâlde durur.',
|
|
210
|
-
release: 'Klasörü boşalt; branch kalsın',
|
|
211
|
-
released: 'Klasör havuza döner. Dosyalarına dokunulmaz, dal kalır.',
|
|
212
|
-
save: 'Değişiklikleri kaydedip klasörü boşalt',
|
|
213
|
-
saved: 'Kaydedilmemiş değişiklikler önce bir Git ref’ine yazılır, sonra klasör boşaltılır. Değişiklikler o ref’ten geri alınabilir.',
|
|
214
|
-
keep: 'Klasör olduğu gibi kalsın',
|
|
215
|
-
kept: 'Hiçbir şey değişmez. Klasör bu göreve ayrılmış hâlde kalır.',
|
|
216
|
-
},
|
|
217
|
-
};
|
|
55
|
+
const text = z.string().min(1);
|
|
56
|
+
const roleTexts = z.strictObject({ development: text, production: text, test: text });
|
|
57
|
+
const preferenceWording = z.strictObject({
|
|
58
|
+
message: text,
|
|
59
|
+
context: text,
|
|
60
|
+
example: text,
|
|
61
|
+
ask: roleTexts,
|
|
62
|
+
askNone: roleTexts,
|
|
63
|
+
save: text,
|
|
64
|
+
saved: text,
|
|
65
|
+
leave: text,
|
|
66
|
+
unchanged: text,
|
|
67
|
+
});
|
|
68
|
+
const fallbackWording = z.strictObject({
|
|
69
|
+
messageHere: text,
|
|
70
|
+
messageWorktree: text,
|
|
71
|
+
context: text,
|
|
72
|
+
example: text,
|
|
73
|
+
approve: text,
|
|
74
|
+
approved: text,
|
|
75
|
+
defer: text,
|
|
76
|
+
deferred: text,
|
|
77
|
+
});
|
|
78
|
+
const forgetWording = z.strictObject({
|
|
79
|
+
message: text,
|
|
80
|
+
context: text,
|
|
81
|
+
pendingDelivery: text,
|
|
82
|
+
example: text,
|
|
83
|
+
forget: text,
|
|
84
|
+
forgotten: text,
|
|
85
|
+
keep: text,
|
|
86
|
+
kept: text,
|
|
87
|
+
});
|
|
88
|
+
const retireWording = z.strictObject({
|
|
89
|
+
missing: text,
|
|
90
|
+
message: text,
|
|
91
|
+
noBranch: text,
|
|
92
|
+
context: text,
|
|
93
|
+
contextMissing: text,
|
|
94
|
+
contextFolder: text,
|
|
95
|
+
example: text,
|
|
96
|
+
exampleMissing: text,
|
|
97
|
+
retire: text,
|
|
98
|
+
retired: text,
|
|
99
|
+
retiredMissing: text,
|
|
100
|
+
keep: text,
|
|
101
|
+
kept: text,
|
|
102
|
+
});
|
|
103
|
+
const unownedWording = z.strictObject({
|
|
104
|
+
message: text,
|
|
105
|
+
context: text,
|
|
106
|
+
example: text,
|
|
107
|
+
release: text,
|
|
108
|
+
released: text,
|
|
109
|
+
preserve: text,
|
|
110
|
+
preserved: text,
|
|
111
|
+
});
|
|
112
|
+
const cancelWording = z.strictObject({
|
|
113
|
+
message: text,
|
|
114
|
+
context: text,
|
|
115
|
+
uncommittedManaged: text,
|
|
116
|
+
uncommittedOwn: text,
|
|
117
|
+
example: text,
|
|
118
|
+
release: text,
|
|
119
|
+
released: text,
|
|
120
|
+
save: text,
|
|
121
|
+
saved: text,
|
|
122
|
+
keep: text,
|
|
123
|
+
kept: text,
|
|
124
|
+
});
|
|
218
125
|
const baseSchema = z.discriminatedUnion('kind', [
|
|
219
126
|
z.strictObject({
|
|
220
127
|
kind: z.literal('current'),
|
|
@@ -266,7 +173,7 @@ export function registerWorktreeTools(server, service) {
|
|
|
266
173
|
presentation,
|
|
267
174
|
}),
|
|
268
175
|
}, async (input, context) => {
|
|
269
|
-
const
|
|
176
|
+
const wording = copies(preferenceWording, 'gitPreferences', await service.language(input.language));
|
|
270
177
|
const current = await service.projectGitPreferences(input);
|
|
271
178
|
if (!current.ok)
|
|
272
179
|
return output(current);
|
|
@@ -296,24 +203,26 @@ export function registerWorktreeTools(server, service) {
|
|
|
296
203
|
...(input.decisionAttempt ? { decisionAttempt: input.decisionAttempt } : {}),
|
|
297
204
|
}));
|
|
298
205
|
const questionnaireId = 'project-branches-' + digest;
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
206
|
+
const definitions = wording.map(({ language, copy }) => ({
|
|
207
|
+
questionnaireId,
|
|
208
|
+
language,
|
|
209
|
+
message: copy.message,
|
|
210
|
+
context: copy.context,
|
|
211
|
+
example: copy.example,
|
|
212
|
+
questions: roles.map((role) => {
|
|
213
|
+
const branch = source(role, null);
|
|
214
|
+
return {
|
|
308
215
|
id: role,
|
|
309
|
-
message:
|
|
216
|
+
message: branch
|
|
217
|
+
? format(copy.ask[role], language, { source: branch })
|
|
218
|
+
: copy.askNone[role],
|
|
310
219
|
options: [
|
|
311
220
|
{ id: 'approve', label: copy.save, description: copy.saved },
|
|
312
221
|
{ id: 'defer', label: copy.leave, description: copy.unchanged },
|
|
313
222
|
],
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
};
|
|
223
|
+
};
|
|
224
|
+
}),
|
|
225
|
+
}));
|
|
317
226
|
const previous = (turkish) => ({
|
|
318
227
|
questionnaireId,
|
|
319
228
|
language: turkish ? 'tr' : 'en',
|
|
@@ -347,10 +256,10 @@ export function registerWorktreeTools(server, service) {
|
|
|
347
256
|
}),
|
|
348
257
|
};
|
|
349
258
|
const form = await askQuestionnaire(server, service, {
|
|
350
|
-
...
|
|
259
|
+
...definitions[0],
|
|
351
260
|
repoRoot: input.repoRoot,
|
|
352
261
|
presentation: input.presentation,
|
|
353
|
-
}, context, [
|
|
262
|
+
}, context, [...definitions, previous(true), previous(false)], owner);
|
|
354
263
|
if (askFailed(form))
|
|
355
264
|
return form;
|
|
356
265
|
const record = await service.questionnaireResume({
|
|
@@ -388,7 +297,7 @@ export function registerWorktreeTools(server, service) {
|
|
|
388
297
|
presentation,
|
|
389
298
|
}),
|
|
390
299
|
}, async (input, context) => {
|
|
391
|
-
const
|
|
300
|
+
const told = await service.language(input.language);
|
|
392
301
|
const preflight = await service.taskBranchPreflight(input);
|
|
393
302
|
if (!preflight.ok)
|
|
394
303
|
return output(preflight);
|
|
@@ -410,7 +319,11 @@ export function registerWorktreeTools(server, service) {
|
|
|
410
319
|
recovery: 'task.branch',
|
|
411
320
|
},
|
|
412
321
|
});
|
|
413
|
-
const { previous, ...definition } = taskStartDefinition({
|
|
322
|
+
const { previous, ...definition } = taskStartDefinition({
|
|
323
|
+
...input,
|
|
324
|
+
...flight,
|
|
325
|
+
language: told ?? 'en',
|
|
326
|
+
});
|
|
414
327
|
const owner = {
|
|
415
328
|
tool: 'task.branch',
|
|
416
329
|
externalTaskId: input.externalTaskId,
|
|
@@ -477,21 +390,25 @@ export function registerWorktreeTools(server, service) {
|
|
|
477
390
|
const fallback = async () => {
|
|
478
391
|
const from = sourceLabel(choice.base, flight.currentBranch);
|
|
479
392
|
const local = sourceLabel(fallbackBase, flight.currentBranch);
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
393
|
+
const definitions = copies(fallbackWording, 'startFallback', told).map(({ language, copy }) => ({
|
|
394
|
+
questionnaireId: fallbackId,
|
|
395
|
+
language,
|
|
396
|
+
allowFreeText: false,
|
|
397
|
+
message: format(choice.inPlace ? copy.messageHere : copy.messageWorktree, language, {
|
|
398
|
+
remote: from,
|
|
399
|
+
local,
|
|
400
|
+
}),
|
|
401
|
+
context: copy.context,
|
|
402
|
+
example: format(copy.example, language, { remote: from, local }),
|
|
403
|
+
options: [
|
|
404
|
+
{
|
|
405
|
+
id: 'approve',
|
|
406
|
+
label: copy.approve,
|
|
407
|
+
description: format(copy.approved, language, { local }),
|
|
408
|
+
},
|
|
409
|
+
{ id: 'defer', label: copy.defer, description: copy.deferred },
|
|
410
|
+
],
|
|
411
|
+
}));
|
|
495
412
|
const previousFallback = (turkish) => ({
|
|
496
413
|
questionnaireId: fallbackId,
|
|
497
414
|
language: turkish ? 'tr' : 'en',
|
|
@@ -514,10 +431,10 @@ export function registerWorktreeTools(server, service) {
|
|
|
514
431
|
],
|
|
515
432
|
});
|
|
516
433
|
const fallbackForm = await askQuestionnaire(server, service, {
|
|
517
|
-
...
|
|
434
|
+
...definitions[0],
|
|
518
435
|
repoRoot: input.repoRoot,
|
|
519
436
|
presentation: input.presentation,
|
|
520
|
-
}, context, [
|
|
437
|
+
}, context, [...definitions, previousFallback(true), previousFallback(false)], owner);
|
|
521
438
|
if (askFailed(fallbackForm))
|
|
522
439
|
return fallbackForm;
|
|
523
440
|
const answer = await service.questionnaireResume({
|
|
@@ -571,7 +488,7 @@ export function registerWorktreeTools(server, service) {
|
|
|
571
488
|
language: languageTag.optional(),
|
|
572
489
|
}),
|
|
573
490
|
}, async (input, context) => {
|
|
574
|
-
const
|
|
491
|
+
const told = await service.language(input.language);
|
|
575
492
|
const inspection = await service.worktreeOperation('reconcile', input);
|
|
576
493
|
if (!inspection.ok ||
|
|
577
494
|
(!input.releaseUnowned && !input.retireLegacy && !input.forgetUnreadable))
|
|
@@ -590,21 +507,21 @@ export function registerWorktreeTools(server, service) {
|
|
|
590
507
|
});
|
|
591
508
|
const questionnaireId = forgetUnreadableQuestionId(item, input.decisionAttempt);
|
|
592
509
|
const folder = basename(item.repoRoot);
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
};
|
|
510
|
+
const named = { task: item.externalTaskId, folder };
|
|
511
|
+
const definitions = copies(forgetWording, 'forgetWorktree', told).map(({ language, copy }) => ({
|
|
512
|
+
questionnaireId,
|
|
513
|
+
language,
|
|
514
|
+
allowFreeText: false,
|
|
515
|
+
message: format(copy.message, language, named),
|
|
516
|
+
context: item.pendingDelivery
|
|
517
|
+
? `${copy.context} ${copy.pendingDelivery}`
|
|
518
|
+
: copy.context,
|
|
519
|
+
example: format(copy.example, language, named),
|
|
520
|
+
options: [
|
|
521
|
+
{ id: 'forget', label: copy.forget, description: copy.forgotten },
|
|
522
|
+
{ id: 'keep', label: copy.keep, description: copy.kept },
|
|
523
|
+
],
|
|
524
|
+
}));
|
|
608
525
|
const previous = (turkish) => ({
|
|
609
526
|
questionnaireId,
|
|
610
527
|
language: turkish ? 'tr' : 'en',
|
|
@@ -635,7 +552,7 @@ export function registerWorktreeTools(server, service) {
|
|
|
635
552
|
{ id: 'keep', label: turkish ? 'Takip etmeye devam et' : 'Keep tracking it' },
|
|
636
553
|
],
|
|
637
554
|
});
|
|
638
|
-
const form = await askQuestionnaire(server, service, { ...
|
|
555
|
+
const form = await askQuestionnaire(server, service, { ...definitions[0], repoRoot: input.repoRoot }, context, [...definitions, previous(true), previous(false)], {
|
|
639
556
|
tool: 'worktree.reconcile',
|
|
640
557
|
...(input.decisionAttempt ? { decisionAttempt: input.decisionAttempt } : {}),
|
|
641
558
|
retryArguments: json({
|
|
@@ -671,22 +588,25 @@ export function registerWorktreeTools(server, service) {
|
|
|
671
588
|
const missing = item.reasons.includes('worktree directory missing');
|
|
672
589
|
const questionnaireId = retireQuestionId(item, !missing, input.decisionAttempt);
|
|
673
590
|
const folder = basename(item.repoRoot);
|
|
674
|
-
const
|
|
675
|
-
const
|
|
676
|
-
const named = item.branch ?? (turkish ? 'yok' : 'none');
|
|
591
|
+
const definitions = copies(retireWording, 'retireWorktree', told).map(({ language, copy }) => {
|
|
592
|
+
const named = { folder, branch: item.branch ?? copy.noBranch };
|
|
677
593
|
return {
|
|
678
594
|
questionnaireId,
|
|
679
|
-
language
|
|
595
|
+
language,
|
|
680
596
|
allowFreeText: false,
|
|
681
|
-
message: missing ? copy.missing
|
|
682
|
-
context: copy.context
|
|
683
|
-
example: copy.example
|
|
597
|
+
message: format(missing ? copy.missing : copy.message, language, named),
|
|
598
|
+
context: `${copy.context} ${missing ? copy.contextMissing : copy.contextFolder}`,
|
|
599
|
+
example: format(missing ? copy.exampleMissing : copy.example, language, named),
|
|
684
600
|
options: [
|
|
685
|
-
{
|
|
601
|
+
{
|
|
602
|
+
id: 'retire',
|
|
603
|
+
label: copy.retire,
|
|
604
|
+
description: missing ? copy.retiredMissing : copy.retired,
|
|
605
|
+
},
|
|
686
606
|
{ id: 'keep', label: copy.keep, description: copy.kept },
|
|
687
607
|
],
|
|
688
608
|
};
|
|
689
|
-
};
|
|
609
|
+
});
|
|
690
610
|
const previous = (turkish) => ({
|
|
691
611
|
questionnaireId,
|
|
692
612
|
language: turkish ? 'tr' : 'en',
|
|
@@ -709,7 +629,7 @@ export function registerWorktreeTools(server, service) {
|
|
|
709
629
|
{ id: 'keep', label: turkish ? 'Kalsın' : 'Keep it' },
|
|
710
630
|
],
|
|
711
631
|
});
|
|
712
|
-
const form = await askQuestionnaire(server, service, { ...
|
|
632
|
+
const form = await askQuestionnaire(server, service, { ...definitions[0], repoRoot: input.repoRoot }, context, [...definitions, previous(true), previous(false)]);
|
|
713
633
|
if (askFailed(form)) {
|
|
714
634
|
refused.push({
|
|
715
635
|
repoRoot: item.repoRoot,
|
|
@@ -763,21 +683,18 @@ export function registerWorktreeTools(server, service) {
|
|
|
763
683
|
decisionAttempt: input.decisionAttempt,
|
|
764
684
|
}));
|
|
765
685
|
const questionnaireId = 'worktree-release-unowned-' + digest;
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
],
|
|
779
|
-
};
|
|
780
|
-
};
|
|
686
|
+
const definitions = copies(unownedWording, 'releaseUnowned', told).map(({ language, copy }) => ({
|
|
687
|
+
questionnaireId,
|
|
688
|
+
language,
|
|
689
|
+
allowFreeText: false,
|
|
690
|
+
message: format(copy.message, language, { folder: basename(entry.repoRoot) }),
|
|
691
|
+
context: copy.context,
|
|
692
|
+
example: format(copy.example, language, { commit: entry.baseCommit.slice(0, 12) }),
|
|
693
|
+
options: [
|
|
694
|
+
{ id: 'release_unowned', label: copy.release, description: copy.released },
|
|
695
|
+
{ id: 'preserve', label: copy.preserve, description: copy.preserved },
|
|
696
|
+
],
|
|
697
|
+
}));
|
|
781
698
|
const previous = (turkish) => ({
|
|
782
699
|
questionnaireId,
|
|
783
700
|
language: turkish ? 'tr' : 'en',
|
|
@@ -795,7 +712,7 @@ export function registerWorktreeTools(server, service) {
|
|
|
795
712
|
{ id: 'preserve', label: turkish ? 'Korumaya devam et' : 'Keep protected' },
|
|
796
713
|
],
|
|
797
714
|
});
|
|
798
|
-
const form = await askQuestionnaire(server, service, { ...
|
|
715
|
+
const form = await askQuestionnaire(server, service, { ...definitions[0], repoRoot: input.repoRoot }, context, [...definitions, previous(true), previous(false)]);
|
|
799
716
|
if (askFailed(form))
|
|
800
717
|
return form;
|
|
801
718
|
const decision = await service.questionnaireResume({
|
|
@@ -828,7 +745,7 @@ export function registerWorktreeTools(server, service) {
|
|
|
828
745
|
language: languageTag.optional(),
|
|
829
746
|
}),
|
|
830
747
|
}, async (input, context) => {
|
|
831
|
-
const
|
|
748
|
+
const told = await service.language(input.language);
|
|
832
749
|
if (input.deliveryOutcome !== 'cancelled')
|
|
833
750
|
return output(await service.worktreeOperation('release', input));
|
|
834
751
|
const state = await service.worktreeFolder(input);
|
|
@@ -841,21 +758,22 @@ export function registerWorktreeTools(server, service) {
|
|
|
841
758
|
...input,
|
|
842
759
|
decisionId: questionnaireId,
|
|
843
760
|
}));
|
|
844
|
-
const
|
|
845
|
-
const copy = cancelCopy[turkish ? 'tr' : 'en'];
|
|
761
|
+
const definitions = copies(cancelWording, 'cancelDelivery', told).map(({ language, copy }) => {
|
|
846
762
|
const keep = { id: 'keep', label: copy.keep, description: copy.kept };
|
|
847
763
|
return {
|
|
848
764
|
questionnaireId,
|
|
849
|
-
language
|
|
765
|
+
language,
|
|
850
766
|
allowFreeText: false,
|
|
851
|
-
message: copy.message
|
|
852
|
-
context:
|
|
767
|
+
message: format(copy.message, language, { task: input.externalTaskId }),
|
|
768
|
+
context: folder.clean
|
|
769
|
+
? copy.context
|
|
770
|
+
: `${copy.context} ${folder.managed ? copy.uncommittedManaged : copy.uncommittedOwn}`,
|
|
853
771
|
example: copy.example,
|
|
854
772
|
options: folder.clean || !folder.managed
|
|
855
773
|
? [{ id: 'release', label: copy.release, description: copy.released }, keep]
|
|
856
774
|
: [{ id: 'save_and_release', label: copy.save, description: copy.saved }, keep],
|
|
857
775
|
};
|
|
858
|
-
};
|
|
776
|
+
});
|
|
859
777
|
const previous = (turkish) => ({
|
|
860
778
|
questionnaireId,
|
|
861
779
|
language: turkish ? 'tr' : 'en',
|
|
@@ -901,7 +819,7 @@ export function registerWorktreeTools(server, service) {
|
|
|
901
819
|
},
|
|
902
820
|
],
|
|
903
821
|
});
|
|
904
|
-
const form = await askQuestionnaire(server, service, { ...
|
|
822
|
+
const form = await askQuestionnaire(server, service, { ...definitions[0], repoRoot: input.repoRoot }, context, [...definitions, previous(true), previous(false)]);
|
|
905
823
|
if (askFailed(form))
|
|
906
824
|
return form;
|
|
907
825
|
const decision = await service.questionnaireResume({
|