@clipboard-health/groundcrew 3.1.2 → 3.1.3
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/README.md +31 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +12 -0
- package/dist/commands/cleaner.d.ts.map +1 -1
- package/dist/commands/cleaner.js +2 -0
- package/dist/commands/cleanupWorkspace.d.ts.map +1 -1
- package/dist/commands/cleanupWorkspace.js +2 -0
- package/dist/commands/interruptWorkspace.d.ts +8 -0
- package/dist/commands/interruptWorkspace.d.ts.map +1 -0
- package/dist/commands/interruptWorkspace.js +108 -0
- package/dist/commands/resumeWorkspace.d.ts +7 -0
- package/dist/commands/resumeWorkspace.d.ts.map +1 -0
- package/dist/commands/resumeWorkspace.js +163 -0
- package/dist/commands/setupWorkspace.d.ts.map +1 -1
- package/dist/commands/setupWorkspace.js +77 -79
- package/dist/commands/ticketDoctor.d.ts +18 -3
- package/dist/commands/ticketDoctor.d.ts.map +1 -1
- package/dist/commands/ticketDoctor.js +77 -8
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/lib/agentLaunch.d.ts +29 -0
- package/dist/lib/agentLaunch.d.ts.map +1 -0
- package/dist/lib/agentLaunch.js +53 -0
- package/dist/lib/runState.d.ts +46 -0
- package/dist/lib/runState.d.ts.map +1 -0
- package/dist/lib/runState.js +137 -0
- package/dist/lib/runStateCleanup.d.ts +4 -0
- package/dist/lib/runStateCleanup.d.ts.map +1 -0
- package/dist/lib/runStateCleanup.js +12 -0
- package/dist/lib/stagedLaunch.d.ts +32 -0
- package/dist/lib/stagedLaunch.d.ts.map +1 -0
- package/dist/lib/stagedLaunch.js +58 -0
- package/dist/lib/workspaces.d.ts +19 -1
- package/dist/lib/workspaces.d.ts.map +1 -1
- package/dist/lib/workspaces.js +29 -9
- package/dist/lib/worktrees.d.ts.map +1 -1
- package/dist/lib/worktrees.js +12 -4
- package/package.json +1 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { BUILD_SECRET_NAMES } from "./config.js";
|
|
5
|
+
import { shellSingleQuote } from "./launchCommand.js";
|
|
6
|
+
import { readEnvironmentVariable } from "./util.js";
|
|
7
|
+
function renderPromptTemplate(template, variables) {
|
|
8
|
+
return template
|
|
9
|
+
.replaceAll("{{ticket}}", variables.ticket)
|
|
10
|
+
.replaceAll("{{worktree}}", variables.worktree)
|
|
11
|
+
.replaceAll("{{title}}", variables.title)
|
|
12
|
+
.replaceAll("{{description}}", variables.description);
|
|
13
|
+
}
|
|
14
|
+
export function stagePromptText(input) {
|
|
15
|
+
const promptDir = mkdtempSync(join(tmpdir(), `${input.prefix}-${input.ticket}-`));
|
|
16
|
+
const promptFile = join(promptDir, "prompt.txt");
|
|
17
|
+
writeFileSync(promptFile, input.text);
|
|
18
|
+
return { directory: promptDir, file: promptFile };
|
|
19
|
+
}
|
|
20
|
+
export function stagePromptFromTemplate(input) {
|
|
21
|
+
return stagePromptText({
|
|
22
|
+
prefix: input.prefix,
|
|
23
|
+
ticket: input.ticket,
|
|
24
|
+
text: renderPromptTemplate(input.config.prompts.initial, input.variables),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Stage a `KEY='value'` env file for any populated build-time secret so
|
|
29
|
+
* the launch command can source it. Returns `undefined` when groundcrew
|
|
30
|
+
* has nothing to forward, leaving the launch command unchanged.
|
|
31
|
+
*/
|
|
32
|
+
export function stageBuildSecrets(promptDir) {
|
|
33
|
+
const lines = [];
|
|
34
|
+
for (const name of BUILD_SECRET_NAMES) {
|
|
35
|
+
const value = readEnvironmentVariable(name);
|
|
36
|
+
if (value === undefined || value.length === 0) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
lines.push(`${name}=${shellSingleQuote(value)}`);
|
|
40
|
+
}
|
|
41
|
+
if (lines.length === 0) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
const secretsFile = join(promptDir, "secrets.env");
|
|
45
|
+
writeFileSync(secretsFile, `${lines.join("\n")}\n`, { mode: 0o600 });
|
|
46
|
+
return secretsFile;
|
|
47
|
+
}
|
|
48
|
+
function stageLaunchScript(promptDir, command) {
|
|
49
|
+
const launcherFile = join(promptDir, "launch.sh");
|
|
50
|
+
writeFileSync(launcherFile, `#!/usr/bin/env bash\n${command}\n`, { mode: 0o700 });
|
|
51
|
+
return launcherFile;
|
|
52
|
+
}
|
|
53
|
+
export function stageWorkspaceLaunchCommand(promptDir, command) {
|
|
54
|
+
return `bash ${shellSingleQuote(stageLaunchScript(promptDir, command))}`;
|
|
55
|
+
}
|
|
56
|
+
export function removeStagedPrompt(directory) {
|
|
57
|
+
rmSync(directory, { recursive: true, force: true });
|
|
58
|
+
}
|
package/dist/lib/workspaces.d.ts
CHANGED
|
@@ -41,6 +41,22 @@ export type WorkspaceProbe = {
|
|
|
41
41
|
kind: "unavailable";
|
|
42
42
|
error?: unknown;
|
|
43
43
|
};
|
|
44
|
+
export type WorkspaceInterruptResult = {
|
|
45
|
+
kind: "interrupted";
|
|
46
|
+
} | {
|
|
47
|
+
kind: "missing";
|
|
48
|
+
} | {
|
|
49
|
+
kind: "unavailable";
|
|
50
|
+
error?: unknown;
|
|
51
|
+
};
|
|
52
|
+
export type WorkspaceCloseResult = {
|
|
53
|
+
kind: "closed";
|
|
54
|
+
} | {
|
|
55
|
+
kind: "missing";
|
|
56
|
+
} | {
|
|
57
|
+
kind: "unavailable";
|
|
58
|
+
error?: unknown;
|
|
59
|
+
};
|
|
44
60
|
export interface WorkspaceResolution {
|
|
45
61
|
requested: WorkspaceKindSetting;
|
|
46
62
|
resolved: WorkspaceKind;
|
|
@@ -53,10 +69,12 @@ interface ResolveArguments {
|
|
|
53
69
|
}
|
|
54
70
|
export declare function resolveWorkspaceKind(arguments_: ResolveArguments): WorkspaceResolution;
|
|
55
71
|
declare function probeWorkspaces(config: ResolvedConfig, signal?: AbortSignal): Promise<WorkspaceProbe>;
|
|
72
|
+
declare function interruptWorkspace(config: ResolvedConfig, name: string, signal?: AbortSignal): Promise<WorkspaceInterruptResult>;
|
|
56
73
|
export declare const workspaces: {
|
|
57
74
|
open(config: ResolvedConfig, spec: OpenSpec, signal?: AbortSignal): Promise<void>;
|
|
58
75
|
probe: typeof probeWorkspaces;
|
|
59
|
-
close(config: ResolvedConfig, name: string, signal?: AbortSignal): Promise<
|
|
76
|
+
close(config: ResolvedConfig, name: string, signal?: AbortSignal): Promise<WorkspaceCloseResult>;
|
|
77
|
+
interrupt: typeof interruptWorkspace;
|
|
60
78
|
accessHint(config: ResolvedConfig, name: string, signal?: AbortSignal): Promise<WorkspaceAccessHint | undefined>;
|
|
61
79
|
};
|
|
62
80
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/lib/workspaces.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAI1E,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C,MAAM,WAAW,SAAS;IACxB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/lib/workspaces.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAI1E,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C,MAAM,WAAW,SAAS;IACxB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,wBAAwB,GAChC;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAwU7C,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,oBAAoB,CAAC;IAChC,QAAQ,EAAE,aAAa,CAAC;IACxB,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,gBAAgB;IACxB,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,gBAAgB,CAAC;CACxB;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,gBAAgB,GAAG,mBAAmB,CAUtF;AAgOD,iBAAe,eAAe,CAC5B,MAAM,EAAE,cAAc,EACtB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CAezB;AAED,iBAAe,kBAAkB,CAC/B,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,wBAAwB,CAAC,CAenC;AAED,eAAO,MAAM,UAAU;IACf,IAAI,SAAS,cAAc,QAAQ,QAAQ,WAAW,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvF,KAAK;IACC,KAAK,SACD,cAAc,QAChB,MAAM,WACH,WAAW,GACnB,OAAO,CAAC,oBAAoB,CAAC;IAIhC,SAAS;IACH,UAAU,SACN,cAAc,QAChB,MAAM,WACH,WAAW,GACnB,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;CAI5C,CAAC"}
|
package/dist/lib/workspaces.js
CHANGED
|
@@ -226,25 +226,27 @@ const cmuxAdapter = {
|
|
|
226
226
|
// would always fail. The list failure has already been logged by
|
|
227
227
|
// `listCmuxRaw`; bail rather than guarantee a downstream error.
|
|
228
228
|
log(`cmux close-workspace skipped for ${name}: list-workspaces failed, no usable id`);
|
|
229
|
-
return;
|
|
229
|
+
return { kind: "unavailable" };
|
|
230
230
|
}
|
|
231
231
|
const match = raw.find((ws) => ws.title === name);
|
|
232
232
|
if (match === undefined) {
|
|
233
|
-
return;
|
|
233
|
+
return { kind: "missing" };
|
|
234
234
|
}
|
|
235
235
|
try {
|
|
236
236
|
await closeCmuxWorkspace(match.id, signal);
|
|
237
|
+
return { kind: "closed" };
|
|
237
238
|
}
|
|
238
239
|
catch (error) {
|
|
239
240
|
if (isSignalAborted(signal)) {
|
|
240
241
|
throw error;
|
|
241
242
|
}
|
|
242
243
|
const remaining = await listCmuxRaw(signal);
|
|
243
|
-
if (remaining
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
if (remaining === undefined) {
|
|
245
|
+
return { kind: "unavailable", error };
|
|
246
|
+
}
|
|
247
|
+
const isStillPresent = remaining.some((ws) => ws.title === name);
|
|
248
|
+
if (!isStillPresent) {
|
|
249
|
+
return { kind: "closed" };
|
|
248
250
|
}
|
|
249
251
|
throw error;
|
|
250
252
|
}
|
|
@@ -420,13 +422,14 @@ const tmuxAdapter = {
|
|
|
420
422
|
async close(name, signal) {
|
|
421
423
|
try {
|
|
422
424
|
await runWorkspaceCommand("tmux", ["kill-window", "-t", tmuxTarget(name)], signal);
|
|
425
|
+
return { kind: "closed" };
|
|
423
426
|
}
|
|
424
427
|
catch (error) {
|
|
425
428
|
if (isSignalAborted(signal)) {
|
|
426
429
|
throw error;
|
|
427
430
|
}
|
|
428
431
|
if (isTmuxNotFoundError(error)) {
|
|
429
|
-
return;
|
|
432
|
+
return { kind: "missing" };
|
|
430
433
|
}
|
|
431
434
|
throw error;
|
|
432
435
|
}
|
|
@@ -469,6 +472,22 @@ async function probeWorkspaces(config, signal) {
|
|
|
469
472
|
}
|
|
470
473
|
return { kind: "ok", names: new Set(raw.map((ws) => ws.name)) };
|
|
471
474
|
}
|
|
475
|
+
async function interruptWorkspace(config, name, signal) {
|
|
476
|
+
const probe = await probeWorkspaces(config, signal);
|
|
477
|
+
if (probe.kind === "unavailable") {
|
|
478
|
+
return { kind: "unavailable", ...(probe.error === undefined ? {} : { error: probe.error }) };
|
|
479
|
+
}
|
|
480
|
+
if (!probe.names.has(name)) {
|
|
481
|
+
return { kind: "missing" };
|
|
482
|
+
}
|
|
483
|
+
const result = await workspaces.close(config, name, signal);
|
|
484
|
+
if (result.kind === "unavailable") {
|
|
485
|
+
return result.error === undefined
|
|
486
|
+
? { kind: "unavailable" }
|
|
487
|
+
: { kind: "unavailable", error: result.error };
|
|
488
|
+
}
|
|
489
|
+
return { kind: "interrupted" };
|
|
490
|
+
}
|
|
472
491
|
export const workspaces = {
|
|
473
492
|
async open(config, spec, signal) {
|
|
474
493
|
const adapter = await adapterFor(config, signal);
|
|
@@ -477,8 +496,9 @@ export const workspaces = {
|
|
|
477
496
|
probe: probeWorkspaces,
|
|
478
497
|
async close(config, name, signal) {
|
|
479
498
|
const adapter = await adapterFor(config, signal);
|
|
480
|
-
await adapter.close(name, signal);
|
|
499
|
+
return await adapter.close(name, signal);
|
|
481
500
|
},
|
|
501
|
+
interrupt: interruptWorkspace,
|
|
482
502
|
async accessHint(config, name, signal) {
|
|
483
503
|
const adapter = await adapterFor(config, signal);
|
|
484
504
|
return adapter.accessHint(name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worktrees.d.ts","sourceRoot":"","sources":["../../src/lib/worktrees.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,KAAK,cAAc,EAAc,MAAM,iBAAiB,CAAC;AAIlE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC;AAElC,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,SAAgB,GAAG,EAAE,MAAM,CAAC;IAE5B,YAAmB,GAAG,EAAE,MAAM,EAI7B;CACF;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,0BAA0B,CAEhG;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAaD,iBAAS,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAqOD,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AA6ExB,iBAAS,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,aAAa,EAAE,CAErD;AAED,iBAAS,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAE7E;AAED,iBAAe,MAAM,CACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,YAAY,EAClB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,aAAa,CAAC,CAQxB;AAED,iBAAe,MAAM,CACnB,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,aAAa,EACpB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GAClD,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,MAAM,MAAM,YAAY,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAEjE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,sCAAsC;IACtC,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,wDAAwD;IACxD,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,cAAc,EAAE,cAAc,CAAC;CAChC;
|
|
1
|
+
{"version":3,"file":"worktrees.d.ts","sourceRoot":"","sources":["../../src/lib/worktrees.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,KAAK,cAAc,EAAc,MAAM,iBAAiB,CAAC;AAIlE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC;AAElC,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,SAAgB,GAAG,EAAE,MAAM,CAAC;IAE5B,YAAmB,GAAG,EAAE,MAAM,EAI7B;CACF;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,0BAA0B,CAEhG;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAaD,iBAAS,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAqOD,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AA6ExB,iBAAS,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,aAAa,EAAE,CAErD;AAED,iBAAS,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAE7E;AAED,iBAAe,MAAM,CACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,YAAY,EAClB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,aAAa,CAAC,CAQxB;AAED,iBAAe,MAAM,CACnB,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,aAAa,EACpB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GAClD,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,MAAM,MAAM,YAAY,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAEjE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,sCAAsC;IACtC,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,wDAAwD;IACxD,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,cAAc,EAAE,cAAc,CAAC;CAChC;AAyBD,iBAAe,QAAQ,CACrB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,SAAS,aAAa,EAAE,EACjC,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GAClD,OAAO,CAAC,cAAc,CAAC,CAiDzB;AAED,iBAAe,gBAAgB,CAAC,KAAK,EAAE;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAE7B;AAED,eAAO,MAAM,SAAS;;;;;;;;CAQrB,CAAC"}
|
package/dist/lib/worktrees.js
CHANGED
|
@@ -284,6 +284,13 @@ async function remove(config, entry, options) {
|
|
|
284
284
|
...signalProperty(options?.signal),
|
|
285
285
|
});
|
|
286
286
|
}
|
|
287
|
+
async function closeWorkspaceForTeardown(config, ticket, signal) {
|
|
288
|
+
const closeResult = await workspaces.close(config, ticket, signal);
|
|
289
|
+
return closeResult.kind === "closed";
|
|
290
|
+
}
|
|
291
|
+
function shouldCloseWorkspaceForTeardown(ticket, workspaceProbe, liveNames, closedTickets) {
|
|
292
|
+
return (!closedTickets.has(ticket) && (workspaceProbe.kind === "unavailable" || liveNames.has(ticket)));
|
|
293
|
+
}
|
|
287
294
|
// A flaky cmux/tmux must not abort the batch — otherwise every on-disk
|
|
288
295
|
// worktree gets stranded. The probe verdict is captured on the result and
|
|
289
296
|
// removal proceeds with no live-workspace knowledge (so no close attempts).
|
|
@@ -307,12 +314,13 @@ async function teardown(config, entries, options) {
|
|
|
307
314
|
workspaceProbe,
|
|
308
315
|
};
|
|
309
316
|
for (const entry of entries) {
|
|
310
|
-
if (
|
|
311
|
-
(workspaceProbe.kind === "unavailable" || liveNames.has(entry.ticket))) {
|
|
317
|
+
if (shouldCloseWorkspaceForTeardown(entry.ticket, workspaceProbe, liveNames, closedTickets)) {
|
|
312
318
|
try {
|
|
313
319
|
// oxlint-disable-next-line no-await-in-loop -- teardown is intentionally sequential per ticket
|
|
314
|
-
await
|
|
315
|
-
|
|
320
|
+
const closed = await closeWorkspaceForTeardown(config, entry.ticket, options?.signal);
|
|
321
|
+
if (closed) {
|
|
322
|
+
result.closed.push(entry.ticket);
|
|
323
|
+
}
|
|
316
324
|
}
|
|
317
325
|
catch (error) {
|
|
318
326
|
if (options?.signal?.aborted === true) {
|
package/package.json
CHANGED