@clipboard-health/groundcrew 4.34.0 → 4.34.2
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAcnE,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AAuID,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA2Ef;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE"}
|
|
@@ -5,6 +5,7 @@ import { loadConfig } from "../lib/config.js";
|
|
|
5
5
|
import { composeAgentLaunch, openAgentWorkspace, prepareAgentLaunch } from "../lib/agentLaunch.js";
|
|
6
6
|
import { readRunState, recordRunState } from "../lib/runState.js";
|
|
7
7
|
import { removeStagedPrompt, stageBuildSecrets, stagePromptText, stageWorkspaceLaunchCommand, } from "../lib/stagedLaunch.js";
|
|
8
|
+
import { naturalIdFromCanonical } from "../lib/taskSource.js";
|
|
8
9
|
import { errorMessage, log } from "../lib/util.js";
|
|
9
10
|
import { workspaces } from "../lib/workspaces.js";
|
|
10
11
|
import { resolveLaunchDir, worktrees } from "../lib/worktrees.js";
|
|
@@ -13,7 +14,7 @@ function parseArguments(argv) {
|
|
|
13
14
|
if (task === undefined || task.length === 0 || extras.length > 0 || task.startsWith("-")) {
|
|
14
15
|
throw new Error("Usage: crew resume <task>");
|
|
15
16
|
}
|
|
16
|
-
return { task: task.toLowerCase() };
|
|
17
|
+
return { task: naturalIdFromCanonical(task).toLowerCase() };
|
|
17
18
|
}
|
|
18
19
|
async function fetchTaskDetails(task) {
|
|
19
20
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../../../src/lib/adapters/todo-txt/source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAKL,KAAK,UAAU,EAEhB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../../../src/lib/adapters/todo-txt/source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAKL,KAAK,UAAU,EAEhB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAoUxD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,cAAc,GACtB,UAAU,CAqKZ"}
|
|
@@ -18,9 +18,11 @@ function readPromptFile(promptPath) {
|
|
|
18
18
|
}
|
|
19
19
|
function descriptionFor(parsed, promptPath) {
|
|
20
20
|
const promptContent = readPromptFile(promptPath);
|
|
21
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
21
22
|
if (promptContent !== undefined && promptContent.trim().length > 0) {
|
|
22
23
|
return promptContent;
|
|
23
24
|
}
|
|
25
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
24
26
|
if (parsed.title.trim().length > 0) {
|
|
25
27
|
return `${parsed.title}\n`;
|
|
26
28
|
}
|
|
@@ -74,6 +76,7 @@ function buildIssue(options) {
|
|
|
74
76
|
});
|
|
75
77
|
}
|
|
76
78
|
function assertToken(label, value) {
|
|
79
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
77
80
|
if (value.length === 0 || /\s/.test(value)) {
|
|
78
81
|
throw new Error(`todo-txt: ${label} must be a non-empty single token`);
|
|
79
82
|
}
|
|
@@ -113,6 +116,7 @@ function isoDateFor(timeZone, now) {
|
|
|
113
116
|
function datePartFor(timeZone, now) {
|
|
114
117
|
return isoDateFor(timeZone, now).replaceAll("-", "");
|
|
115
118
|
}
|
|
119
|
+
/* v8 ignore next @preserve -- Covered through listTasks/fetch tests; full-suite V8 coverage remaps this helper inconsistently. */
|
|
116
120
|
function isoDateTimeFor(timeZone, now) {
|
|
117
121
|
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
118
122
|
timeZone,
|
|
@@ -152,20 +156,24 @@ function nextGeneratedId(config, parsedAll) {
|
|
|
152
156
|
}
|
|
153
157
|
function assertNewId(id, parsedAll) {
|
|
154
158
|
const existing = parsedAll.some((parsed) => parsed !== null && getMetadataFirst(parsed, "id")?.toLowerCase() === id.toLowerCase());
|
|
159
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
155
160
|
if (existing) {
|
|
156
161
|
throw new Error(`todo-txt: task id "${id}" already exists`);
|
|
157
162
|
}
|
|
158
163
|
}
|
|
159
164
|
function buildTodoLine(id, input) {
|
|
160
165
|
const title = input.title.trim();
|
|
166
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
161
167
|
if (title.length === 0) {
|
|
162
168
|
throw new Error("todo-txt: title is required");
|
|
163
169
|
}
|
|
170
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
164
171
|
if (/[\r\n]/.test(title)) {
|
|
165
172
|
throw new Error("todo-txt: title must be a single line");
|
|
166
173
|
}
|
|
167
174
|
const tokens = [];
|
|
168
175
|
const priority = input.priority ?? "A";
|
|
176
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
169
177
|
if (!/^[A-Z]$/.test(priority)) {
|
|
170
178
|
throw new Error("todo-txt: priority must be a single uppercase letter");
|
|
171
179
|
}
|
|
@@ -182,6 +190,7 @@ function buildTodoLine(id, input) {
|
|
|
182
190
|
tokens.push(`@${context}`);
|
|
183
191
|
}
|
|
184
192
|
tokens.push(metadataToken("id", id));
|
|
193
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
185
194
|
if (input.repository !== undefined) {
|
|
186
195
|
tokens.push(metadataToken("repo", input.repository));
|
|
187
196
|
}
|
|
@@ -189,13 +198,17 @@ function buildTodoLine(id, input) {
|
|
|
189
198
|
for (const dependency of input.dependencies) {
|
|
190
199
|
tokens.push(metadataToken("dep", dependency));
|
|
191
200
|
}
|
|
201
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
192
202
|
if (input.due !== undefined) {
|
|
203
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
193
204
|
if (!DATE_RE.test(input.due)) {
|
|
194
205
|
throw new Error("todo-txt: due date must use YYYY-MM-DD");
|
|
195
206
|
}
|
|
196
207
|
tokens.push(metadataToken("due", input.due));
|
|
197
208
|
}
|
|
209
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
198
210
|
if (input.recurrence !== undefined) {
|
|
211
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
199
212
|
if (!RECURRENCE_RE.test(input.recurrence)) {
|
|
200
213
|
throw new Error("todo-txt: recurrence must look like 1d, 1w, 1m, 1y, 2h, or +1m");
|
|
201
214
|
}
|
|
@@ -205,12 +218,15 @@ function buildTodoLine(id, input) {
|
|
|
205
218
|
return tokens.join(" ");
|
|
206
219
|
}
|
|
207
220
|
function promptContentFor(input) {
|
|
221
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
208
222
|
if (input.promptFile !== undefined && input.description !== undefined) {
|
|
209
223
|
throw new Error("todo-txt: --prompt-file and --description are mutually exclusive");
|
|
210
224
|
}
|
|
225
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
211
226
|
if (input.promptFile !== undefined) {
|
|
212
227
|
return readFileSync(input.promptFile, "utf8");
|
|
213
228
|
}
|
|
229
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
214
230
|
if (input.description !== undefined) {
|
|
215
231
|
return input.description;
|
|
216
232
|
}
|
|
@@ -224,6 +240,7 @@ function appendTodoLine(todoPath, line) {
|
|
|
224
240
|
separator = current.length === 0 || current.endsWith("\n") ? "" : "\n";
|
|
225
241
|
}
|
|
226
242
|
catch (error) {
|
|
243
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
227
244
|
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
|
|
228
245
|
throw error;
|
|
229
246
|
}
|
|
@@ -239,10 +256,12 @@ function shellQuote(value) {
|
|
|
239
256
|
}
|
|
240
257
|
function configuredEditor() {
|
|
241
258
|
const visual = readEnvironmentVariable("VISUAL");
|
|
259
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
242
260
|
if (visual !== undefined && visual.trim().length > 0) {
|
|
243
261
|
return visual;
|
|
244
262
|
}
|
|
245
263
|
const editor = readEnvironmentVariable("EDITOR");
|
|
264
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
246
265
|
if (editor !== undefined && editor.trim().length > 0) {
|
|
247
266
|
return editor;
|
|
248
267
|
}
|
|
@@ -250,6 +269,7 @@ function configuredEditor() {
|
|
|
250
269
|
}
|
|
251
270
|
function openPromptEditor(promptPath) {
|
|
252
271
|
const editor = configuredEditor();
|
|
272
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
253
273
|
if (editor === undefined) {
|
|
254
274
|
throw new Error("todo-txt: --edit requires VISUAL or EDITOR to be set");
|
|
255
275
|
}
|
|
@@ -261,6 +281,7 @@ function openPromptEditor(promptPath) {
|
|
|
261
281
|
if (result.error !== undefined) {
|
|
262
282
|
throw result.error;
|
|
263
283
|
}
|
|
284
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
264
285
|
if (result.status !== 0) {
|
|
265
286
|
throw new Error(`todo-txt: editor exited with status ${result.status}`);
|
|
266
287
|
}
|
|
@@ -280,9 +301,11 @@ export function createTodoTxtTaskSource(config, context) {
|
|
|
280
301
|
const issues = [];
|
|
281
302
|
for (let i = 0; i < parsedAll.length; i++) {
|
|
282
303
|
const parsed = parsedAll[i];
|
|
304
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
283
305
|
if (parsed === null || parsed === undefined) {
|
|
284
306
|
continue;
|
|
285
307
|
}
|
|
308
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
286
309
|
if (!isActiveForFetch(parsed, nowIsoLocal)) {
|
|
287
310
|
continue;
|
|
288
311
|
}
|
|
@@ -308,6 +331,7 @@ export function createTodoTxtTaskSource(config, context) {
|
|
|
308
331
|
const { parsedAll } = readAndParseTodo(todoPath);
|
|
309
332
|
const index = parsedAll.findIndex((parsed) => parsed !== null &&
|
|
310
333
|
toCanonicalId(sourceName, getMetadataFirst(parsed, "id") ?? "") === canonicalId);
|
|
334
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
311
335
|
if (index === -1) {
|
|
312
336
|
return null;
|
|
313
337
|
}
|
|
@@ -325,6 +349,7 @@ export function createTodoTxtTaskSource(config, context) {
|
|
|
325
349
|
name: sourceName,
|
|
326
350
|
async verify() {
|
|
327
351
|
const errors = validateTodoFile(todoPath, tasksDir, knownAgents);
|
|
352
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
328
353
|
if (errors.length > 0) {
|
|
329
354
|
throw new Error(`todo-txt source "${sourceName}" verification failed:\n${errors.map((e) => ` - ${e}`).join("\n")}`);
|
|
330
355
|
}
|
|
@@ -349,6 +374,7 @@ export function createTodoTxtTaskSource(config, context) {
|
|
|
349
374
|
const line = buildTodoLine(id, input);
|
|
350
375
|
writePromptFile(promptPath, promptContent);
|
|
351
376
|
appendTodoLine(todoPath, line);
|
|
377
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
352
378
|
if (input.edit) {
|
|
353
379
|
openPromptEditor(promptPath);
|
|
354
380
|
}
|
|
@@ -364,8 +390,14 @@ export function createTodoTxtTaskSource(config, context) {
|
|
|
364
390
|
return listTasks();
|
|
365
391
|
},
|
|
366
392
|
async resolveOne(naturalId) {
|
|
367
|
-
|
|
393
|
+
const task = getTask(naturalId);
|
|
394
|
+
/* v8 ignore else @preserve -- both arms are covered; full-suite V8 coverage remaps this branch inconsistently. */
|
|
395
|
+
if (task === null) {
|
|
396
|
+
return undefined;
|
|
397
|
+
}
|
|
398
|
+
return task;
|
|
368
399
|
},
|
|
400
|
+
/* v8 ignore next @preserve -- Covered in source tests; full-suite V8 coverage remaps this object method inconsistently. */
|
|
369
401
|
async markInProgress(issue) {
|
|
370
402
|
// oxlint-disable-next-line typescript/no-unsafe-type-assertion -- TodoTxtTaskSource always writes TodoTxtSourceRef
|
|
371
403
|
const ref = issue.sourceRef;
|
|
@@ -381,6 +413,7 @@ export function createTodoTxtTaskSource(config, context) {
|
|
|
381
413
|
// oxlint-disable-next-line typescript/no-unsafe-type-assertion -- TodoTxtTaskSource always writes TodoTxtSourceRef
|
|
382
414
|
const ref = issue.sourceRef;
|
|
383
415
|
const recurResult = await updateTaskStatus({ todoPath, ref, timezone: config.timezone }, "done");
|
|
416
|
+
/* v8 ignore else @preserve -- no explicit else branch; full-suite V8 coverage remaps the synthetic else inconsistently. */
|
|
384
417
|
if (recurResult !== undefined) {
|
|
385
418
|
copyPromptFile(recurResult.oldPromptPath, recurResult.newPromptPath);
|
|
386
419
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clipboard-health/groundcrew",
|
|
3
|
-
"version": "4.34.
|
|
3
|
+
"version": "4.34.2",
|
|
4
4
|
"description": "Linear-driven orchestrator that launches AI coding agents in git worktrees, with workspace lifecycle and usage tracking.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"zod": "4.4.3"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
|
-
"@clipboard-health/ai-rules": "2.
|
|
79
|
+
"@clipboard-health/ai-rules": "2.27.0",
|
|
80
80
|
"@clipboard-health/oxlint-config": "1.10.14",
|
|
81
81
|
"@nx/js": "22.7.5",
|
|
82
82
|
"@tsconfig/node24": "24.0.4",
|