@ricsam/r5d-worker 0.0.46 → 0.0.47

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/dist/cjs/main.cjs CHANGED
@@ -43,6 +43,9 @@ __export(main_exports, {
43
43
  resolveHostShell: () => resolveHostShell,
44
44
  resolveWorkerFilePath: () => resolveWorkerFilePath,
45
45
  syncSessionArtifacts: () => syncSessionArtifacts,
46
+ visibleCheckoutGitTestHarness: () => visibleCheckoutGitTestHarness,
47
+ visibleCheckoutRemoteFor: () => visibleCheckoutRemoteFor,
48
+ workspaceSyncCheckoutTargets: () => workspaceSyncCheckoutTargets,
46
49
  writeWorkerTextFile: () => writeWorkerTextFile
47
50
  });
48
51
  module.exports = __toCommonJS(main_exports);
@@ -614,6 +617,14 @@ function validatePlanId(planId) {
614
617
  throw new Error(`Invalid plan id from server: ${planId}`);
615
618
  }
616
619
  }
620
+ const NON_RECURSIVE_GIT_CONFIG_ARGS = [
621
+ "-c",
622
+ "submodule.recurse=false",
623
+ "-c",
624
+ "fetch.recurseSubmodules=false",
625
+ "-c",
626
+ "push.recurseSubmodules=false"
627
+ ];
617
628
  function gitExtraHeaderConfigKey(extraHeaderUrl) {
618
629
  return `http.${normalizeBaseUrl(extraHeaderUrl)}/.extraHeader`;
619
630
  }
@@ -621,10 +632,23 @@ function gitAuthArgs(auth) {
621
632
  if (!auth) {
622
633
  return [];
623
634
  }
624
- return ["-c", `${gitExtraHeaderConfigKey(auth.extraHeaderUrl)}=${auth.header}`];
635
+ const scopedKey = gitExtraHeaderConfigKey(auth.extraHeaderUrl);
636
+ return ["-c", "http.extraHeader=", "-c", `${scopedKey}=`, "-c", `${scopedKey}=${auth.header}`];
637
+ }
638
+ const visibleCheckoutGitTestHarness = {
639
+ gitAuthArgs,
640
+ commandArgs: (args, auth) => ["git", ...NON_RECURSIVE_GIT_CONFIG_ARGS, ...gitAuthArgs(auth), ...args],
641
+ cloneArgs: (remoteUrl, branchPath) => ["clone", "--no-recurse-submodules", "--origin", "origin", remoteUrl, branchPath],
642
+ fetchArgs: (...args) => ["fetch", "--no-recurse-submodules", ...args]
643
+ };
644
+ function visibleCheckoutCloneArgs(remoteUrl, branchPath) {
645
+ return visibleCheckoutGitTestHarness.cloneArgs(remoteUrl, branchPath);
646
+ }
647
+ function visibleCheckoutFetchArgs(...args) {
648
+ return visibleCheckoutGitTestHarness.fetchArgs(...args);
625
649
  }
626
650
  function runGit(args, options = {}) {
627
- const command = ["git", ...gitAuthArgs(options.auth), ...args];
651
+ const command = visibleCheckoutGitTestHarness.commandArgs(args, options.auth);
628
652
  const result = Bun.spawnSync(command, {
629
653
  cwd: options.cwd,
630
654
  stdout: "pipe",
@@ -768,8 +792,28 @@ function resolveWorkerFilePath(branchPath, inputPath, builtInPaths) {
768
792
  function fallbackInternalRemoteUrl(baseUrl, projectId) {
769
793
  return new URL(`/git/${projectId}.git`, baseUrl).toString();
770
794
  }
771
- function githubRemoteUrlFor(baseUrl, projectId, manifest) {
772
- return manifest?.repoHttpUrl ?? fallbackInternalRemoteUrl(baseUrl, projectId);
795
+ function visibleCheckoutRemoteFor(input) {
796
+ const canonicalCheckout = input.manifest?.canonicalCheckouts?.find((checkout) => checkout.branchName === input.branchName);
797
+ const isCanonicalManifestBranch = Boolean(canonicalCheckout);
798
+ const usesCanonicalRemote = isCanonicalManifestBranch || !input.manifest?.repoHttpUrl;
799
+ if (usesCanonicalRemote) {
800
+ return {
801
+ remoteUrl: fallbackInternalRemoteUrl(input.baseUrl, input.projectId),
802
+ authHeader: `Authorization: Bearer ${input.token}`,
803
+ persistAuth: false,
804
+ reconcileExistingOrigin: isCanonicalManifestBranch,
805
+ requireRemoteBranch: isCanonicalManifestBranch,
806
+ requiredBaseCommit: canonicalCheckout?.scaffoldCommitHash ?? null
807
+ };
808
+ }
809
+ return {
810
+ remoteUrl: input.manifest?.repoHttpUrl ?? fallbackInternalRemoteUrl(input.baseUrl, input.projectId),
811
+ authHeader: input.manifest?.repoAuthHeader ?? null,
812
+ persistAuth: true,
813
+ reconcileExistingOrigin: Boolean(input.manifest?.repoHttpUrl),
814
+ requireRemoteBranch: false,
815
+ requiredBaseCommit: null
816
+ };
773
817
  }
774
818
  function gitExtraHeaderUrlForRemote(remoteUrl) {
775
819
  try {
@@ -798,6 +842,10 @@ function ensureOriginRemote(branchPath, remoteUrl) {
798
842
  runGit(["remote", "add", "origin", remoteUrl], { cwd: branchPath });
799
843
  }
800
844
  }
845
+ function originRemoteUrl(branchPath) {
846
+ if (!tryGit(["remote", "get-url", "origin"], { cwd: branchPath })) return null;
847
+ return runGit(["remote", "get-url", "origin"], { cwd: branchPath });
848
+ }
801
849
  function shellQuote(value) {
802
850
  return `'${value.replace(/'/g, "'\\''")}'`;
803
851
  }
@@ -866,6 +914,18 @@ function configureVisibleGitHubAuth(branchPath, remoteUrl, authHeader) {
866
914
  }
867
915
  runGit(["config", `${gitExtraHeaderConfigKey(gitExtraHeaderUrlForRemote(remoteUrl))}`, authHeader], { cwd: branchPath });
868
916
  }
917
+ function clearVisibleGitAuthentication(branchPath) {
918
+ let extraHeaderKeys = [];
919
+ try {
920
+ extraHeaderKeys = runGit(["config", "--local", "--name-only", "--get-regexp", "^http\\..*extraheader$"], { cwd: branchPath }).split(/\r?\n/).filter(Boolean);
921
+ } catch {
922
+ }
923
+ for (const key of extraHeaderKeys) {
924
+ tryGit(["config", "--local", "--unset-all", key], { cwd: branchPath });
925
+ }
926
+ runGit(["config", "--local", "--replace-all", "credential.helper", ""], { cwd: branchPath });
927
+ tryGit(["config", "--local", "--unset-all", "credential.useHttpPath"], { cwd: branchPath });
928
+ }
869
929
  function dockerConfigPath() {
870
930
  return import_node_path.default.join(import_node_os.default.homedir(), ".docker", "config.json");
871
931
  }
@@ -954,18 +1014,58 @@ function checkoutVisibleBranch(input) {
954
1014
  });
955
1015
  const clean = !hasWorktreeChanges(input.branchPath);
956
1016
  if (remoteBranchExists && clean) {
957
- runGit(["checkout", "-B", input.branchName, `origin/${input.branchName}`], { cwd: input.branchPath });
1017
+ runGit(["checkout", "--no-recurse-submodules", "-B", input.branchName, `origin/${input.branchName}`], {
1018
+ cwd: input.branchPath
1019
+ });
958
1020
  return;
959
1021
  }
960
1022
  if (branchExists) {
961
- runGit(["checkout", input.branchName], { cwd: input.branchPath });
1023
+ runGit(["checkout", "--no-recurse-submodules", input.branchName], { cwd: input.branchPath });
962
1024
  return;
963
1025
  }
964
1026
  if (defaultRemoteExists) {
965
- runGit(["checkout", "-B", input.branchName, `origin/${input.defaultBranch}`], { cwd: input.branchPath });
1027
+ runGit(["checkout", "--no-recurse-submodules", "-B", input.branchName, `origin/${input.defaultBranch}`], {
1028
+ cwd: input.branchPath
1029
+ });
966
1030
  return;
967
1031
  }
968
- runGit(["checkout", "-B", input.branchName], { cwd: input.branchPath });
1032
+ runGit(["checkout", "--no-recurse-submodules", "-B", input.branchName], { cwd: input.branchPath });
1033
+ }
1034
+ function migrateExistingCheckoutToRequiredRemote(input) {
1035
+ if (originRemoteUrl(input.branchPath) === input.remoteUrl) return;
1036
+ if (hasWorktreeChanges(input.branchPath)) {
1037
+ throw new Error(`Cannot migrate dirty checkout for ${input.branchName} to its canonical remote`);
1038
+ }
1039
+ runGit(
1040
+ visibleCheckoutFetchArgs("--no-tags", input.remoteUrl, `+refs/heads/${input.branchName}:refs/remotes/origin/${input.branchName}`),
1041
+ {
1042
+ cwd: input.branchPath,
1043
+ auth: input.remoteAuth
1044
+ }
1045
+ );
1046
+ const canonicalRemoteRef = `refs/remotes/origin/${input.branchName}`;
1047
+ if (!tryGit(["show-ref", "--verify", "--quiet", canonicalRemoteRef], { cwd: input.branchPath })) {
1048
+ throw new Error(`Canonical branch ${input.branchName} is unavailable during checkout migration`);
1049
+ }
1050
+ if (input.requiredBaseCommit && (!tryGit(["cat-file", "-e", `${input.requiredBaseCommit}^{commit}`], { cwd: input.branchPath }) || !tryGit(["merge-base", "--is-ancestor", input.requiredBaseCommit, canonicalRemoteRef], { cwd: input.branchPath }))) {
1051
+ throw new Error(`Canonical branch ${input.branchName} is not derived from required scaffold ${input.requiredBaseCommit}`);
1052
+ }
1053
+ if (tryGit(["rev-parse", "--verify", "HEAD"], { cwd: input.branchPath })) {
1054
+ const previousHead = runGit(["rev-parse", "HEAD"], { cwd: input.branchPath });
1055
+ runGit(["update-ref", `refs/r5d/pre-canonical-checkout/${previousHead}`, previousHead], { cwd: input.branchPath });
1056
+ }
1057
+ ensureOriginRemote(input.branchPath, input.remoteUrl);
1058
+ runGit(["checkout", "--no-recurse-submodules", "-B", input.branchName, `origin/${input.branchName}`], {
1059
+ cwd: input.branchPath
1060
+ });
1061
+ }
1062
+ function assertCheckoutDerivedFromRequiredBase(input) {
1063
+ const remoteRevision = `refs/remotes/origin/${input.branchName}`;
1064
+ for (const revision of [remoteRevision, "HEAD"]) {
1065
+ if (!tryGit(["cat-file", "-e", `${input.requiredBaseCommit}^{commit}`], { cwd: input.branchPath }) || !tryGit(["merge-base", "--is-ancestor", input.requiredBaseCommit, revision], { cwd: input.branchPath })) {
1066
+ throw new Error(`Canonical checkout ${input.branchName} is not derived from required scaffold ${input.requiredBaseCommit}`);
1067
+ }
1068
+ }
969
1069
  }
970
1070
  function ensureVisibleGitCheckout(input) {
971
1071
  validateBranchName(input.branchName);
@@ -975,40 +1075,114 @@ function ensureVisibleGitCheckout(input) {
975
1075
  if (createdCheckout) {
976
1076
  import_node_fs.default.rmSync(branchPath, { recursive: true, force: true });
977
1077
  import_node_fs.default.mkdirSync(import_node_path.default.dirname(branchPath), { recursive: true });
978
- if (!tryGit(["clone", "--origin", "origin", input.githubRemoteUrl, branchPath], { auth: input.githubAuth })) {
1078
+ const cloned = tryGit(visibleCheckoutCloneArgs(input.remoteUrl, branchPath), {
1079
+ auth: input.remoteAuth
1080
+ });
1081
+ if (!cloned && input.requireRemoteBranch) {
1082
+ import_node_fs.default.rmSync(branchPath, { recursive: true, force: true });
1083
+ throw new Error(`Failed to clone canonical checkout for branch ${input.branchName}`);
1084
+ }
1085
+ if (!cloned) {
979
1086
  import_node_fs.default.mkdirSync(branchPath, { recursive: true });
980
1087
  runGit(["init"], { cwd: branchPath });
981
1088
  }
982
- ensureOriginRemote(branchPath, input.githubRemoteUrl);
983
- configureVisibleGitHubAuth(branchPath, input.githubRemoteUrl, input.githubAuthHeader);
1089
+ ensureOriginRemote(branchPath, input.remoteUrl);
1090
+ if (input.clearPersistentAuth) clearVisibleGitAuthentication(branchPath);
1091
+ else configureVisibleGitHubAuth(branchPath, input.remoteUrl, input.persistentAuthHeader);
984
1092
  (0, import_git_identity.configureVisibleGitIdentity)(branchPath, visibleGitIdentity, runGit);
985
- tryGit(["fetch", "origin", "--prune"], { cwd: branchPath, auth: input.githubAuth });
1093
+ tryGit(visibleCheckoutFetchArgs("origin", "--prune"), { cwd: branchPath, auth: input.remoteAuth });
1094
+ if (input.requireRemoteBranch && !tryGit(["show-ref", "--verify", "--quiet", `refs/remotes/origin/${input.branchName}`], { cwd: branchPath })) {
1095
+ import_node_fs.default.rmSync(branchPath, { recursive: true, force: true });
1096
+ throw new Error(`Canonical branch ${input.branchName} is unavailable after clone`);
1097
+ }
986
1098
  checkoutVisibleBranch({ branchPath, branchName: input.branchName, defaultBranch: input.defaultBranch });
1099
+ if (input.requiredBaseCommit) {
1100
+ try {
1101
+ assertCheckoutDerivedFromRequiredBase({
1102
+ branchPath,
1103
+ branchName: input.branchName,
1104
+ requiredBaseCommit: input.requiredBaseCommit
1105
+ });
1106
+ } catch (error) {
1107
+ import_node_fs.default.rmSync(branchPath, { recursive: true, force: true });
1108
+ throw error;
1109
+ }
1110
+ }
987
1111
  return branchPath;
988
1112
  }
1113
+ if (input.requireRemoteBranch) {
1114
+ if (input.allowRequiredRemoteMigration === false && originRemoteUrl(branchPath) !== input.remoteUrl) {
1115
+ throw new Error(`Canonical checkout ${input.branchName} no longer uses its required remote`);
1116
+ }
1117
+ migrateExistingCheckoutToRequiredRemote({
1118
+ branchPath,
1119
+ branchName: input.branchName,
1120
+ remoteUrl: input.remoteUrl,
1121
+ remoteAuth: input.remoteAuth,
1122
+ requiredBaseCommit: input.requiredBaseCommit
1123
+ });
1124
+ runGit(
1125
+ visibleCheckoutFetchArgs("--no-tags", input.remoteUrl, `+refs/heads/${input.branchName}:refs/remotes/origin/${input.branchName}`),
1126
+ {
1127
+ cwd: branchPath,
1128
+ auth: input.remoteAuth
1129
+ }
1130
+ );
1131
+ }
989
1132
  if (input.reconcileExistingOrigin) {
990
- ensureOriginRemote(branchPath, input.githubRemoteUrl);
1133
+ ensureOriginRemote(branchPath, input.remoteUrl);
1134
+ }
1135
+ if (input.requireRemoteBranch && !tryGit(["show-ref", "--verify", "--quiet", `refs/remotes/origin/${input.branchName}`], { cwd: branchPath })) {
1136
+ throw new Error(`Existing checkout for ${input.branchName} does not contain its canonical remote branch`);
1137
+ }
1138
+ if (input.requiredBaseCommit) {
1139
+ assertCheckoutDerivedFromRequiredBase({
1140
+ branchPath,
1141
+ branchName: input.branchName,
1142
+ requiredBaseCommit: input.requiredBaseCommit
1143
+ });
991
1144
  }
992
- configureVisibleGitHubAuth(branchPath, input.githubRemoteUrl, input.githubAuthHeader);
1145
+ if (input.clearPersistentAuth) clearVisibleGitAuthentication(branchPath);
1146
+ else configureVisibleGitHubAuth(branchPath, input.remoteUrl, input.persistentAuthHeader);
993
1147
  (0, import_git_identity.configureVisibleGitIdentity)(branchPath, visibleGitIdentity, runGit);
994
1148
  return branchPath;
995
1149
  }
996
1150
  function ensureBranchWorkspace(input) {
997
1151
  const defaultBranch = input.manifest?.defaultBranch || "main";
998
- const githubRemoteUrl = githubRemoteUrlFor(input.baseUrl, input.projectId, input.manifest);
999
- const githubAuth = gitAuthForRemote(githubRemoteUrl, input.manifest?.repoAuthHeader);
1152
+ const remote = visibleCheckoutRemoteFor(input);
1000
1153
  return {
1001
1154
  branchPath: ensureVisibleGitCheckout({
1002
1155
  projectRoot: input.projectRoot,
1003
1156
  branchName: input.branchName,
1004
- githubRemoteUrl,
1005
- githubAuth,
1006
- githubAuthHeader: input.manifest?.repoAuthHeader ?? null,
1157
+ remoteUrl: remote.remoteUrl,
1158
+ remoteAuth: gitAuthForRemote(remote.remoteUrl, remote.authHeader),
1159
+ persistentAuthHeader: remote.persistAuth ? remote.authHeader : null,
1007
1160
  defaultBranch,
1008
- reconcileExistingOrigin: Boolean(input.manifest?.repoHttpUrl)
1161
+ reconcileExistingOrigin: remote.reconcileExistingOrigin,
1162
+ requireRemoteBranch: remote.requireRemoteBranch,
1163
+ requiredBaseCommit: remote.requiredBaseCommit,
1164
+ clearPersistentAuth: !remote.persistAuth
1009
1165
  })
1010
1166
  };
1011
1167
  }
1168
+ function workspaceSyncCheckoutTargets(input) {
1169
+ const selected = /* @__PURE__ */ new Map();
1170
+ const add = (target) => {
1171
+ selected.set(`${target.projectId}\0${target.branchName}`, target);
1172
+ };
1173
+ if (input.canonicalCheckoutOnly) {
1174
+ add(input.canonicalCheckoutOnly);
1175
+ } else if (input.includeAllManifestCheckouts) {
1176
+ for (const project of input.projects) {
1177
+ for (const branchName of project.branches) add({ projectId: project.projectId, branchName });
1178
+ }
1179
+ } else {
1180
+ for (const target of input.pendingTargets) add(target);
1181
+ }
1182
+ return [...selected.values()].sort(
1183
+ (left, right) => left.projectId.localeCompare(right.projectId) || left.branchName.localeCompare(right.branchName)
1184
+ );
1185
+ }
1012
1186
  function resolveCommandCwd(branchPath, cwd) {
1013
1187
  if (!cwd) {
1014
1188
  return branchPath;
@@ -2232,6 +2406,7 @@ async function startWorker(options) {
2232
2406
  let reloadAfterClose = false;
2233
2407
  const workspaceSyncInput = (trigger, overrides = {}) => {
2234
2408
  if (!workspaceRemoteUrl) throw new Error("Worker workspace manifest has not been received");
2409
+ const projects = (0, import_workspace_sync.workspaceProjectsForSync)([...manifestByProjectId.values()], trigger);
2235
2410
  return {
2236
2411
  workerLabel: label,
2237
2412
  remoteUrl: workspaceRemoteUrl,
@@ -2239,7 +2414,7 @@ async function startWorker(options) {
2239
2414
  projectsRoot,
2240
2415
  plansRoot: planRoot,
2241
2416
  shadowRoot: workspaceShadowRoot,
2242
- projects: [...manifestByProjectId.values()],
2417
+ projects,
2243
2418
  trigger,
2244
2419
  ...overrides
2245
2420
  };
@@ -2251,7 +2426,7 @@ async function startWorker(options) {
2251
2426
  const allManifestCheckouts = () => [...manifestByProjectId.values()].flatMap(
2252
2427
  (manifest) => manifest.branches.map((branchName) => ({ projectId: manifest.projectId, branchName }))
2253
2428
  );
2254
- const ensureVisibleWorkspaceCheckouts = (targets) => {
2429
+ const ensureVisibleWorkspaceCheckouts = (targets, options2 = {}) => {
2255
2430
  const created = [];
2256
2431
  for (const target of targets) {
2257
2432
  const manifest = manifestByProjectId.get(target.projectId);
@@ -2263,15 +2438,25 @@ async function startWorker(options) {
2263
2438
  const projectRoot = projectRootFor(projectsRoot, manifest.projectId, manifestByProjectId);
2264
2439
  const branchPath = import_node_path.default.join(projectRoot, target.branchName);
2265
2440
  const existed = hasNormalVisibleGitDir(branchPath);
2266
- const githubRemoteUrl = githubRemoteUrlFor(baseUrl, manifest.projectId, manifest);
2441
+ const remote = visibleCheckoutRemoteFor({
2442
+ baseUrl,
2443
+ token,
2444
+ projectId: manifest.projectId,
2445
+ branchName: target.branchName,
2446
+ manifest
2447
+ });
2267
2448
  ensureVisibleGitCheckout({
2268
2449
  projectRoot,
2269
2450
  branchName: target.branchName,
2270
- githubRemoteUrl,
2271
- githubAuth: gitAuthForRemote(githubRemoteUrl, manifest.repoAuthHeader),
2272
- githubAuthHeader: manifest.repoAuthHeader,
2451
+ remoteUrl: remote.remoteUrl,
2452
+ remoteAuth: gitAuthForRemote(remote.remoteUrl, remote.authHeader),
2453
+ persistentAuthHeader: remote.persistAuth ? remote.authHeader : null,
2273
2454
  defaultBranch: manifest.defaultBranch || "main",
2274
- reconcileExistingOrigin: Boolean(manifest.repoHttpUrl)
2455
+ reconcileExistingOrigin: remote.reconcileExistingOrigin,
2456
+ requireRemoteBranch: remote.requireRemoteBranch,
2457
+ requiredBaseCommit: remote.requiredBaseCommit,
2458
+ allowRequiredRemoteMigration: !(options2.strictCanonicalRevalidation && remote.requireRemoteBranch),
2459
+ clearPersistentAuth: !remote.persistAuth
2275
2460
  });
2276
2461
  if (!existed) created.push(target);
2277
2462
  }
@@ -2283,15 +2468,30 @@ async function startWorker(options) {
2283
2468
  let pendingTargets = [];
2284
2469
  const result = await workspaceSyncSingleFlight.runPrepared(() => {
2285
2470
  const shouldEnsureCheckouts = !overrides.skipVisibleMirror && !overrides.resetToCanonical;
2471
+ const syncProjects = (0, import_workspace_sync.workspaceProjectsForSync)([...manifestByProjectId.values()], trigger);
2472
+ const allowedCheckoutKeys = new Set(
2473
+ syncProjects.flatMap((project) => project.branches.map((branchName) => manifestCheckoutKey(project.projectId, branchName)))
2474
+ );
2475
+ const scopedPendingTargets = [...pendingManifestCheckouts.values()].filter(
2476
+ (target) => allowedCheckoutKeys.has(manifestCheckoutKey(target.projectId, target.branchName))
2477
+ );
2286
2478
  let checkoutTargets = [];
2287
2479
  if (shouldEnsureCheckouts) {
2288
- checkoutTargets = trigger.type === "connect" ? allManifestCheckouts() : [...pendingManifestCheckouts.values()];
2480
+ checkoutTargets = workspaceSyncCheckoutTargets({
2481
+ projects: syncProjects,
2482
+ pendingTargets: scopedPendingTargets,
2483
+ includeAllManifestCheckouts: trigger.type === "connect",
2484
+ ...trigger.canonicalCheckoutOnly && trigger.projectId && trigger.branchName ? { canonicalCheckoutOnly: { projectId: trigger.projectId, branchName: trigger.branchName } } : {}
2485
+ });
2289
2486
  }
2290
- pendingTargets = shouldEnsureCheckouts ? [...pendingManifestCheckouts.values()] : [];
2291
- const createdCheckouts = ensureVisibleWorkspaceCheckouts(checkoutTargets);
2487
+ pendingTargets = shouldEnsureCheckouts ? scopedPendingTargets : [];
2488
+ const createdCheckouts = ensureVisibleWorkspaceCheckouts(checkoutTargets, {
2489
+ strictCanonicalRevalidation: true
2490
+ });
2292
2491
  const newVisibleCheckoutByKey = /* @__PURE__ */ new Map();
2293
2492
  for (const target of [...overrides.newVisibleCheckouts ?? [], ...createdCheckouts, ...pendingTargets]) {
2294
- newVisibleCheckoutByKey.set(manifestCheckoutKey(target.projectId, target.branchName), target);
2493
+ const key = manifestCheckoutKey(target.projectId, target.branchName);
2494
+ if (allowedCheckoutKeys.has(key)) newVisibleCheckoutByKey.set(key, target);
2295
2495
  }
2296
2496
  const newVisibleCheckouts = [...newVisibleCheckoutByKey.values()];
2297
2497
  return workspaceSyncInput(trigger, {
@@ -2367,7 +2567,8 @@ async function startWorker(options) {
2367
2567
  version: getWorkerVersion(),
2368
2568
  r5dctlVersion: (0, import_cli_update.readInstalledCliVersion)("r5dctl"),
2369
2569
  capabilities: {
2370
- updateClis: true
2570
+ updateClis: true,
2571
+ canonicalResolverCheckout: true
2371
2572
  },
2372
2573
  projectRoot: projectsRoot,
2373
2574
  artifactRoot,
@@ -2427,7 +2628,15 @@ async function startWorker(options) {
2427
2628
  if (!workspaceRemoteUrl || activeWorkspaceIncidentId || cliUpdateInProgress || periodicWorkspaceScanInFlight) return;
2428
2629
  periodicWorkspaceScanInFlight = true;
2429
2630
  void (async () => {
2430
- if (pendingManifestCheckouts.size > 0) {
2631
+ const genericCheckoutKeys = new Set(
2632
+ (0, import_workspace_sync.workspaceProjectsForSync)([...manifestByProjectId.values()], { type: "periodic" }).flatMap(
2633
+ (project) => project.branches.map((branchName) => manifestCheckoutKey(project.projectId, branchName))
2634
+ )
2635
+ );
2636
+ const hasPendingGenericCheckout = [...pendingManifestCheckouts.values()].some(
2637
+ (target) => genericCheckoutKeys.has(manifestCheckoutKey(target.projectId, target.branchName))
2638
+ );
2639
+ if (hasPendingGenericCheckout) {
2431
2640
  previousPeriodicFingerprint = null;
2432
2641
  await runRequestedWorkspaceSync(crypto.randomUUID(), {
2433
2642
  type: "periodic",
@@ -2845,5 +3054,8 @@ if (isCliEntrypoint()) {
2845
3054
  resolveHostShell,
2846
3055
  resolveWorkerFilePath,
2847
3056
  syncSessionArtifacts,
3057
+ visibleCheckoutGitTestHarness,
3058
+ visibleCheckoutRemoteFor,
3059
+ workspaceSyncCheckoutTargets,
2848
3060
  writeWorkerTextFile
2849
3061
  });
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.46",
3
+ "version": "0.0.47",
4
4
  "type": "commonjs"
5
5
  }