@clipboard-health/groundcrew 4.46.6 → 4.47.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.
@@ -1 +1 @@
1
- {"version":3,"file":"openWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/openWorkspace.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AActF,UAAU,gBAAgB;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA6JD,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAyGf;AA4ID,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAE3E;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpE"}
1
+ {"version":3,"file":"openWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/openWorkspace.ts"],"names":[],"mappings":"AAKA,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAetF,UAAU,gBAAgB;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA6JD,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA6Gf;AA4ID,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAE3E;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpE"}
@@ -1,10 +1,12 @@
1
1
  import { existsSync, readFileSync, rmSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { composeAgentLaunch, openAgentWorkspace, prepareAgentLaunch } from "../lib/agentLaunch.js";
4
+ import { inferAgentCommandName } from "../lib/launchCommand.js";
4
5
  import { loadConfig, repositoryBaseDir } from "../lib/config.js";
5
6
  import { resolvePullRequest } from "../lib/pullRequests.js";
6
7
  import { resolvePrepareWorktreeCommand } from "../lib/repositoryHooks.js";
7
8
  import { recordRunState, readRunState } from "../lib/runState.js";
9
+ import { seedLaunchWorkspaceTrust } from "../lib/seedLaunchWorkspaceTrust.js";
8
10
  import { stageBuildSecrets, stagePromptText, stageWorkspaceLaunchCommand, } from "../lib/stagedLaunch.js";
9
11
  import { normalizePlainTaskId } from "../lib/taskId.js";
10
12
  import { debug, errorMessage, log, okMark } from "../lib/util.js";
@@ -159,6 +161,10 @@ export async function openWorkspace(config, options) {
159
161
  defaultHooks: config.defaults.hooks,
160
162
  });
161
163
  const secretsFile = prepareWorktreeCommand === undefined ? undefined : stageBuildSecrets(stagedPrompt.directory);
164
+ seedLaunchWorkspaceTrust({
165
+ agentCommandName: inferAgentCommandName(definition.cmd),
166
+ launchDir,
167
+ });
162
168
  let launchCommand;
163
169
  ({ launchCommand, srtSettingsDir } = composeAgentLaunch({
164
170
  runner,
@@ -1 +1 @@
1
- {"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiBzF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAyKD,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAoGf;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE"}
1
+ {"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAsBzF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAyKD,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAwGf;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE"}
@@ -3,8 +3,9 @@ import { getLinearClient } from "../lib/adapters/linear/client.js";
3
3
  import { isLinearEnabled, sourcesFromConfig } from "../lib/buildSources.js";
4
4
  import { loadConfig } from "../lib/config.js";
5
5
  import { composeAgentLaunch, openAgentWorkspace, prepareAgentLaunch } from "../lib/agentLaunch.js";
6
- import { withResumeArgs, workerEnvironmentForTask } from "../lib/launchCommand.js";
6
+ import { inferAgentCommandName, withResumeArgs, workerEnvironmentForTask, } from "../lib/launchCommand.js";
7
7
  import { readRunState, recordRunState } from "../lib/runState.js";
8
+ import { seedLaunchWorkspaceTrust } from "../lib/seedLaunchWorkspaceTrust.js";
8
9
  import { taskSupportsCompletionCommand } from "../lib/sourceCapabilities.js";
9
10
  import { removeStagedPrompt, stageBuildSecrets, stagePromptText, stageWorkspaceLaunchCommand, } from "../lib/stagedLaunch.js";
10
11
  import { taskSourceWritePathsForCompletion } from "../lib/taskSourceFilesystem.js";
@@ -183,6 +184,10 @@ export async function resumeWorkspace(config, options) {
183
184
  workingDir: launchDir,
184
185
  })
185
186
  : undefined;
187
+ seedLaunchWorkspaceTrust({
188
+ agentCommandName: inferAgentCommandName(launchDefinition.cmd),
189
+ launchDir,
190
+ });
186
191
  ({ launchCommand, srtSettingsDir } = composeAgentLaunch({
187
192
  runner,
188
193
  networkEgress,
@@ -1 +1 @@
1
- {"version":3,"file":"setupWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/setupWorkspace.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAyBnE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6FAA6F;IAC7F,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAuBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,qBAAqB,EAC9B,UAAU,GAAE,wBAA6B,GACxC,OAAO,CAAC,IAAI,CAAC,CAiJf;AA8MD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CAkDf"}
1
+ {"version":3,"file":"setupWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/setupWorkspace.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA0BnE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6FAA6F;IAC7F,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAuBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,qBAAqB,EAC9B,UAAU,GAAE,wBAA6B,GACxC,OAAO,CAAC,IAAI,CAAC,CAqJf;AA8MD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CAkDf"}
@@ -1,11 +1,12 @@
1
1
  import { rmSync } from "node:fs";
2
2
  import { loadConfig } from "../lib/config.js";
3
3
  import { composeAgentLaunch, openAgentWorkspace, prepareAgentLaunch } from "../lib/agentLaunch.js";
4
+ import { inferAgentCommandName, workerEnvironmentForTask } from "../lib/launchCommand.js";
4
5
  import { createBoard } from "../lib/board.js";
5
6
  import { buildSources, sourcesFromConfig } from "../lib/buildSources.js";
6
- import { workerEnvironmentForTask } from "../lib/launchCommand.js";
7
7
  import { resolvePrepareWorktreeCommand } from "../lib/repositoryHooks.js";
8
8
  import { recordRunState } from "../lib/runState.js";
9
+ import { seedLaunchWorkspaceTrust } from "../lib/seedLaunchWorkspaceTrust.js";
9
10
  import { sourceSupportsMarkDone } from "../lib/sourceCapabilities.js";
10
11
  import { stageBuildSecrets, stagePromptFromTemplate, stageWorkspaceLaunchCommand, } from "../lib/stagedLaunch.js";
11
12
  import { taskSourceWritePathsForCompletion } from "../lib/taskSourceFilesystem.js";
@@ -103,6 +104,10 @@ export async function setupWorkspace(config, options, runOptions = {}) {
103
104
  workingDir: launchDir,
104
105
  })
105
106
  : undefined;
107
+ seedLaunchWorkspaceTrust({
108
+ agentCommandName: inferAgentCommandName(definition.cmd),
109
+ launchDir,
110
+ });
106
111
  const { launchCommand, srtSettingsDir: stagedSrtSettingsDir } = composeAgentLaunch({
107
112
  runner,
108
113
  networkEgress,
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/lib/adapters/linear/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,QAAA,MAAM,sBAAsB,YAAI,2BAA2B,EAAE,gBAAgB,CAAU,CAAC;AAExF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,wBAAgB,mBAAmB,IAAI,oBAAoB,GAAG,SAAS,CAatE;AAED,wBAAgB,eAAe,IAAI,YAAY,CAQ9C;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,YAAY,GAAG,MAAM,YAAY,CAMhF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/lib/adapters/linear/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,QAAA,MAAM,sBAAsB,YAAI,2BAA2B,EAAE,gBAAgB,CAAU,CAAC;AAExF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,wBAAgB,mBAAmB,IAAI,oBAAoB,GAAG,SAAS,CActE;AAED,wBAAgB,eAAe,IAAI,YAAY,CAQ9C;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,YAAY,GAAG,MAAM,YAAY,CAMhF"}
@@ -8,6 +8,7 @@ export function resolveLinearApiKey() {
8
8
  if (value === undefined) {
9
9
  continue;
10
10
  }
11
+ /* v8 ignore next */
11
12
  if (value.length === 0) {
12
13
  continue;
13
14
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Record agent workspace trust for a launch directory. Fail-open: logs on
3
+ * error and returns so agent launch can continue.
4
+ */
5
+ export declare function seedLaunchWorkspaceTrust(input: {
6
+ agentCommandName: string;
7
+ launchDir: string;
8
+ }): void;
9
+ //# sourceMappingURL=seedLaunchWorkspaceTrust.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seedLaunchWorkspaceTrust.d.ts","sourceRoot":"","sources":["../../src/lib/seedLaunchWorkspaceTrust.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,IAAI,CASP"}
@@ -0,0 +1,17 @@
1
+ import { agentTrustDir } from "agent-trust";
2
+ import { writeError } from "./util.js";
3
+ const GROUNDCREW_TRUST_METHOD = "groundcrew-auto-trust";
4
+ /**
5
+ * Record agent workspace trust for a launch directory. Fail-open: logs on
6
+ * error and returns so agent launch can continue.
7
+ */
8
+ export function seedLaunchWorkspaceTrust(input) {
9
+ const result = agentTrustDir({
10
+ agent: input.agentCommandName,
11
+ dirPath: input.launchDir,
12
+ trustMethod: GROUNDCREW_TRUST_METHOD,
13
+ });
14
+ if (!result.ok) {
15
+ writeError(`groundcrew: ${result.error}`);
16
+ }
17
+ }
@@ -58,6 +58,13 @@ export type WorktreeDirtiness = {
58
58
  } | {
59
59
  kind: "unknown";
60
60
  };
61
+ export declare function isRecoverableRemovalError(error: unknown): boolean;
62
+ export interface ForceRemoveDirectoryOptions {
63
+ attempts?: number;
64
+ delayMs?: number;
65
+ remove?: (target: string) => void;
66
+ }
67
+ export declare function forceRemoveDirectory(targetDir: string, options?: ForceRemoveDirectoryOptions): Promise<void>;
61
68
  declare function list(config: ResolvedConfig): WorktreeEntry[];
62
69
  declare function findByTask(config: ResolvedConfig, task: string): WorktreeEntry[];
63
70
  export interface PredictedWorktreeEntry {
@@ -1 +1 @@
1
- {"version":3,"file":"worktrees.d.ts","sourceRoot":"","sources":["../../src/lib/worktrees.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worktrees.d.ts","sourceRoot":"","sources":["../../src/lib/worktrees.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@
11
11
  import { existsSync, readdirSync, rmSync, statSync } from "node:fs";
12
12
  import { userInfo } from "node:os";
13
13
  import path from "node:path";
14
+ import { setTimeout as sleep } from "node:timers/promises";
14
15
  import { applySubstitutions } from "./adapters/shell/invoke.js";
15
16
  import { runCommandAsync } from "./commandRunner.js";
16
17
  import { repositoryBaseDir, worktreeBaseDir, } from "./config.js";
@@ -384,7 +385,7 @@ async function removeWorktree(config, entry, options) {
384
385
  if (registration !== "orphan") {
385
386
  throw error;
386
387
  }
387
- removeOrphanWorktreeDirectory(config, entry);
388
+ await removeOrphanWorktreeDirectory(config, entry);
388
389
  }
389
390
  else {
390
391
  const dirtiness = await throwIfWorktreeDirty(entry, options.signal, error);
@@ -533,7 +534,46 @@ function isInsideDirectory(parentDir, childDir) {
533
534
  !childRelativePath.startsWith("..") &&
534
535
  !path.isAbsolute(childRelativePath));
535
536
  }
536
- function removeOrphanWorktreeDirectory(config, entry) {
537
+ // APFS reports ENOTEMPTY (and occasionally EBUSY/EPERM) from a recursive rmdir
538
+ // when directory-entry caches lag behind the unlinks that just emptied it. This
539
+ // bites large trees like node_modules, where `rmSync` bails partway through even
540
+ // though a plain `rm -rf` succeeds. Retrying the removal lets the caches settle
541
+ // and drains the remaining entries.
542
+ const RECOVERABLE_REMOVAL_ERROR_CODES = new Set([
543
+ "ENOTEMPTY",
544
+ "EBUSY",
545
+ "EPERM",
546
+ "EMFILE",
547
+ "ENFILE",
548
+ ]);
549
+ export function isRecoverableRemovalError(error) {
550
+ return (error instanceof Error &&
551
+ "code" in error &&
552
+ typeof error.code === "string" &&
553
+ RECOVERABLE_REMOVAL_ERROR_CODES.has(error.code));
554
+ }
555
+ export async function forceRemoveDirectory(targetDir, options = {}) {
556
+ const attempts = options.attempts ?? 8;
557
+ const delayMs = options.delayMs ?? 100;
558
+ const removeDirectory = options.remove ??
559
+ ((target) => {
560
+ rmSync(target, { recursive: true, force: true });
561
+ });
562
+ for (let attempt = 1;; attempt += 1) {
563
+ try {
564
+ removeDirectory(targetDir);
565
+ return;
566
+ }
567
+ catch (error) {
568
+ if (attempt >= attempts || !isRecoverableRemovalError(error)) {
569
+ throw error;
570
+ }
571
+ // oxlint-disable-next-line no-await-in-loop -- retries are intentionally serial with a settle delay between attempts.
572
+ await sleep(delayMs);
573
+ }
574
+ }
575
+ }
576
+ async function removeOrphanWorktreeDirectory(config, entry) {
537
577
  const worktreeRoot = path.resolve(worktreeBaseDir(config));
538
578
  const expectedDir = expectedHostWorktreeDir(config, entry);
539
579
  const targetDir = path.resolve(entry.dir);
@@ -541,7 +581,7 @@ function removeOrphanWorktreeDirectory(config, entry) {
541
581
  throw new Error(`Refusing to force-delete ${entry.dir}: expected groundcrew worktree path ${expectedDir}.`);
542
582
  }
543
583
  debug(`Removing orphaned worktree directory ${entry.dir} (--force)...`);
544
- rmSync(targetDir, { recursive: true, force: true });
584
+ await forceRemoveDirectory(targetDir);
545
585
  }
546
586
  function list(config) {
547
587
  return listWorktrees(config);
@@ -52,6 +52,20 @@ If the task intentionally has no PR, mark it complete with `crew task done <task
52
52
 
53
53
  Groundcrew creates isolated per-task worktrees for unattended runs, so the shipped `claude` command is `claude --permission-mode auto` to let Claude proceed without stopping for clarifying questions while keeping its built-in safety prompts intact. Override `agents.definitions.claude.cmd` for `bypassPermissions` if you need to suppress tool-permission prompts entirely, or for a stricter mode.
54
54
 
55
+ ## Workspace Trust Is Seeded Automatically
56
+
57
+ Groundcrew provisions each worktree and records workspace trust for `claude`, `codex`, and `cursor-agent` before the agent starts (via [`agent-trust`](https://www.npmjs.com/package/agent-trust)), so unattended launches do not stall on first-run trust dialogs. There is no config toggle: if groundcrew created the worktree, trust is recorded in the agent's local store (`~/.claude.json` for Claude, `~/.codex/config.toml` for Codex, `~/.cursor/projects/<slug>/.workspace-trusted` for Cursor) for the worktree launch directory. Cursor markers use `trustMethod: "groundcrew-auto-trust"` for auditability. This applies only to groundcrew-provisioned worktrees at launch time; it does not trust arbitrary paths you open manually. Permission mode (`claude --permission-mode auto`) and Codex approval bypass (`--dangerously-bypass-approvals-and-sandbox`) are separate from workspace trust.
58
+
59
+ Inspect or clean trust entries with the published CLI:
60
+
61
+ ```bash
62
+ npm i -g agent-trust
63
+ agent-trust list
64
+ agent-trust list --missing
65
+ agent-trust remove --trust-method groundcrew-auto-trust --all --agent cursor
66
+ agent-trust prune
67
+ ```
68
+
55
69
  ## Doctor's Command Introspection Is Shallow
56
70
 
57
71
  Doctor reports the resolved local runner and whether its prerequisites are met, then tokenizes agent `cmd` and checks the first two non-flag tokens against PATH. Boolean flags without values, env-var assignments (`FOO=1`), shell pipelines, and subshells are not parsed. When `local.runner` is `"none"`, doctor surfaces a single WARNING line.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clipboard-health/groundcrew",
3
- "version": "4.46.6",
3
+ "version": "4.47.1",
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",
@@ -73,6 +73,7 @@
73
73
  "@anthropic-ai/sandbox-runtime": "0.0.63",
74
74
  "@clipboard-health/clearance": "1.4.4",
75
75
  "@linear/sdk": "88.0.0",
76
+ "agent-trust": "1.0.0",
76
77
  "cosmiconfig": "9.0.2",
77
78
  "tslib": "2.8.1",
78
79
  "zod": "4.4.3"
@@ -83,8 +84,8 @@
83
84
  "@nx/js": "22.7.6",
84
85
  "@tsconfig/node24": "24.0.4",
85
86
  "@tsconfig/strictest": "2.0.8",
86
- "@types/node": "25.9.4",
87
- "@typescript/native-preview": "7.0.0-dev.20260705.1",
87
+ "@types/node": "25.9.5",
88
+ "@typescript/native-preview": "7.0.0-dev.20260707.2",
88
89
  "@vitest/coverage-v8": "4.1.9",
89
90
  "cspell": "10.0.1",
90
91
  "dependency-cruiser": "18.0.0",