@pushpalsdev/cli 1.0.36 → 1.0.38

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.
Files changed (2) hide show
  1. package/dist/pushpals-cli.js +104 -49
  2. package/package.json +1 -1
@@ -6,12 +6,12 @@ import {
6
6
  appendFileSync,
7
7
  chmodSync,
8
8
  cpSync,
9
- existsSync as existsSync4,
9
+ existsSync as existsSync5,
10
10
  lstatSync,
11
11
  mkdirSync,
12
12
  readdirSync,
13
13
  readFileSync as readFileSync4,
14
- rmSync,
14
+ rmSync as rmSync2,
15
15
  writeFileSync
16
16
  } from "fs";
17
17
  import { basename, delimiter, dirname, extname, join as join2, resolve as resolve4, win32 as pathWin32 } from "path";
@@ -269,12 +269,60 @@ class ServiceManager {
269
269
  }
270
270
  }
271
271
 
272
+ // ../../apps/workerpals/src/common/worktree_cleanup.ts
273
+ import { existsSync, rmSync } from "fs";
274
+ function defaultSleep(ms) {
275
+ return new Promise((resolve) => setTimeout(resolve, ms));
276
+ }
277
+ function windowsDeletionCandidates(worktreePath) {
278
+ const seen = new Set;
279
+ const out = [];
280
+ const add = (value) => {
281
+ if (!value || seen.has(value))
282
+ return;
283
+ seen.add(value);
284
+ out.push(value);
285
+ };
286
+ add(worktreePath);
287
+ if (process.platform === "win32" && /^[A-Za-z]:[\\/]/.test(worktreePath)) {
288
+ add(`\\\\?\\${worktreePath}`);
289
+ }
290
+ return out;
291
+ }
292
+ async function forceDeleteWorktreePath(worktreePath, options = {}) {
293
+ const retries = Math.max(1, Math.floor(options.retries ?? 5));
294
+ const delayMs = Math.max(0, Math.floor(options.delayMs ?? 120));
295
+ const sleep = options.sleepFn ?? defaultSleep;
296
+ const removePath = options.removeFn ?? ((targetPath) => rmSync(targetPath, { recursive: true, force: true }));
297
+ const pathExists = options.existsFn ?? ((targetPath) => existsSync(targetPath));
298
+ let lastError = "";
299
+ for (let attempt = 1;attempt <= retries; attempt++) {
300
+ if (!pathExists(worktreePath))
301
+ return { removed: true };
302
+ for (const candidate of windowsDeletionCandidates(worktreePath)) {
303
+ try {
304
+ removePath(candidate);
305
+ } catch (error) {
306
+ lastError = String(error);
307
+ }
308
+ }
309
+ if (!pathExists(worktreePath))
310
+ return { removed: true };
311
+ if (attempt < retries)
312
+ await sleep(delayMs * attempt);
313
+ }
314
+ return {
315
+ removed: !pathExists(worktreePath),
316
+ ...lastError ? { lastError } : {}
317
+ };
318
+ }
319
+
272
320
  // ../shared/src/client_preflight.ts
273
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
321
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
274
322
  import { relative, resolve as resolve2 } from "path";
275
323
 
276
324
  // ../shared/src/config.ts
277
- import { existsSync, readFileSync } from "fs";
325
+ import { existsSync as existsSync2, readFileSync } from "fs";
278
326
  import { join, resolve, isAbsolute } from "path";
279
327
 
280
328
  // ../shared/src/autonomy_policy.ts
@@ -399,7 +447,7 @@ function parseIntEnv(name) {
399
447
  return Number.isFinite(parsed) ? parsed : null;
400
448
  }
401
449
  function parseTomlFile(path) {
402
- if (!existsSync(path))
450
+ if (!existsSync2(path))
403
451
  return {};
404
452
  const raw = readFileSync(path, "utf-8");
405
453
  const parsed = Bun.TOML.parse(raw);
@@ -408,7 +456,7 @@ function parseTomlFile(path) {
408
456
  return parsed;
409
457
  }
410
458
  function parseRequiredTomlFile(path) {
411
- if (!existsSync(path)) {
459
+ if (!existsSync2(path)) {
412
460
  throw new Error(`Missing required runtime config file: ${path}`);
413
461
  }
414
462
  return parseTomlFile(path);
@@ -1201,7 +1249,7 @@ function validateVisionDocStructure(markdown) {
1201
1249
  // ../shared/src/client_preflight.ts
1202
1250
  function runtimeHasConfigDir(runtimeRoot, dirName) {
1203
1251
  const dirPath = resolve2(runtimeRoot, dirName);
1204
- return existsSync2(resolve2(dirPath, "default.toml")) || existsSync2(resolve2(dirPath, "local.example.toml")) || existsSync2(resolve2(dirPath, "local.toml"));
1252
+ return existsSync3(resolve2(dirPath, "default.toml")) || existsSync3(resolve2(dirPath, "local.example.toml")) || existsSync3(resolve2(dirPath, "local.toml"));
1205
1253
  }
1206
1254
  function resolveClientConfigDir(projectRoot, runtimeRoot, explicitConfigDir) {
1207
1255
  if (explicitConfigDir && explicitConfigDir.trim()) {
@@ -1255,21 +1303,21 @@ function evaluateClientRuntimePreflight(options) {
1255
1303
  });
1256
1304
  const issues = [];
1257
1305
  const envPath = resolve2(runtimeRoot, ".env");
1258
- if (!existsSync2(envPath)) {
1306
+ if (!existsSync3(envPath)) {
1259
1307
  const envExamplePath = resolve2(runtimeRoot, ".env.example");
1260
1308
  issues.push({
1261
1309
  code: "missing_env_file",
1262
1310
  message: `Missing required local env file: ${toDisplayPath(projectRoot, envPath)}.`,
1263
- copyCommands: existsSync2(envExamplePath) ? buildCopyCommands(projectRoot, envExamplePath, envPath) : undefined
1311
+ copyCommands: existsSync3(envExamplePath) ? buildCopyCommands(projectRoot, envExamplePath, envPath) : undefined
1264
1312
  });
1265
1313
  }
1266
1314
  const localTomlPath = resolve2(runtimeRoot, "configs", "local.toml");
1267
- if (!existsSync2(localTomlPath)) {
1315
+ if (!existsSync3(localTomlPath)) {
1268
1316
  const localExamplePath = resolve2(runtimeRoot, "configs", "local.example.toml");
1269
1317
  issues.push({
1270
1318
  code: "missing_local_toml",
1271
1319
  message: `Missing required local config file: ${toDisplayPath(projectRoot, localTomlPath)}.`,
1272
- copyCommands: existsSync2(localExamplePath) ? buildCopyCommands(projectRoot, localExamplePath, localTomlPath) : undefined
1320
+ copyCommands: existsSync3(localExamplePath) ? buildCopyCommands(projectRoot, localExamplePath, localTomlPath) : undefined
1273
1321
  });
1274
1322
  }
1275
1323
  const autonomyEnabled = Boolean(config.remotebuddy.autonomy.enabled);
@@ -1286,11 +1334,11 @@ function evaluateClientRuntimePreflight(options) {
1286
1334
  }
1287
1335
  const visionPath = resolve2(projectRoot, "vision.md");
1288
1336
  const visionTemplatePath = resolve2(visionTemplateRoot, "vision.example.md");
1289
- if (!existsSync2(visionPath)) {
1337
+ if (!existsSync3(visionPath)) {
1290
1338
  issues.push({
1291
1339
  code: "missing_vision_doc",
1292
1340
  message: "Missing required autonomy vision file: vision.md " + "(required when remotebuddy.autonomy.enabled=true).",
1293
- copyCommands: existsSync2(visionTemplatePath) ? buildCopyCommands(projectRoot, visionTemplatePath, visionPath) : undefined
1341
+ copyCommands: existsSync3(visionTemplatePath) ? buildCopyCommands(projectRoot, visionTemplatePath, visionPath) : undefined
1294
1342
  });
1295
1343
  return {
1296
1344
  ok: false,
@@ -1404,14 +1452,14 @@ function normalizePresenceLookupToken(value) {
1404
1452
  }
1405
1453
 
1406
1454
  // ../shared/src/repo.ts
1407
- import { existsSync as existsSync3, readFileSync as readFileSync3, statSync } from "fs";
1455
+ import { existsSync as existsSync4, readFileSync as readFileSync3, statSync } from "fs";
1408
1456
  import { resolve as resolve3 } from "path";
1409
1457
  function resolveDotGitEntry(repoRoot) {
1410
1458
  return resolve3(repoRoot, ".git");
1411
1459
  }
1412
1460
  function resolveGitMetadataDir(repoRoot) {
1413
1461
  const dotGitPath = resolveDotGitEntry(repoRoot);
1414
- if (!existsSync3(dotGitPath))
1462
+ if (!existsSync4(dotGitPath))
1415
1463
  return null;
1416
1464
  try {
1417
1465
  const stat = statSync(dotGitPath);
@@ -1430,7 +1478,7 @@ function resolveGitMetadataDir(repoRoot) {
1430
1478
  if (!match)
1431
1479
  return null;
1432
1480
  const gitDir = resolve3(repoRoot, match[1].trim());
1433
- return existsSync3(gitDir) ? gitDir : null;
1481
+ return existsSync4(gitDir) ? gitDir : null;
1434
1482
  } catch {
1435
1483
  return null;
1436
1484
  }
@@ -1856,7 +1904,7 @@ function copyTrackedRepoPath(repoRoot, sourcePath, destinationPath, force = true
1856
1904
  throw new Error("sourcePath is required");
1857
1905
  }
1858
1906
  const absoluteSource = resolve4(repoRoot, normalizedSource);
1859
- if (!existsSync4(absoluteSource)) {
1907
+ if (!existsSync5(absoluteSource)) {
1860
1908
  throw new Error(`tracked repo source is missing: ${absoluteSource}`);
1861
1909
  }
1862
1910
  const trackedFiles = listTrackedRepoFilesForPath(repoRoot, normalizedSource);
@@ -1889,7 +1937,7 @@ function copyTrackedRepoPath(repoRoot, sourcePath, destinationPath, force = true
1889
1937
  }
1890
1938
  }
1891
1939
  function isCompleteWorkerpalSandboxRoot(root) {
1892
- return existsSync4(join2(root, "package.json")) && existsSync4(join2(root, "apps", "workerpals", "Dockerfile.sandbox")) && existsSync4(join2(root, "packages", "shared", "package.json")) && existsSync4(join2(root, "packages", "protocol", "package.json")) && existsSync4(join2(root, "configs", "default.toml")) && existsSync4(join2(root, "prompts", "workerpals")) && existsSync4(join2(root, "protocol", "schemas", "envelope.schema.json")) && existsSync4(join2(root, "protocol", "schemas", "events.schema.json"));
1940
+ return existsSync5(join2(root, "package.json")) && existsSync5(join2(root, "apps", "workerpals", "Dockerfile.sandbox")) && existsSync5(join2(root, "packages", "shared", "package.json")) && existsSync5(join2(root, "packages", "protocol", "package.json")) && existsSync5(join2(root, "configs", "default.toml")) && existsSync5(join2(root, "prompts", "workerpals")) && existsSync5(join2(root, "protocol", "schemas", "envelope.schema.json")) && existsSync5(join2(root, "protocol", "schemas", "events.schema.json"));
1893
1941
  }
1894
1942
  function populateWorkerpalSandboxRuntimeAssets(runtimeRoot, force) {
1895
1943
  const sandbox = buildWorkerpalSandboxPaths(runtimeRoot);
@@ -1920,7 +1968,7 @@ function copySourceCheckoutWorkerpalSandboxBuildContext(sourceRoot, runtimeRoot,
1920
1968
  for (const [fromPath, toPath] of copyPairs) {
1921
1969
  copyTrackedRepoPath(sourceRoot, fromPath, toPath, force);
1922
1970
  }
1923
- if (existsSync4(join2(sourceRoot, "bun.lock"))) {
1971
+ if (existsSync5(join2(sourceRoot, "bun.lock"))) {
1924
1972
  copyTrackedRepoPath(sourceRoot, "bun.lock", join2(sandbox.root, "bun.lock"), force);
1925
1973
  }
1926
1974
  populateWorkerpalSandboxRuntimeAssets(runtimeRoot, force);
@@ -1938,7 +1986,7 @@ function copyWorkerpalSandboxBuildContext(source, runtimeRoot, force) {
1938
1986
  copySourceCheckoutWorkerpalSandboxBuildContext(source.root, runtimeRoot, force);
1939
1987
  }
1940
1988
  function isCompleteRuntimeAssetSource(source) {
1941
- return existsSync4(source.envExamplePath) && existsSync4(source.visionExamplePath) && existsSync4(join2(source.configsDir, "default.toml")) && existsSync4(source.promptsDir) && existsSync4(join2(source.protocolSchemasDir, "envelope.schema.json")) && existsSync4(join2(source.protocolSchemasDir, "events.schema.json"));
1989
+ return existsSync5(source.envExamplePath) && existsSync5(source.visionExamplePath) && existsSync5(join2(source.configsDir, "default.toml")) && existsSync5(source.promptsDir) && existsSync5(join2(source.protocolSchemasDir, "envelope.schema.json")) && existsSync5(join2(source.protocolSchemasDir, "events.schema.json"));
1942
1990
  }
1943
1991
  function resolveBundledRuntimeAssetSource() {
1944
1992
  const candidates = [
@@ -1953,10 +2001,10 @@ function resolveBundledRuntimeAssetSource() {
1953
2001
  return null;
1954
2002
  }
1955
2003
  function looksLikeMonitoringHubBuild(root) {
1956
- return existsSync4(join2(root, "index.html")) && existsSync4(join2(root, "_expo"));
2004
+ return existsSync5(join2(root, "index.html")) && existsSync5(join2(root, "_expo"));
1957
2005
  }
1958
2006
  function latestPathMtimeMs(pathValue) {
1959
- if (!existsSync4(pathValue))
2007
+ if (!existsSync5(pathValue))
1960
2008
  return 0;
1961
2009
  const stat = lstatSync(pathValue);
1962
2010
  let latest = stat.mtimeMs;
@@ -2009,7 +2057,7 @@ function resolveCliSourceCheckoutRoot() {
2009
2057
  resolve4(import.meta.dir, "..", "..", "..")
2010
2058
  ];
2011
2059
  for (const candidate of candidates) {
2012
- if (existsSync4(join2(candidate, "package.json")) && existsSync4(join2(candidate, "apps", "client", "app.json")) && existsSync4(join2(candidate, "scripts", "sync-cli-monitor-ui.ts"))) {
2060
+ if (existsSync5(join2(candidate, "package.json")) && existsSync5(join2(candidate, "apps", "client", "app.json")) && existsSync5(join2(candidate, "scripts", "sync-cli-monitor-ui.ts"))) {
2013
2061
  return candidate;
2014
2062
  }
2015
2063
  }
@@ -2043,7 +2091,7 @@ async function ensureBundledMonitoringHubRoot() {
2043
2091
  return resolveBundledMonitoringHubRoot();
2044
2092
  }
2045
2093
  function repoLooksLikePushPalsSourceCheckout(repoRoot) {
2046
- return existsSync4(join2(repoRoot, "configs", "default.toml"));
2094
+ return existsSync5(join2(repoRoot, "configs", "default.toml"));
2047
2095
  }
2048
2096
  function parseSemverFromPackageVersion(value) {
2049
2097
  const raw = String(value ?? "").trim();
@@ -2093,13 +2141,13 @@ async function resolveRuntimeReleaseTag(explicitTag) {
2093
2141
  return await fetchLatestReleaseTag();
2094
2142
  }
2095
2143
  function writeTextFileIfMissing(pathValue, text) {
2096
- if (existsSync4(pathValue))
2144
+ if (existsSync5(pathValue))
2097
2145
  return;
2098
2146
  mkdirSync(dirname(pathValue), { recursive: true });
2099
2147
  writeFileSync(pathValue, text, "utf8");
2100
2148
  }
2101
2149
  function migrateEmbeddedRuntimeLocalToml(localTomlPath) {
2102
- if (!existsSync4(localTomlPath))
2150
+ if (!existsSync5(localTomlPath))
2103
2151
  return;
2104
2152
  let original;
2105
2153
  try {
@@ -2149,8 +2197,8 @@ function copyBundledRuntimeAssets(runtimeRoot, force = true) {
2149
2197
  }
2150
2198
  function hasSeededRuntimePreflightAssets(runtimeRoot) {
2151
2199
  const protocolSchemasDir = join2(runtimeRoot, "protocol", "schemas");
2152
- const hasProtocolSchemas = existsSync4(join2(protocolSchemasDir, "envelope.schema.json")) && existsSync4(join2(protocolSchemasDir, "events.schema.json"));
2153
- return existsSync4(join2(runtimeRoot, ".env.example")) && existsSync4(join2(runtimeRoot, "vision.example.md")) && existsSync4(join2(runtimeRoot, "configs", "default.toml")) && existsSync4(join2(runtimeRoot, "prompts")) && hasProtocolSchemas && isCompleteWorkerpalSandboxRoot(join2(runtimeRoot, "sandbox"));
2200
+ const hasProtocolSchemas = existsSync5(join2(protocolSchemasDir, "envelope.schema.json")) && existsSync5(join2(protocolSchemasDir, "events.schema.json"));
2201
+ return existsSync5(join2(runtimeRoot, ".env.example")) && existsSync5(join2(runtimeRoot, "vision.example.md")) && existsSync5(join2(runtimeRoot, "configs", "default.toml")) && existsSync5(join2(runtimeRoot, "prompts")) && hasProtocolSchemas && isCompleteWorkerpalSandboxRoot(join2(runtimeRoot, "sandbox"));
2154
2202
  }
2155
2203
  function seedRuntimePreflightAssets(runtimeRoot) {
2156
2204
  if (!hasSeededRuntimePreflightAssets(runtimeRoot)) {
@@ -2160,7 +2208,7 @@ function seedRuntimePreflightAssets(runtimeRoot) {
2160
2208
  `);
2161
2209
  const localExamplePath = join2(runtimeRoot, "configs", "local.example.toml");
2162
2210
  const localTomlPath = join2(runtimeRoot, "configs", "local.toml");
2163
- if (existsSync4(localExamplePath)) {
2211
+ if (existsSync5(localExamplePath)) {
2164
2212
  writeTextFileIfMissing(localTomlPath, readFileSync4(localExamplePath, "utf8"));
2165
2213
  } else {
2166
2214
  writeTextFileIfMissing(localTomlPath, `# Local PushPals runtime overrides
@@ -2205,15 +2253,15 @@ async function downloadRuntimeAssetsFromSourceTag(runtimeRoot, tag) {
2205
2253
  async function ensureRuntimeAssets(runtimeRoot, runtimeTag) {
2206
2254
  console.log(`[pushpals] Preparing embedded runtime assets for ${runtimeTag}...`);
2207
2255
  const markerPath = join2(runtimeRoot, ".runtime-assets-tag");
2208
- const currentTag = existsSync4(markerPath) ? readFileSync4(markerPath, "utf8").trim() : "";
2256
+ const currentTag = existsSync5(markerPath) ? readFileSync4(markerPath, "utf8").trim() : "";
2209
2257
  const protocolSchemasDir = join2(runtimeRoot, "protocol", "schemas");
2210
- const hasProtocolSchemas = existsSync4(join2(protocolSchemasDir, "envelope.schema.json")) && existsSync4(join2(protocolSchemasDir, "events.schema.json"));
2211
- const hasAssets = existsSync4(join2(runtimeRoot, ".env.example")) && existsSync4(join2(runtimeRoot, "vision.example.md")) && existsSync4(join2(runtimeRoot, "configs", "default.toml")) && existsSync4(join2(runtimeRoot, "prompts")) && hasProtocolSchemas && isCompleteWorkerpalSandboxRoot(join2(runtimeRoot, "sandbox"));
2258
+ const hasProtocolSchemas = existsSync5(join2(protocolSchemasDir, "envelope.schema.json")) && existsSync5(join2(protocolSchemasDir, "events.schema.json"));
2259
+ const hasAssets = existsSync5(join2(runtimeRoot, ".env.example")) && existsSync5(join2(runtimeRoot, "vision.example.md")) && existsSync5(join2(runtimeRoot, "configs", "default.toml")) && existsSync5(join2(runtimeRoot, "prompts")) && hasProtocolSchemas && isCompleteWorkerpalSandboxRoot(join2(runtimeRoot, "sandbox"));
2212
2260
  if (!hasAssets || currentTag !== runtimeTag) {
2213
2261
  console.log(`[pushpals] Embedded runtime assets ${hasAssets ? "are stale" : "are missing"}; refreshing bundle...`);
2214
2262
  copyBundledRuntimeAssets(runtimeRoot);
2215
- const hasProtocolSchemasAfterCopy = existsSync4(join2(protocolSchemasDir, "envelope.schema.json")) && existsSync4(join2(protocolSchemasDir, "events.schema.json"));
2216
- const hasAssetsAfterCopy = existsSync4(join2(runtimeRoot, ".env.example")) && existsSync4(join2(runtimeRoot, "vision.example.md")) && existsSync4(join2(runtimeRoot, "configs", "default.toml")) && existsSync4(join2(runtimeRoot, "prompts")) && hasProtocolSchemasAfterCopy && isCompleteWorkerpalSandboxRoot(join2(runtimeRoot, "sandbox"));
2263
+ const hasProtocolSchemasAfterCopy = existsSync5(join2(protocolSchemasDir, "envelope.schema.json")) && existsSync5(join2(protocolSchemasDir, "events.schema.json"));
2264
+ const hasAssetsAfterCopy = existsSync5(join2(runtimeRoot, ".env.example")) && existsSync5(join2(runtimeRoot, "vision.example.md")) && existsSync5(join2(runtimeRoot, "configs", "default.toml")) && existsSync5(join2(runtimeRoot, "prompts")) && hasProtocolSchemasAfterCopy && isCompleteWorkerpalSandboxRoot(join2(runtimeRoot, "sandbox"));
2217
2265
  if (!hasAssetsAfterCopy) {
2218
2266
  console.log("[pushpals] Bundled runtime assets are incomplete; falling back to release source downloads...");
2219
2267
  await downloadRuntimeAssetsFromSourceTag(runtimeRoot, runtimeTag);
@@ -2225,7 +2273,7 @@ async function ensureRuntimeAssets(runtimeRoot, runtimeTag) {
2225
2273
  `);
2226
2274
  const localExamplePath = join2(runtimeRoot, "configs", "local.example.toml");
2227
2275
  const localTomlPath = join2(runtimeRoot, "configs", "local.toml");
2228
- if (existsSync4(localExamplePath)) {
2276
+ if (existsSync5(localExamplePath)) {
2229
2277
  writeTextFileIfMissing(localTomlPath, readFileSync4(localExamplePath, "utf8"));
2230
2278
  } else {
2231
2279
  writeTextFileIfMissing(localTomlPath, `# Local PushPals runtime overrides
@@ -2279,12 +2327,12 @@ function runtimeBinaryFilename(serviceName, platformKey) {
2279
2327
  function resolveRuntimeBinaryInstallState(runtimeRoot, platformKey) {
2280
2328
  const binDir = join2(runtimeRoot, "bin", platformKey);
2281
2329
  const tagMarkerPath = join2(binDir, ".runtime-tag");
2282
- const installedTag = existsSync4(tagMarkerPath) ? readFileSync4(tagMarkerPath, "utf8").trim() : "";
2330
+ const installedTag = existsSync5(tagMarkerPath) ? readFileSync4(tagMarkerPath, "utf8").trim() : "";
2283
2331
  return { binDir, tagMarkerPath, installedTag };
2284
2332
  }
2285
2333
  function cleanupLegacyRuntimeBinaryLayouts(runtimeRoot, platformKey, activeBinDir) {
2286
2334
  const legacyRoot = join2(runtimeRoot, "bin");
2287
- if (!existsSync4(legacyRoot))
2335
+ if (!existsSync5(legacyRoot))
2288
2336
  return;
2289
2337
  let entries;
2290
2338
  try {
@@ -2301,7 +2349,7 @@ function cleanupLegacyRuntimeBinaryLayouts(runtimeRoot, platformKey, activeBinDi
2301
2349
  if (!entry.name.endsWith(`-${platformKey}`))
2302
2350
  continue;
2303
2351
  try {
2304
- rmSync(candidateDir, { recursive: true, force: true });
2352
+ rmSync2(candidateDir, { recursive: true, force: true });
2305
2353
  } catch {}
2306
2354
  }
2307
2355
  }
@@ -2373,7 +2421,7 @@ function resolveEmbeddedBunExecutableFromEnv(env, platform = process.platform, c
2373
2421
  continue;
2374
2422
  for (const candidate of candidates) {
2375
2423
  const fullPath = join2(dir, candidate);
2376
- if (existsSync4(fullPath)) {
2424
+ if (existsSync5(fullPath)) {
2377
2425
  return fullPath;
2378
2426
  }
2379
2427
  }
@@ -2446,7 +2494,7 @@ function appendRuntimeServicesLogLine(logPath, line) {
2446
2494
  } catch {}
2447
2495
  }
2448
2496
  function readLogTail(logPath, maxLines = 40) {
2449
- if (!existsSync4(logPath))
2497
+ if (!existsSync5(logPath))
2450
2498
  return "";
2451
2499
  const raw = readFileSync4(logPath, "utf8");
2452
2500
  const lines = raw.split(/\r?\n/).map((line) => line.trimEnd()).filter((line) => line.length > 0);
@@ -2472,7 +2520,7 @@ function extractRemoteBuddyAutonomousEngineState(logText) {
2472
2520
  return state;
2473
2521
  }
2474
2522
  function readRemoteBuddyAutonomousEngineState(logPath) {
2475
- if (!existsSync4(logPath))
2523
+ if (!existsSync5(logPath))
2476
2524
  return "unknown";
2477
2525
  try {
2478
2526
  return extractRemoteBuddyAutonomousEngineState(readFileSync4(logPath, "utf8"));
@@ -2514,7 +2562,7 @@ async function ensureRuntimeBinaries(runtimeRoot, runtimeTag) {
2514
2562
  const shouldRefreshAll = installedTag !== runtimeTag;
2515
2563
  let downloadedCount = 0;
2516
2564
  for (const binaryPath of requiredAssets) {
2517
- if (!shouldRefreshAll && existsSync4(binaryPath))
2565
+ if (!shouldRefreshAll && existsSync5(binaryPath))
2518
2566
  continue;
2519
2567
  const assetName = binaryPath.split(/[\\/]/).pop() || "";
2520
2568
  await downloadBinaryAsset(runtimeTag, assetName, binaryPath);
@@ -2918,6 +2966,7 @@ async function cleanupLingeringWorkerpalWarmContainers(opts) {
2918
2966
  }
2919
2967
  async function cleanupLingeringPushPalsGitWorktrees(opts) {
2920
2968
  const runCommandWithEnvFn = opts.runCommandWithEnvFn ?? runCommandWithEnv;
2969
+ const forceDeleteWorktreePathFn = opts.forceDeleteWorktreePathFn ?? forceDeleteWorktreePath;
2921
2970
  const list = await runCommandWithEnvFn(["git", "worktree", "list", "--porcelain"], opts.repoRoot, opts.env);
2922
2971
  if (!list.ok) {
2923
2972
  const detail = list.stderr || list.stdout || `exit ${list.exitCode}`;
@@ -2945,7 +2994,13 @@ async function cleanupLingeringPushPalsGitWorktrees(opts) {
2945
2994
  removed += 1;
2946
2995
  continue;
2947
2996
  }
2948
- failures.push(`${entry.path}: ${remove.stderr || remove.stdout || `exit ${remove.exitCode}`}`);
2997
+ const forced = await forceDeleteWorktreePathFn(entry.path);
2998
+ if (forced.removed) {
2999
+ removed += 1;
3000
+ continue;
3001
+ }
3002
+ const removeDetail = remove.stderr || remove.stdout || `exit ${remove.exitCode}`;
3003
+ failures.push(`${entry.path}: ${removeDetail}${forced.lastError ? ` | fallback: ${forced.lastError}` : ""}`);
2949
3004
  }
2950
3005
  const prune = await runCommandWithEnvFn(["git", "worktree", "prune"], opts.repoRoot, opts.env);
2951
3006
  if (!prune.ok) {
@@ -3300,10 +3355,10 @@ function buildCliClearTargets(opts) {
3300
3355
  return targets;
3301
3356
  }
3302
3357
  function removeCliClearTarget(target) {
3303
- if (!existsSync4(target.path))
3358
+ if (!existsSync5(target.path))
3304
3359
  return "missing";
3305
3360
  try {
3306
- rmSync(target.path, { recursive: true, force: true });
3361
+ rmSync2(target.path, { recursive: true, force: true });
3307
3362
  return "removed";
3308
3363
  } catch (err) {
3309
3364
  return {
@@ -4000,7 +4055,7 @@ ${tail}` : ""}`);
4000
4055
  throw new Error(`Timed out waiting for LocalBuddy at ${opts.localAgentUrl} and RemoteBuddy session consumer after ${DEFAULT_RUNTIME_BOOT_TIMEOUT_MS}ms`);
4001
4056
  }
4002
4057
  function readCliState(pathValue) {
4003
- if (!existsSync4(pathValue))
4058
+ if (!existsSync5(pathValue))
4004
4059
  return {};
4005
4060
  try {
4006
4061
  const raw = readFileSync4(pathValue, "utf8");
@@ -4103,11 +4158,11 @@ function resolveMonitoringHubAssetPath(assetRoot, pathname) {
4103
4158
  const candidatePath = resolve4(root, relativePath);
4104
4159
  if (candidatePath !== root && !candidatePath.startsWith(rootPrefix))
4105
4160
  return null;
4106
- if (existsSync4(candidatePath))
4161
+ if (existsSync5(candidatePath))
4107
4162
  return candidatePath;
4108
4163
  if (!extname(relativePath)) {
4109
4164
  const nestedIndexPath = resolve4(root, relativePath, "index.html");
4110
- if ((nestedIndexPath === root || nestedIndexPath.startsWith(rootPrefix)) && existsSync4(nestedIndexPath)) {
4165
+ if ((nestedIndexPath === root || nestedIndexPath.startsWith(rootPrefix)) && existsSync5(nestedIndexPath)) {
4111
4166
  return nestedIndexPath;
4112
4167
  }
4113
4168
  return join2(root, "index.html");
@@ -4116,7 +4171,7 @@ function resolveMonitoringHubAssetPath(assetRoot, pathname) {
4116
4171
  }
4117
4172
  async function serveBundledMonitoringHub(assetRoot, pathname, bootstrap) {
4118
4173
  const assetPath = resolveMonitoringHubAssetPath(assetRoot, pathname);
4119
- if (!assetPath || !existsSync4(assetPath))
4174
+ if (!assetPath || !existsSync5(assetPath))
4120
4175
  return null;
4121
4176
  if (assetPath.endsWith("index.html")) {
4122
4177
  const html = injectMonitoringHubBootstrap(readFileSync4(assetPath, "utf8"), bootstrap);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushpalsdev/cli",
3
- "version": "1.0.36",
3
+ "version": "1.0.38",
4
4
  "description": "PushPals terminal CLI for LocalBuddy -> RemoteBuddy orchestration",
5
5
  "license": "MIT",
6
6
  "repository": {