@wspc/cli 0.1.10 → 0.1.12

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/cli.js CHANGED
@@ -1520,9 +1520,9 @@ function createConsistencyFetch(opts) {
1520
1520
  }
1521
1521
 
1522
1522
  // src/version.ts
1523
- var VERSION = "0.1.10";
1523
+ var VERSION = "0.1.12";
1524
1524
  var SPEC_SHA = "bec760cd";
1525
- var SPEC_FETCHED_AT = "2026-07-07T06:24:39.560Z";
1525
+ var SPEC_FETCHED_AT = "2026-07-08T02:10:53.728Z";
1526
1526
  var API_BASE = "https://api.wspc.ai";
1527
1527
 
1528
1528
  // src/index.ts
@@ -5040,17 +5040,18 @@ async function writeDriveRealtimeState(root, realtime) {
5040
5040
  async function withDriveLock(root, fn) {
5041
5041
  await mkdir(join2(root, DRIVE_DIR), { recursive: true });
5042
5042
  const lockFile = join2(root, DRIVE_DIR, "sync.lock");
5043
- const fh = await open(lockFile, "wx").catch(async (error) => {
5043
+ const acquire = async () => {
5044
+ const handle = await open(lockFile, "wx");
5045
+ await handle.writeFile(String(process.pid));
5046
+ return handle;
5047
+ };
5048
+ const fh = await acquire().catch(async (error) => {
5044
5049
  if (error.code !== "EEXIST") throw error;
5045
- const lockStat = await stat2(lockFile).catch((statError) => {
5046
- if (statError.code === "ENOENT") return void 0;
5047
- throw statError;
5048
- });
5049
- if (lockStat && Date.now() - lockStat.mtimeMs <= STALE_LOCK_MS) {
5050
+ if (!await isLockAbandoned(lockFile)) {
5050
5051
  throw new Error("sync lock already exists");
5051
5052
  }
5052
5053
  await rm(lockFile, { force: true });
5053
- return open(lockFile, "wx").catch((retryError) => {
5054
+ return acquire().catch((retryError) => {
5054
5055
  if (retryError.code === "EEXIST") {
5055
5056
  throw new Error("sync lock already exists");
5056
5057
  }
@@ -5066,6 +5067,28 @@ async function withDriveLock(root, fn) {
5066
5067
  });
5067
5068
  }
5068
5069
  }
5070
+ async function isLockAbandoned(lockFile) {
5071
+ const pid = await readLockPid(lockFile);
5072
+ if (pid !== void 0 && !isProcessAlive(pid)) return true;
5073
+ const lockStat = await stat2(lockFile).catch((statError) => {
5074
+ if (statError.code === "ENOENT") return void 0;
5075
+ throw statError;
5076
+ });
5077
+ return lockStat === void 0 || Date.now() - lockStat.mtimeMs > STALE_LOCK_MS;
5078
+ }
5079
+ async function readLockPid(lockFile) {
5080
+ const text = await readFile2(lockFile, "utf8").catch(() => void 0);
5081
+ if (text === void 0 || !/^\d+$/.test(text.trim())) return void 0;
5082
+ return Number(text.trim());
5083
+ }
5084
+ function isProcessAlive(pid) {
5085
+ try {
5086
+ process.kill(pid, 0);
5087
+ return true;
5088
+ } catch (error) {
5089
+ return error.code !== "ESRCH";
5090
+ }
5091
+ }
5069
5092
  function isRecord2(value) {
5070
5093
  return typeof value === "object" && value !== null && !Array.isArray(value);
5071
5094
  }
@@ -6302,6 +6325,7 @@ function containsVersionConflict(value) {
6302
6325
  // src/handwritten/commands/drive/watch.ts
6303
6326
  import { Command as Command81 } from "commander";
6304
6327
  import chokidar from "chokidar";
6328
+ import { watch as fsWatch } from "fs";
6305
6329
  import { relative as relative2, resolve as resolve4 } from "path";
6306
6330
 
6307
6331
  // src/handwritten/commands/drive/realtime.ts
@@ -6627,6 +6651,7 @@ async function runDriveWatch(root, options = {}) {
6627
6651
  do {
6628
6652
  rerunRequested = false;
6629
6653
  try {
6654
+ emit({ kind: "drive_sync_start" });
6630
6655
  const summary = await runSync(root);
6631
6656
  emit({ kind: "drive_sync_once", ...summary });
6632
6657
  backoffMs = 1e3;
@@ -6718,7 +6743,7 @@ async function runDriveWatch(root, options = {}) {
6718
6743
  writeRealtimeState: (next) => writeDriveRealtimeState(root, next)
6719
6744
  });
6720
6745
  }
6721
- source = options.source ?? createChokidarSource(root);
6746
+ source = options.source ?? createDefaultWatchSource(root);
6722
6747
  source.onChange((path) => {
6723
6748
  if (isDriveInternalPath(root, path)) return;
6724
6749
  scheduleSync(debounceMs);
@@ -6767,6 +6792,27 @@ function driveWatchCommand(options = {}) {
6767
6792
  await runDriveWatch(resolve4(path), options);
6768
6793
  });
6769
6794
  }
6795
+ function createDefaultWatchSource(root) {
6796
+ return process.platform === "win32" ? createNativeRecursiveSource(root) : createChokidarSource(root);
6797
+ }
6798
+ function createNativeRecursiveSource(root) {
6799
+ const handlers = [];
6800
+ const watcher = fsWatch(root, { recursive: true }, (_event, filename) => {
6801
+ if (filename === null) return;
6802
+ const path = resolve4(root, filename.toString());
6803
+ for (const handler of handlers) handler(path);
6804
+ });
6805
+ watcher.on("error", () => {
6806
+ });
6807
+ return {
6808
+ onChange(handler) {
6809
+ handlers.push(handler);
6810
+ },
6811
+ async close() {
6812
+ watcher.close();
6813
+ }
6814
+ };
6815
+ }
6770
6816
  function createChokidarSource(root) {
6771
6817
  const watcher = chokidar.watch(root, {
6772
6818
  ignoreInitial: true,