@clipboard-health/groundcrew 4.52.4 → 4.52.5
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.
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface WorkingDirectoryDeps {
|
|
2
|
+
cwd: () => string;
|
|
3
|
+
chdir: (directory: string) => void;
|
|
4
|
+
exists: (directory: string) => boolean;
|
|
5
|
+
/** The shell's logical working directory; still set after the directory is removed. */
|
|
6
|
+
pwd: string | undefined;
|
|
7
|
+
home: string;
|
|
8
|
+
}
|
|
9
|
+
export interface RecoveredWorkingDirectory {
|
|
10
|
+
missing: string | undefined;
|
|
11
|
+
recovered: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* When the shell's working directory was removed (e.g. `crew cleanup` run from
|
|
15
|
+
* inside a worktree an earlier cleanup deleted), every `process.cwd()` call —
|
|
16
|
+
* including cosmiconfig's at module load — throws ENOENT. Move to the nearest
|
|
17
|
+
* surviving ancestor of `$PWD`, or the home directory, so commands can still run.
|
|
18
|
+
* Returns undefined when the working directory is intact.
|
|
19
|
+
*/
|
|
20
|
+
export declare function recoverWorkingDirectory(deps?: WorkingDirectoryDeps): RecoveredWorkingDirectory | undefined;
|
|
21
|
+
//# sourceMappingURL=workingDirectory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workingDirectory.d.ts","sourceRoot":"","sources":["../../src/lib/workingDirectory.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,uFAAuF;IACvF,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,GAAE,oBAAoC,GACzC,yBAAyB,GAAG,SAAS,CAUvC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { readEnvironmentVariable } from "./util.js";
|
|
5
|
+
/**
|
|
6
|
+
* When the shell's working directory was removed (e.g. `crew cleanup` run from
|
|
7
|
+
* inside a worktree an earlier cleanup deleted), every `process.cwd()` call —
|
|
8
|
+
* including cosmiconfig's at module load — throws ENOENT. Move to the nearest
|
|
9
|
+
* surviving ancestor of `$PWD`, or the home directory, so commands can still run.
|
|
10
|
+
* Returns undefined when the working directory is intact.
|
|
11
|
+
*/
|
|
12
|
+
export function recoverWorkingDirectory(deps = defaultDeps()) {
|
|
13
|
+
if (!isMissingWorkingDirectory(deps)) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
const ancestor = existingAncestors(deps).find((directory) => tryChdir({ deps, directory }));
|
|
17
|
+
if (ancestor !== undefined) {
|
|
18
|
+
return { missing: deps.pwd, recovered: ancestor };
|
|
19
|
+
}
|
|
20
|
+
deps.chdir(deps.home);
|
|
21
|
+
return { missing: deps.pwd, recovered: deps.home };
|
|
22
|
+
}
|
|
23
|
+
function defaultDeps() {
|
|
24
|
+
return {
|
|
25
|
+
cwd: () => process.cwd(),
|
|
26
|
+
chdir: (directory) => {
|
|
27
|
+
process.chdir(directory);
|
|
28
|
+
},
|
|
29
|
+
exists: existsSync,
|
|
30
|
+
pwd: readEnvironmentVariable("PWD"),
|
|
31
|
+
home: homedir(),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function isMissingWorkingDirectory(deps) {
|
|
35
|
+
try {
|
|
36
|
+
deps.cwd();
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function existingAncestors(deps) {
|
|
47
|
+
if (deps.pwd === undefined || !path.isAbsolute(deps.pwd)) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
const candidates = [];
|
|
51
|
+
let current = path.resolve(deps.pwd);
|
|
52
|
+
for (;;) {
|
|
53
|
+
if (deps.exists(current)) {
|
|
54
|
+
candidates.push(current);
|
|
55
|
+
}
|
|
56
|
+
const parent = path.dirname(current);
|
|
57
|
+
if (parent === current) {
|
|
58
|
+
return candidates;
|
|
59
|
+
}
|
|
60
|
+
current = parent;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function tryChdir(input) {
|
|
64
|
+
const { deps, directory } = input;
|
|
65
|
+
try {
|
|
66
|
+
deps.chdir(directory);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { recoverWorkingDirectory } from "./lib/workingDirectory.js";
|
|
2
2
|
try {
|
|
3
|
+
// Must run before cli.ts loads: config.ts builds its cosmiconfig explorer at
|
|
4
|
+
// import time, which reads process.cwd() and crashes if the directory is gone.
|
|
5
|
+
const recovery = recoverWorkingDirectory();
|
|
6
|
+
if (recovery !== undefined) {
|
|
7
|
+
process.stderr.write(`Current directory ${recovery.missing ?? "(unknown)"} no longer exists; continuing from ${recovery.recovered}\n`);
|
|
8
|
+
}
|
|
9
|
+
const { run } = await import("./cli.js");
|
|
3
10
|
await run(process.argv.slice(2));
|
|
4
11
|
}
|
|
5
12
|
catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clipboard-health/groundcrew",
|
|
3
|
-
"version": "4.52.
|
|
3
|
+
"version": "4.52.5",
|
|
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",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"@tsconfig/strictest": "2.0.8",
|
|
85
85
|
"@types/node": "26.5.1",
|
|
86
86
|
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
87
|
-
"@vitest/coverage-v8": "5.0.
|
|
87
|
+
"@vitest/coverage-v8": "5.0.2",
|
|
88
88
|
"dependency-cruiser": "18.3.1",
|
|
89
89
|
"husky": "9.1.7",
|
|
90
90
|
"jscpd": "5.2.1",
|
|
@@ -94,10 +94,10 @@
|
|
|
94
94
|
"nx": "23.1.0",
|
|
95
95
|
"oxfmt": "0.63.0",
|
|
96
96
|
"oxlint": "1.78.0",
|
|
97
|
-
"oxlint-tsgolint": "7.0.
|
|
97
|
+
"oxlint-tsgolint": "7.0.2003",
|
|
98
98
|
"syncpack": "15.3.3",
|
|
99
|
-
"vite": "8.3.
|
|
100
|
-
"vitest": "5.0.
|
|
99
|
+
"vite": "8.3.1",
|
|
100
|
+
"vitest": "5.0.2"
|
|
101
101
|
},
|
|
102
102
|
"engines": {
|
|
103
103
|
"node": "24.14.1",
|