@clipboard-health/groundcrew 1.12.1 → 1.12.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.
package/README.md CHANGED
@@ -102,7 +102,7 @@ This installs the `crew` binary. `@clipboard-health/clearance` is pulled in tran
102
102
 
103
103
  Known MCP aliases are `linear`, `slack`, and `notion`. For another HTTP MCP server, pass `--mcp name=https://example.com/mcp`. The command creates the remote runner if needed, prepares `~/dev`, configures Git, runs selected auth flows, adds selected MCP servers to Claude Code, and then opens Claude so you can run `/mcp` and authenticate only those selected servers. With the Sprite provider, `--copy-local-codex-auth` copies `${CODEX_HOME:-$HOME/.codex}/auth.json` into `/home/sprite/.codex/auth.json` and then verifies `codex login status`; it never prints the file contents. `--datadog` installs a pinned `pup` release in the remote runner, verifies its checksum, installs the `dd-pup` guidance for Claude and Codex, verifies `pup auth status`, and when auth is missing temporarily runs `sprite proxy` for the OAuth callback while `pup auth login --read-only` runs in the remote runner. Open the Datadog URL printed by `pup` if your terminal does not open it automatically. Use `--skip-mcp-auth` when you only want to add MCP definitions, and run the `/mcp` step later.
104
104
 
105
- Repo setup is separate from runner setup and should run after the ticket branch exists, immediately before launching an agent. It clones/fetches the repo in the remote runner, checks out the requested branch (creating it from the base branch when it does not exist on origin), forwards only build-time secrets for the dependency install, removes the temporary secret file, clears those env vars, and then exits. It uses groundcrew's remote setup command.
105
+ Repo setup is separate from runner setup and should run after the ticket branch exists, immediately before launching an agent. It clones/fetches the repo in the remote runner using `git.remote`, checks out the requested branch (creating it from the base branch when it does not exist on that remote), forwards only build-time secrets for the dependency install, removes the temporary secret file, clears those env vars, and then exits. It uses groundcrew's remote setup command.
106
106
 
107
107
  ```bash
108
108
  op run --env-file "${XDG_CONFIG_HOME:-$HOME/.config}/groundcrew/op.env" -- \
@@ -22,6 +22,7 @@ export interface RemoteBootstrapOptions {
22
22
  repository: string;
23
23
  owner: string;
24
24
  baseBranch: string;
25
+ gitRemote?: string;
25
26
  secretNames: string[];
26
27
  shouldRequireSelectedSecrets: boolean;
27
28
  shouldUseSecrets: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"remoteSetup.d.ts","sourceRoot":"","sources":["../../src/commands/remoteSetup.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,wBAAwB,EAAE,OAAO,CAAC;IAClC,uBAAuB,EAAE,OAAO,CAAC;IACjC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,wBAAwB,EAAE,OAAO,CAAC;IAClC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,4BAA4B,EAAE,OAAO,CAAC;IACtC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAy0BD,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B9F;AAUD,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAItF;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrF;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAItF;AAED,wBAAsB,2BAA2B,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG;AAYD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgClF;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2B7D"}
1
+ {"version":3,"file":"remoteSetup.d.ts","sourceRoot":"","sources":["../../src/commands/remoteSetup.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,wBAAwB,EAAE,OAAO,CAAC;IAClC,uBAAuB,EAAE,OAAO,CAAC;IACjC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,wBAAwB,EAAE,OAAO,CAAC;IAClC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,4BAA4B,EAAE,OAAO,CAAC;IACtC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAaD,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAw1BD,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC9F;AAUD,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAItF;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrF;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAItF;AAED,wBAAsB,2BAA2B,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG;AAYD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgClF;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2B7D"}
@@ -14,7 +14,7 @@ const KNOWN_MCP_SERVER_URLS = {
14
14
  const DEFAULT_CHECKPOINT_COMMENT = "groundcrew remote runner baseline: selected agent auth, git identity, and MCP config";
15
15
  const CLAUDE_SUBSCRIPTION_LOGIN_FLAG = ["--claude", "ai"].join("");
16
16
  const DEFAULT_REPOSITORY_OWNER = "ClipboardHealth";
17
- const DEFAULT_BASE_BRANCH = "main";
17
+ const DEFAULT_GIT_REMOTE = "origin";
18
18
  const DATADOG_PUP_VERSION = "0.63.0";
19
19
  const DATADOG_OAUTH_CALLBACK_PORT = 8000;
20
20
  const DATADOG_AUTH_STATUS_RETRY_ATTEMPTS = 5;
@@ -52,7 +52,7 @@ function usage() {
52
52
  "",
53
53
  "Bootstrap options:",
54
54
  " --branch <branch> Checkout/create a ticket branch before installing deps",
55
- " --base <branch> Base branch used when creating a missing branch (default: main)",
55
+ " --base <branch> Base branch used when creating a missing branch (default: git.defaultBranch)",
56
56
  " --owner <owner> GitHub owner for bare repo names (default: ClipboardHealth)",
57
57
  " --secret <env-name> Forward one required build secret; repeat for multiple",
58
58
  " --no-secrets Do not forward NPM_TOKEN/BUF_TOKEN even if present",
@@ -233,7 +233,7 @@ function parseBootstrapArguments(argv) {
233
233
  }
234
234
  validateRepository(repository);
235
235
  let owner = DEFAULT_REPOSITORY_OWNER;
236
- let baseBranch = DEFAULT_BASE_BRANCH;
236
+ let baseBranch;
237
237
  let branchName;
238
238
  let shouldUseSecrets = true;
239
239
  let shouldRequireSelectedSecrets = false;
@@ -276,10 +276,10 @@ function parseBootstrapArguments(argv) {
276
276
  runnerName,
277
277
  repository,
278
278
  owner,
279
- baseBranch,
280
279
  secretNames: selectedSecretNames.length > 0 ? selectedSecretNames : [...BUILD_SECRET_NAMES],
281
280
  shouldRequireSelectedSecrets,
282
281
  shouldUseSecrets,
282
+ ...(baseBranch === undefined ? {} : { baseBranch }),
283
283
  ...(branchName === undefined ? {} : { branchName }),
284
284
  };
285
285
  }
@@ -634,34 +634,46 @@ function repositoryDirectoryName(repository) {
634
634
  function remoteBootstrapCommand(options) {
635
635
  const slug = repositorySlug(options);
636
636
  const directoryName = repositoryDirectoryName(options.repository);
637
+ const baseRef = `${options.gitRemote}/${options.baseBranch}`;
637
638
  const unsetSecretsLine = options.secretNames.length === 0 ? ":" : `unset ${options.secretNames.join(" ")}`;
638
639
  const checkoutLines = options.branchName === undefined
639
- ? [
640
- `git checkout -B ${shellSingleQuote(options.baseBranch)} ${shellSingleQuote(`origin/${options.baseBranch}`)}`,
641
- ]
640
+ ? [`git checkout -B ${shellSingleQuote(options.baseBranch)} ${shellSingleQuote(baseRef)}`]
642
641
  : [
643
- `if git show-ref --verify --quiet ${shellSingleQuote(`refs/remotes/origin/${options.branchName}`)}; then`,
644
- ` git checkout -B ${shellSingleQuote(options.branchName)} ${shellSingleQuote(`origin/${options.branchName}`)}`,
642
+ `if git show-ref --verify --quiet ${shellSingleQuote(`refs/remotes/${options.gitRemote}/${options.branchName}`)}; then`,
643
+ ` git checkout -B ${shellSingleQuote(options.branchName)} ${shellSingleQuote(`${options.gitRemote}/${options.branchName}`)}`,
645
644
  "else",
646
- ` git checkout -B ${shellSingleQuote(options.branchName)} ${shellSingleQuote(`origin/${options.baseBranch}`)}`,
645
+ ` git checkout -B ${shellSingleQuote(options.branchName)} ${shellSingleQuote(baseRef)}`,
647
646
  "fi",
648
647
  ];
649
648
  return [
650
649
  "set -euo pipefail",
651
650
  `cleanup() { rm -f ${shellSingleQuote(REMOTE_SECRETS_FILE)}; ${unsetSecretsLine}; }`,
652
651
  "trap cleanup EXIT",
652
+ `git_remote=${shellSingleQuote(options.gitRemote)}`,
653
653
  'mkdir -p "$HOME/dev"',
654
654
  `repo_dir="$HOME/dev/${directoryName}"`,
655
655
  'if [ ! -d "$repo_dir/.git" ]; then',
656
656
  ` gh repo clone ${shellSingleQuote(slug)} "$repo_dir"`,
657
657
  "fi",
658
658
  'cd "$repo_dir"',
659
- "git fetch origin --prune",
659
+ 'if ! git remote get-url "$git_remote" >/dev/null 2>&1; then',
660
+ ' origin_url="$(git remote get-url origin)"',
661
+ ' git remote add "$git_remote" "$origin_url"',
662
+ "fi",
663
+ 'git fetch "$git_remote" --prune',
660
664
  ...checkoutLines,
661
665
  `if [ -f ${shellSingleQuote(REMOTE_SECRETS_FILE)} ]; then set -a && . ${shellSingleQuote(REMOTE_SECRETS_FILE)} && set +a; fi`,
662
666
  DEFAULT_REMOTE_SETUP_COMMAND,
663
667
  ].join("\n");
664
668
  }
669
+ async function resolveBootstrapOptions(options) {
670
+ const config = await loadConfig();
671
+ return {
672
+ ...options,
673
+ baseBranch: options.baseBranch ?? config.git.defaultBranch,
674
+ gitRemote: config.git.remote,
675
+ };
676
+ }
665
677
  function noSecretCleanup() {
666
678
  // No staged secrets file was created.
667
679
  }
@@ -697,12 +709,16 @@ function stageBuildSecrets(options) {
697
709
  };
698
710
  }
699
711
  export async function bootstrapRemoteRepository(options) {
712
+ const bootstrapOptions = {
713
+ ...options,
714
+ gitRemote: options.gitRemote ?? DEFAULT_GIT_REMOTE,
715
+ };
700
716
  const config = remoteConfigWithRunnerName(options.runnerName);
701
717
  const provider = providerFor(config);
702
718
  if (!(await provider.runnerExists(config))) {
703
719
  throw new Error(`Remote runner ${options.runnerName} does not exist. Run crew remote setup first.`);
704
720
  }
705
- const stagedSecrets = stageBuildSecrets(options);
721
+ const stagedSecrets = stageBuildSecrets(bootstrapOptions);
706
722
  try {
707
723
  if (stagedSecrets.names.length > 0) {
708
724
  log(`Forwarding build secret names for setup only: ${stagedSecrets.names.join(", ")}`);
@@ -710,11 +726,11 @@ export async function bootstrapRemoteRepository(options) {
710
726
  const files = stagedSecrets.filePath === undefined
711
727
  ? []
712
728
  : [{ localPath: stagedSecrets.filePath, remotePath: REMOTE_SECRETS_FILE }];
713
- log(`Bootstrapping ${repositorySlug(options)} in ${options.runnerName}`);
729
+ log(`Bootstrapping ${repositorySlug(bootstrapOptions)} in ${options.runnerName}`);
714
730
  await provider.runCommand({
715
731
  config,
716
732
  files,
717
- remoteArguments: ["bash", "-lc", remoteBootstrapCommand(options)],
733
+ remoteArguments: ["bash", "-lc", remoteBootstrapCommand(bootstrapOptions)],
718
734
  options: { stdio: "inherit", timeoutMs: 0 },
719
735
  });
720
736
  }
@@ -790,7 +806,7 @@ export async function remoteCli(argv) {
790
806
  return;
791
807
  }
792
808
  if (action === "bootstrap") {
793
- await bootstrapRemoteRepository(parseBootstrapArguments(rest));
809
+ await bootstrapRemoteRepository(await resolveBootstrapOptions(parseBootstrapArguments(rest)));
794
810
  return;
795
811
  }
796
812
  if (action === "sessions") {
@@ -30,6 +30,7 @@ interface RemoteWorktreeCreateArguments {
30
30
  ticket: string;
31
31
  branchName: string;
32
32
  baseBranch: string;
33
+ gitRemote: string;
33
34
  signal?: AbortSignal;
34
35
  }
35
36
  interface RemoteWorktreeLocation {
@@ -1 +1 @@
1
- {"version":3,"file":"spriteRemoteRunnerProvider.d.ts","sourceRoot":"","sources":["../../src/lib/spriteRemoteRunnerProvider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"spriteRemoteRunnerProvider.d.ts","sourceRoot":"","sources":["../../src/lib/spriteRemoteRunnerProvider.ts"],"names":[],"mappings":"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"}
@@ -105,6 +105,9 @@ function worktreeTicketComponent(ticket) {
105
105
  }
106
106
  function spriteCreateWorktreeCommand(arguments_) {
107
107
  const slug = repositorySlug(arguments_.owner, arguments_.repository);
108
+ const branchRemoteRef = `refs/remotes/${arguments_.gitRemote}/${arguments_.branchName}`;
109
+ const branchRef = `${arguments_.gitRemote}/${arguments_.branchName}`;
110
+ const baseRef = `${arguments_.gitRemote}/${arguments_.baseBranch}`;
108
111
  return [
109
112
  "set -euo pipefail",
110
113
  `repo_root=${shellSingleQuote(arguments_.repoRoot)}`,
@@ -112,20 +115,27 @@ function spriteCreateWorktreeCommand(arguments_) {
112
115
  `repo_dir=${shellSingleQuote(arguments_.repoDir)}`,
113
116
  `worktree_dir=${shellSingleQuote(arguments_.worktreeDir)}`,
114
117
  `branch=${shellSingleQuote(arguments_.branchName)}`,
115
- `base_branch=${shellSingleQuote(arguments_.baseBranch)}`,
118
+ `git_remote=${shellSingleQuote(arguments_.gitRemote)}`,
119
+ `branch_remote_ref=${shellSingleQuote(branchRemoteRef)}`,
120
+ `branch_ref=${shellSingleQuote(branchRef)}`,
121
+ `base_ref=${shellSingleQuote(baseRef)}`,
116
122
  'mkdir -p "$repo_root" "$worktree_root"',
117
123
  'if [ ! -d "$repo_dir/.git" ]; then',
118
124
  ` gh repo clone ${shellSingleQuote(slug)} "$repo_dir"`,
119
125
  "fi",
120
- 'git -C "$repo_dir" fetch origin --prune',
126
+ 'if ! git -C "$repo_dir" remote get-url "$git_remote" >/dev/null 2>&1; then',
127
+ ' origin_url="$(git -C "$repo_dir" remote get-url origin)"',
128
+ ' git -C "$repo_dir" remote add "$git_remote" "$origin_url"',
129
+ "fi",
130
+ 'git -C "$repo_dir" fetch "$git_remote" --prune',
121
131
  'if [ -e "$worktree_dir" ]; then',
122
132
  ' echo "Remote worktree already exists: $worktree_dir" >&2',
123
133
  " exit 1",
124
134
  "fi",
125
- 'if git -C "$repo_dir" show-ref --verify --quiet "refs/remotes/origin/$branch"; then',
126
- ' git -C "$repo_dir" worktree add -B "$branch" "$worktree_dir" "origin/$branch"',
135
+ 'if git -C "$repo_dir" show-ref --verify --quiet "$branch_remote_ref"; then',
136
+ ' git -C "$repo_dir" worktree add -B "$branch" "$worktree_dir" "$branch_ref"',
127
137
  "else",
128
- ' git -C "$repo_dir" worktree add -b "$branch" "$worktree_dir" "origin/$base_branch"',
138
+ ' git -C "$repo_dir" worktree add -b "$branch" "$worktree_dir" "$base_ref"',
129
139
  "fi",
130
140
  ].join("\n");
131
141
  }
@@ -306,7 +316,7 @@ export const spriteRemoteRunnerProvider = {
306
316
  });
307
317
  },
308
318
  async createWorktree(arguments_) {
309
- const { config, repository, ticket, branchName, baseBranch, signal } = arguments_;
319
+ const { config, repository, ticket, branchName, baseBranch, gitRemote, signal } = arguments_;
310
320
  const remoteRepositoryName = repositoryDirectoryName(config.owner, repository);
311
321
  const remoteRepoDir = remotePathJoin(config.repoRoot, remoteRepositoryName);
312
322
  const remoteWorktreeDir = remotePathJoin(config.worktreeRoot, `${remoteRepositoryName}-${worktreeTicketComponent(ticket)}`);
@@ -324,6 +334,7 @@ export const spriteRemoteRunnerProvider = {
324
334
  worktreeDir: remoteWorktreeDir,
325
335
  branchName,
326
336
  baseBranch,
337
+ gitRemote,
327
338
  repoRoot: config.repoRoot,
328
339
  worktreeRoot: config.worktreeRoot,
329
340
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"worktrees.d.ts","sourceRoot":"","sources":["../../src/lib/worktrees.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAiBH,OAAO,EAA8B,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAMpG,OAAO,EAAE,KAAK,cAAc,EAAc,MAAM,iBAAiB,CAAC;AAIlE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7C,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;IACnB,mCAAmC;IACnC,cAAc,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC;IACtD,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mCAAmC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAaD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAW7E;AAyYD,4FAA4F;AAC5F,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,iBAAS,YAAY,CACnB,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,aAAa,GAAG,SAAS,CAI3B;AAED,iBAAe,MAAM,CACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,YAAY,EAClB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,aAAa,CAAC,CAUxB;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;AAKD,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,CAkDzB;AAED,eAAO,MAAM,SAAS;;;;;;;CAOrB,CAAC"}
1
+ {"version":3,"file":"worktrees.d.ts","sourceRoot":"","sources":["../../src/lib/worktrees.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAiBH,OAAO,EAA8B,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAMpG,OAAO,EAAE,KAAK,cAAc,EAAc,MAAM,iBAAiB,CAAC;AAIlE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7C,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;IACnB,mCAAmC;IACnC,cAAc,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC;IACtD,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mCAAmC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAaD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAW7E;AAgdD,4FAA4F;AAC5F,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,iBAAS,YAAY,CACnB,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,aAAa,GAAG,SAAS,CAI3B;AAED,iBAAe,MAAM,CACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,YAAY,EAClB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,aAAa,CAAC,CAUxB;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;AAKD,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,CAkDzB;AAED,eAAO,MAAM,SAAS;;;;;;;CAOrB,CAAC"}
@@ -198,6 +198,23 @@ function stateBaseDir() {
198
198
  function remoteStateFilePath() {
199
199
  return resolve(stateBaseDir(), "groundcrew", "remote-worktrees.json");
200
200
  }
201
+ function normalizeRemoteStateNamespacePath(path) {
202
+ const normalized = path.replace(/\/+$/u, "");
203
+ return normalized.length === 0 ? "/" : normalized;
204
+ }
205
+ function remoteStateNamespaceFor(config) {
206
+ return JSON.stringify({
207
+ version: 1,
208
+ projectDir: resolve(config.workspace.projectDir),
209
+ remote: {
210
+ provider: config.remote.provider,
211
+ runnerName: config.remote.runnerName,
212
+ owner: config.remote.owner,
213
+ repoRoot: normalizeRemoteStateNamespacePath(config.remote.repoRoot),
214
+ worktreeRoot: normalizeRemoteStateNamespacePath(config.remote.worktreeRoot),
215
+ },
216
+ });
217
+ }
201
218
  function isRemoteEntry(value) {
202
219
  if (typeof value !== "object" || value === null) {
203
220
  return false;
@@ -210,7 +227,8 @@ function isRemoteEntry(value) {
210
227
  entry.kind === "remote" &&
211
228
  isRemoteRunnerProviderName(entry.remoteProvider) &&
212
229
  typeof entry.remoteRunnerName === "string" &&
213
- typeof entry.remoteRepoDir === "string");
230
+ typeof entry.remoteRepoDir === "string" &&
231
+ (entry.remoteStateNamespace === undefined || typeof entry.remoteStateNamespace === "string"));
214
232
  }
215
233
  function readRemoteEntries() {
216
234
  try {
@@ -238,8 +256,41 @@ function writeRemoteEntries(entries) {
238
256
  }
239
257
  }
240
258
  }
241
- function upsertRemoteEntry(entry) {
242
- writeRemoteEntries([...readRemoteEntries(), entry]);
259
+ function remoteStateEntryFor(namespace, entry) {
260
+ return { ...entry, remoteStateNamespace: namespace };
261
+ }
262
+ function remoteStateEntryMatchesNamespace(namespace, entry) {
263
+ // Legacy records have no project/config identity. Keep them on disk, but do
264
+ // not expose them to cleanup paths that could remove another config's remote
265
+ // worktree.
266
+ return entry.remoteStateNamespace === namespace;
267
+ }
268
+ function remoteStateEntryMatchesWorktree(namespace, candidate, entry) {
269
+ return (candidate.remoteStateNamespace === namespace &&
270
+ candidate.repository === entry.repository &&
271
+ candidate.ticket === entry.ticket &&
272
+ candidate.dir === entry.dir &&
273
+ candidate.kind === "remote");
274
+ }
275
+ function worktreeEntryFromRemoteState(entry) {
276
+ return {
277
+ repository: entry.repository,
278
+ ticket: entry.ticket,
279
+ branchName: entry.branchName,
280
+ dir: entry.dir,
281
+ kind: entry.kind,
282
+ remoteProvider: entry.remoteProvider,
283
+ remoteRunnerName: entry.remoteRunnerName,
284
+ remoteRepoDir: entry.remoteRepoDir,
285
+ };
286
+ }
287
+ function upsertRemoteEntry(config, entry) {
288
+ const namespace = remoteStateNamespaceFor(config);
289
+ const stateEntry = remoteStateEntryFor(namespace, entry);
290
+ writeRemoteEntries([
291
+ ...readRemoteEntries().filter((candidate) => !remoteStateEntryMatchesWorktree(namespace, candidate, entry)),
292
+ stateEntry,
293
+ ]);
243
294
  }
244
295
  function removeTemporaryRemoteStateFileBestEffort(path) {
245
296
  try {
@@ -250,11 +301,9 @@ function removeTemporaryRemoteStateFileBestEffort(path) {
250
301
  log(`Temporary remote state file cleanup skipped: ${errorMessage(error)}`);
251
302
  }
252
303
  }
253
- function deleteRemoteEntry(entry) {
254
- writeRemoteEntries(readRemoteEntries().filter((candidate) => !(candidate.repository === entry.repository &&
255
- candidate.ticket === entry.ticket &&
256
- candidate.dir === entry.dir &&
257
- candidate.kind === "remote")));
304
+ function deleteRemoteEntry(config, entry) {
305
+ const namespace = remoteStateNamespaceFor(config);
306
+ writeRemoteEntries(readRemoteEntries().filter((candidate) => !remoteStateEntryMatchesWorktree(namespace, candidate, entry)));
258
307
  }
259
308
  function remoteProviderFor(config, entry) {
260
309
  return getRemoteRunnerProvider(entry?.remoteProvider ?? config.remote.provider);
@@ -284,6 +333,7 @@ const remoteWorktreeAdapter = {
284
333
  ticket: spec.ticket,
285
334
  branchName: base.branchName,
286
335
  baseBranch: config.git.defaultBranch,
336
+ gitRemote: config.git.remote,
287
337
  ...signalProperty(signal),
288
338
  });
289
339
  const entry = {
@@ -297,7 +347,7 @@ const remoteWorktreeAdapter = {
297
347
  remoteRepoDir,
298
348
  };
299
349
  try {
300
- upsertRemoteEntry(entry);
350
+ upsertRemoteEntry(config, entry);
301
351
  }
302
352
  catch (error) {
303
353
  await removeCreatedRemoteWorktreeBestEffort({
@@ -311,7 +361,11 @@ const remoteWorktreeAdapter = {
311
361
  return entry;
312
362
  },
313
363
  list(config) {
314
- return readRemoteEntries().filter((entry) => config.workspace.knownRepositories.includes(entry.repository));
364
+ const namespace = remoteStateNamespaceFor(config);
365
+ return readRemoteEntries()
366
+ .filter((entry) => remoteStateEntryMatchesNamespace(namespace, entry))
367
+ .filter((entry) => config.workspace.knownRepositories.includes(entry.repository))
368
+ .map(worktreeEntryFromRemoteState);
315
369
  },
316
370
  async remove(config, entry, options) {
317
371
  log(`Removing remote worktree ${entry.dir}${options.force ? " (--force)" : ""}...`);
@@ -326,7 +380,7 @@ const remoteWorktreeAdapter = {
326
380
  force: options.force,
327
381
  ...signalProperty(options.signal),
328
382
  });
329
- deleteRemoteEntry(entry);
383
+ deleteRemoteEntry(config, entry);
330
384
  },
331
385
  };
332
386
  function adapterForEntry(entry) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clipboard-health/groundcrew",
3
- "version": "1.12.1",
3
+ "version": "1.12.2",
4
4
  "description": "Linear-driven orchestrator that launches AI coding agents in git worktrees, with workspace lifecycle, remote runners, and usage tracking.",
5
5
  "keywords": [
6
6
  "agent",