@schoolai/shipyard 3.7.0 → 3.8.0-rc.20260529.0

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 (104) hide show
  1. package/dist/{auth-SS7LV5XK.js → auth-EXHO3AG5.js} +4 -4
  2. package/dist/capability-detector-worker.js +142 -0
  3. package/dist/capability-detector-worker.js.map +1 -0
  4. package/dist/{chunk-DKMDBOFU.js → chunk-2CNIEBKO.js} +21 -11
  5. package/dist/chunk-2CNIEBKO.js.map +1 -0
  6. package/dist/chunk-4T2OQAVL.js +51 -0
  7. package/dist/chunk-4T2OQAVL.js.map +1 -0
  8. package/dist/chunk-5ER6ZHA2.js +46 -0
  9. package/dist/chunk-5ER6ZHA2.js.map +1 -0
  10. package/dist/chunk-7LSEE26O.js +24227 -0
  11. package/dist/chunk-7LSEE26O.js.map +1 -0
  12. package/dist/{chunk-7AHRFPAL.js → chunk-7YOU7MBN.js} +183 -17
  13. package/dist/chunk-7YOU7MBN.js.map +1 -0
  14. package/dist/chunk-CMGJGK6R.js +382 -0
  15. package/dist/chunk-CMGJGK6R.js.map +1 -0
  16. package/dist/{chunk-VPMN47TL.js → chunk-CNR7O5YH.js} +1 -2
  17. package/dist/{chunk-2J3WSIAF.js → chunk-EF2DAODF.js} +18 -3
  18. package/dist/chunk-EF2DAODF.js.map +1 -0
  19. package/dist/chunk-HQ43PHOH.js +1203 -0
  20. package/dist/chunk-HQ43PHOH.js.map +1 -0
  21. package/dist/chunk-KITSAHTX.js +134 -0
  22. package/dist/chunk-KITSAHTX.js.map +1 -0
  23. package/dist/chunk-LESHN5J5.js +6898 -0
  24. package/dist/chunk-LESHN5J5.js.map +1 -0
  25. package/dist/{chunk-LW2MS4T5.js → chunk-LMJFHKRD.js} +15 -12
  26. package/dist/chunk-LMJFHKRD.js.map +1 -0
  27. package/dist/{chunk-SNYEQHUK.js → chunk-NACJENDW.js} +14 -21
  28. package/dist/chunk-NACJENDW.js.map +1 -0
  29. package/dist/{chunk-IISLTKYY.js → chunk-TU63KZFW.js} +2 -2
  30. package/dist/chunk-TX6DK4PK.js +186 -0
  31. package/dist/chunk-TX6DK4PK.js.map +1 -0
  32. package/dist/chunk-UQVXWOPT.js +48 -0
  33. package/dist/chunk-UQVXWOPT.js.map +1 -0
  34. package/dist/{chunk-3MNPDCO5.js → chunk-WBB4XHLH.js} +139 -140
  35. package/dist/chunk-WBB4XHLH.js.map +1 -0
  36. package/dist/chunk-X3MULCV5.js +11 -0
  37. package/dist/chunk-X3MULCV5.js.map +1 -0
  38. package/dist/chunk-YZ3Z3ZYI.js +787 -0
  39. package/dist/chunk-YZ3Z3ZYI.js.map +1 -0
  40. package/dist/{chunk-2UN5AR7V.js → chunk-ZAOPND5G.js} +2 -2
  41. package/dist/chunk-ZFKJAYAN.js +542 -0
  42. package/dist/chunk-ZFKJAYAN.js.map +1 -0
  43. package/dist/cursor-hook-shim.js +316 -0
  44. package/dist/cursor-hook-shim.js.map +1 -0
  45. package/dist/cursor-runner.js +358 -0
  46. package/dist/cursor-runner.js.map +1 -0
  47. package/dist/electron-utility.js +111 -0
  48. package/dist/electron-utility.js.map +1 -0
  49. package/dist/git-pool-V73Q53NX.js +18 -0
  50. package/dist/{git-repo-VRT57DGC.js → git-repo-TN3VZXQV.js} +9 -6
  51. package/dist/index.js +12 -12
  52. package/dist/index.js.map +1 -1
  53. package/dist/{logger-GQCSLSZH.js → logger-QHPTO22N.js} +4 -4
  54. package/dist/login-Q7SZI7JJ.js +20 -0
  55. package/dist/{logout-VUNCW5B2.js → logout-O4AVMO5S.js} +6 -6
  56. package/dist/mcp-servers-F64M5T4I.js +24 -0
  57. package/dist/{roi-Y3MX5UW4.js → roi-EYDLPOCS.js} +5 -5
  58. package/dist/rss-worker.js +159 -0
  59. package/dist/rss-worker.js.map +1 -0
  60. package/dist/{serve-O53FNK64.js → serve-6A7RJWEF.js} +89862 -102999
  61. package/dist/{serve-O53FNK64.js.map → serve-6A7RJWEF.js.map} +1 -1
  62. package/dist/skills-ZHEPSBHW.js +11 -0
  63. package/dist/{start-IDFDHRD6.js → start-YGYYIK53.js} +229 -27
  64. package/dist/start-YGYYIK53.js.map +1 -0
  65. package/dist/vault-crypto-BKDOA65F.js +13 -0
  66. package/dist/vault-crypto-BKDOA65F.js.map +1 -0
  67. package/dist/worker.js +6 -3
  68. package/dist/worker.js.map +1 -1
  69. package/package.json +17 -10
  70. package/dist/chunk-2J3WSIAF.js.map +0 -1
  71. package/dist/chunk-3MNPDCO5.js.map +0 -1
  72. package/dist/chunk-66OBOZ3X.js +0 -79
  73. package/dist/chunk-66OBOZ3X.js.map +0 -1
  74. package/dist/chunk-7AHRFPAL.js.map +0 -1
  75. package/dist/chunk-DKMDBOFU.js.map +0 -1
  76. package/dist/chunk-L2WQMPWS.js +0 -666
  77. package/dist/chunk-L2WQMPWS.js.map +0 -1
  78. package/dist/chunk-LW2MS4T5.js.map +0 -1
  79. package/dist/chunk-PI77CUEP.js +0 -49
  80. package/dist/chunk-PI77CUEP.js.map +0 -1
  81. package/dist/chunk-RXI4637N.js +0 -395
  82. package/dist/chunk-RXI4637N.js.map +0 -1
  83. package/dist/chunk-SNYEQHUK.js.map +0 -1
  84. package/dist/chunk-VBPHGPBR.js +0 -126
  85. package/dist/chunk-VBPHGPBR.js.map +0 -1
  86. package/dist/index.d.ts +0 -2
  87. package/dist/login-L4BBPUYO.js +0 -20
  88. package/dist/mcp-servers-MXS5VAWI.js +0 -18
  89. package/dist/shell-V36EX2IJ.js +0 -27
  90. package/dist/skills-GPGRNV4R.js +0 -9
  91. package/dist/start-IDFDHRD6.js.map +0 -1
  92. package/dist/worker.d.ts +0 -49
  93. /package/dist/{auth-SS7LV5XK.js.map → auth-EXHO3AG5.js.map} +0 -0
  94. /package/dist/{chunk-VPMN47TL.js.map → chunk-CNR7O5YH.js.map} +0 -0
  95. /package/dist/{chunk-IISLTKYY.js.map → chunk-TU63KZFW.js.map} +0 -0
  96. /package/dist/{chunk-2UN5AR7V.js.map → chunk-ZAOPND5G.js.map} +0 -0
  97. /package/dist/{git-repo-VRT57DGC.js.map → git-pool-V73Q53NX.js.map} +0 -0
  98. /package/dist/{logger-GQCSLSZH.js.map → git-repo-TN3VZXQV.js.map} +0 -0
  99. /package/dist/{login-L4BBPUYO.js.map → logger-QHPTO22N.js.map} +0 -0
  100. /package/dist/{mcp-servers-MXS5VAWI.js.map → login-Q7SZI7JJ.js.map} +0 -0
  101. /package/dist/{logout-VUNCW5B2.js.map → logout-O4AVMO5S.js.map} +0 -0
  102. /package/dist/{shell-V36EX2IJ.js.map → mcp-servers-F64M5T4I.js.map} +0 -0
  103. /package/dist/{roi-Y3MX5UW4.js.map → roi-EYDLPOCS.js.map} +0 -0
  104. /package/dist/{skills-GPGRNV4R.js.map → skills-ZHEPSBHW.js.map} +0 -0
@@ -1,9 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- assertNever,
4
- decodeLine,
5
- encodeLine
6
- } from "./chunk-SNYEQHUK.js";
3
+ WorkerCommandCodec,
4
+ WorkerReplyCodec
5
+ } from "./chunk-NACJENDW.js";
6
+ import {
7
+ createServiceSupervisor
8
+ } from "./chunk-ZFKJAYAN.js";
9
+ import {
10
+ assertNever
11
+ } from "./chunk-X3MULCV5.js";
7
12
 
8
13
  // src/services/metrics/metrics-collector.ts
9
14
  var NOOP_METRICS = {
@@ -73,6 +78,8 @@ function createMetricsCollector(workerUrl, authToken, telemetryEnabled) {
73
78
 
74
79
  // src/shared/file-watcher-guard.ts
75
80
  import { fork as childProcessFork } from "child_process";
81
+ import { existsSync } from "fs";
82
+ import { dirname } from "path";
76
83
 
77
84
  // src/services/watcher-worker/worker-supervisor.ts
78
85
  import { randomUUID } from "crypto";
@@ -81,34 +88,72 @@ var SHUTDOWN_GRACEFUL_MS = 2e3;
81
88
  var SHUTDOWN_SIGTERM_MS = 500;
82
89
  function createWatcherWorkerSupervisor(deps) {
83
90
  const subscriptions = /* @__PURE__ */ new Map();
84
- let child = null;
85
91
  let restartState = makeInitialAttemptState();
86
- let nextGeneration = 1;
92
+ let liveGeneration = 0;
93
+ let lastSpawnedAt = 0;
94
+ let lastPid = null;
87
95
  let shutdownInitiated = false;
88
96
  let restartTimer = null;
89
97
  let pendingRespawnGeneration = null;
98
+ let nextReplayStartedAt = null;
90
99
  function log(entry) {
91
100
  deps.log(entry);
92
101
  }
93
102
  function captureMetric(eventType, properties) {
94
103
  deps.metrics?.capture(eventType, properties);
95
104
  }
96
- function sendCommand(holder, cmd) {
97
- const stdin = holder.process.stdin;
98
- if (!stdin || stdin.destroyed || holder.exited) return false;
99
- try {
100
- stdin.write(`${encodeLine(cmd)}
101
- `);
102
- return true;
103
- } catch (err) {
105
+ const adaptedFork = (modulePath, args, options) => {
106
+ return deps.fork(modulePath, Array.from(args), options);
107
+ };
108
+ const supervisor = createServiceSupervisor({
109
+ fork: adaptedFork,
110
+ workerPath: deps.workerPath,
111
+ commandCodec: WorkerCommandCodec,
112
+ replyCodec: WorkerReplyCodec,
113
+ onReply: (reply, fromGeneration) => dispatchReply(reply, fromGeneration),
114
+ onChildSpawned: ({ generation, pid }) => {
115
+ liveGeneration = generation;
116
+ lastPid = pid;
117
+ lastSpawnedAt = deps.now();
118
+ log({ event: "watcher_worker_started", pid });
119
+ captureMetric("watcher_worker_started", { pid });
120
+ },
121
+ onChildExit: ({ code, signal, generation, uptimeMs }) => {
122
+ handleChildExit(generation, code, signal, uptimeMs);
123
+ },
124
+ onDecodeFailed: ({ line }) => log({ event: "watcher_worker_decode_failed", line }),
125
+ onStderrLine: (line) => {
126
+ if (!line.trim()) return;
127
+ log({ event: "watcher_worker_stderr", line });
128
+ },
129
+ onMissingStdout: () => log({ event: "watcher_worker_no_stdout" }),
130
+ onOverflow: ({ stream, bytes, maxBytes }) => log({ event: "watcher_worker_stdio_overflow", stream, bytes, maxBytes }),
131
+ onPeerError: (err) => log({ event: "watcher_worker_error", err: err.message }),
132
+ log,
133
+ now: deps.now
134
+ /** Watcher uses its own file-watcher-guard circuit; opt out of the primitive's. */
135
+ });
136
+ function sendCommand(cmd) {
137
+ const sent = supervisor.send(cmd);
138
+ if (!sent && supervisor.getCurrentProcess() !== null) {
104
139
  log({
105
140
  event: "watcher_worker_stdin_write_failed",
106
- err: err instanceof Error ? err.message : String(err)
141
+ err: "stdio peer send returned false"
107
142
  });
108
- return false;
109
143
  }
144
+ return sent;
110
145
  }
111
146
  function dispatchReply(reply, fromGeneration) {
147
+ if (fromGeneration !== liveGeneration) {
148
+ log({
149
+ event: "watcher_worker_stale_reply_dropped",
150
+ replyType: reply.type,
151
+ id: reply.id,
152
+ generation: fromGeneration,
153
+ liveGeneration
154
+ });
155
+ return;
156
+ }
112
157
  switch (reply.type) {
113
158
  case "subscribed":
114
159
  handleSubscribedReply(reply.id, fromGeneration);
@@ -165,68 +210,11 @@ function createWatcherWorkerSupervisor(deps) {
165
210
  if (!entry || entry.status === "unsubscribing") return;
166
211
  entry.callback(null, toCallbackEvents(events));
167
212
  }
168
- function attachChildIo(holder) {
169
- const proc = holder.process;
170
- const { stdout, stderr } = proc;
171
- if (!stdout) {
172
- log({ event: "watcher_worker_no_stdout" });
173
- return;
174
- }
175
- let stdoutBuffer = "";
176
- const fromGeneration = holder.generation;
177
- stdout.setEncoding("utf8");
178
- stdout.on("data", (chunk) => {
179
- stdoutBuffer += chunk;
180
- let nl = stdoutBuffer.indexOf("\n");
181
- while (nl !== -1) {
182
- const line = stdoutBuffer.slice(0, nl);
183
- stdoutBuffer = stdoutBuffer.slice(nl + 1);
184
- nl = stdoutBuffer.indexOf("\n");
185
- if (line.length === 0) continue;
186
- const decoded = decodeLine(line);
187
- if (decoded === null) {
188
- log({ event: "watcher_worker_decode_failed", line });
189
- continue;
190
- }
191
- if (!("type" in decoded)) {
192
- log({ event: "watcher_worker_unexpected_command", cmd: decoded.cmd });
193
- continue;
194
- }
195
- dispatchReply(decoded, fromGeneration);
196
- }
197
- });
198
- if (stderr) {
199
- stderr.setEncoding("utf8");
200
- let stderrBuffer = "";
201
- stderr.on("data", (chunk) => {
202
- stderrBuffer += chunk;
203
- let nl = stderrBuffer.indexOf("\n");
204
- while (nl !== -1) {
205
- const line = stderrBuffer.slice(0, nl);
206
- stderrBuffer = stderrBuffer.slice(nl + 1);
207
- nl = stderrBuffer.indexOf("\n");
208
- if (line.length > 0) {
209
- log({ event: "watcher_worker_stderr", line });
210
- }
211
- }
212
- });
213
- }
214
- proc.on("exit", (code, signal) => {
215
- handleChildExit(holder, code, signal);
216
- });
217
- proc.on("error", (err) => {
218
- log({ event: "watcher_worker_error", err: err.message });
219
- });
220
- }
221
- function handleChildExit(holder, code, signal) {
222
- holder.exited = true;
223
- if (child !== holder) return;
224
- child = null;
225
- if (pendingRespawnGeneration === holder.generation) {
213
+ function handleChildExit(generation, code, signal, uptimeMs) {
214
+ if (pendingRespawnGeneration === generation) {
226
215
  pendingRespawnGeneration = null;
227
216
  }
228
217
  const replayCount = subscriptions.size;
229
- const uptimeMs = deps.now() - holder.spawnedAt;
230
218
  if (shutdownInitiated) {
231
219
  log({ event: "watcher_worker_exited_during_shutdown", code, signal, uptimeMs });
232
220
  return;
@@ -243,11 +231,11 @@ function createWatcherWorkerSupervisor(deps) {
243
231
  replayCount,
244
232
  uptimeMs
245
233
  });
246
- recordRestartFailure(holder);
234
+ recordRestartFailure(uptimeMs);
247
235
  fireSyntheticEvictionToAll();
248
236
  scheduleRespawn();
249
237
  }
250
- function recordRestartFailure(holder) {
238
+ function recordRestartFailure(uptimeMs) {
251
239
  const failureDecision = decideAction(restartState, { kind: "subscribe_failure" }, deps.now());
252
240
  restartState = failureDecision.state;
253
241
  for (const sig of failureDecision.signals) {
@@ -255,7 +243,7 @@ function createWatcherWorkerSupervisor(deps) {
255
243
  log({ event: "watcher_worker_circuit_open" });
256
244
  captureMetric("watcher_worker_circuit_open", {
257
245
  deathCount: restartState.failureCount,
258
- windowMs: deps.now() - holder.spawnedAt
246
+ windowMs: uptimeMs
259
247
  });
260
248
  } else if (sig.kind === "circuit_closed") {
261
249
  log({ event: "watcher_worker_circuit_closed" });
@@ -342,45 +330,37 @@ function createWatcherWorkerSupervisor(deps) {
342
330
  }
343
331
  }
344
332
  function forkAndReplay() {
345
- const isRespawn = nextGeneration > 1;
346
- const replayStart = deps.now();
347
- const holder = spawnChildHolder();
348
- if (isRespawn && subscriptions.size > 0) {
349
- pendingRespawnGeneration = holder.generation;
333
+ const isRespawn = liveGeneration >= 1;
334
+ nextReplayStartedAt = deps.now();
335
+ const shouldMarkPendingRespawn = isRespawn && subscriptions.size > 0;
336
+ if (liveGeneration === 0) {
337
+ supervisor.start();
338
+ } else {
339
+ supervisor.restart();
350
340
  }
351
- const replayResult = replaySubscriptions(holder);
341
+ if (shouldMarkPendingRespawn) {
342
+ pendingRespawnGeneration = liveGeneration;
343
+ }
344
+ const replayResult = replaySubscriptions();
352
345
  if (replayResult.kind === "pipe_failed") {
353
- handleReplayPipeFailure(holder, replayResult.replayedCount);
346
+ handleReplayPipeFailure(replayResult.replayedCount);
354
347
  return;
355
348
  }
356
349
  if (replayResult.replayedCount > 0) {
357
350
  log({ event: "watcher_worker_replayed", replayCount: replayResult.replayedCount });
358
351
  }
359
352
  if (isRespawn) {
360
- recordRespawnTelemetry(holder, replayResult.replayedCount, deps.now() - replayStart);
353
+ recordRespawnTelemetry(
354
+ replayResult.replayedCount,
355
+ deps.now() - (nextReplayStartedAt ?? deps.now())
356
+ );
361
357
  }
362
358
  }
363
- function spawnChildHolder() {
364
- const proc = deps.fork(deps.workerPath, [], {
365
- stdio: ["pipe", "pipe", "pipe", "ipc"]
366
- });
367
- const holder = {
368
- process: proc,
369
- spawnedAt: deps.now(),
370
- generation: nextGeneration++,
371
- exited: false
372
- };
373
- child = holder;
374
- log({ event: "watcher_worker_started", pid: proc.pid ?? null });
375
- captureMetric("watcher_worker_started", { pid: proc.pid ?? null });
376
- attachChildIo(holder);
377
- return holder;
378
- }
379
- function replaySubscriptions(holder) {
359
+ function replaySubscriptions() {
380
360
  let replayedCount = 0;
381
361
  for (const entry of subscriptions.values()) {
382
362
  entry.status = "pending";
383
- const ok = sendCommand(holder, {
363
+ const ok = sendCommand({
384
364
  cmd: "subscribe",
385
365
  id: entry.id,
386
366
  path: entry.path,
@@ -393,17 +373,18 @@ function createWatcherWorkerSupervisor(deps) {
393
373
  }
394
374
  return { kind: "completed", replayedCount };
395
375
  }
396
- function handleReplayPipeFailure(holder, replayedCount) {
376
+ function handleReplayPipeFailure(replayedCount) {
397
377
  log({
398
378
  event: "watcher_worker_replay_pipe_failed",
399
- pid: holder.process.pid ?? null,
379
+ pid: lastPid,
400
380
  replayedCount,
401
381
  pendingCount: subscriptions.size - replayedCount
402
382
  });
403
- recordRestartFailure(holder);
404
- if (!holder.exited) {
383
+ recordRestartFailure(deps.now() - lastSpawnedAt);
384
+ const proc = supervisor.getCurrentProcess();
385
+ if (proc !== null) {
405
386
  try {
406
- holder.process.kill("SIGKILL");
387
+ proc.kill("SIGKILL");
407
388
  } catch (err) {
408
389
  log({
409
390
  event: "watcher_worker_kill_failed",
@@ -414,15 +395,15 @@ function createWatcherWorkerSupervisor(deps) {
414
395
  }
415
396
  scheduleRespawn();
416
397
  }
417
- function recordRespawnTelemetry(holder, replayCount, replayDurationMs) {
398
+ function recordRespawnTelemetry(replayCount, replayDurationMs) {
418
399
  log({
419
400
  event: "watcher_worker_respawned",
420
- pid: holder.process.pid ?? null,
401
+ pid: lastPid,
421
402
  replayCount,
422
403
  replayDurationMs
423
404
  });
424
405
  captureMetric("watcher_worker_respawned", {
425
- newPid: holder.process.pid ?? null,
406
+ newPid: lastPid,
426
407
  replayCount,
427
408
  replayDurationMs
428
409
  });
@@ -435,13 +416,13 @@ function createWatcherWorkerSupervisor(deps) {
435
416
  function unsubscribeEntry(entry) {
436
417
  if (!subscriptions.has(entry.id)) return Promise.resolve();
437
418
  entry.status = "unsubscribing";
438
- if (!child) {
419
+ if (supervisor.getCurrentProcess() === null) {
439
420
  subscriptions.delete(entry.id);
440
421
  return Promise.resolve();
441
422
  }
442
423
  return new Promise((resolve) => {
443
424
  entry.resolveUnsubscribed = resolve;
444
- const sent = child !== null && sendCommand(child, { cmd: "unsubscribe", id: entry.id });
425
+ const sent = sendCommand({ cmd: "unsubscribe", id: entry.id });
445
426
  if (!sent) {
446
427
  subscriptions.delete(entry.id);
447
428
  resolve();
@@ -453,7 +434,7 @@ function createWatcherWorkerSupervisor(deps) {
453
434
  } };
454
435
  }
455
436
  async function start() {
456
- if (child !== null) return;
437
+ if (supervisor.getCurrentProcess() !== null) return;
457
438
  if (shutdownInitiated) {
458
439
  throw new Error("WatcherWorkerSupervisor: cannot start after shutdown");
459
440
  }
@@ -483,10 +464,10 @@ function createWatcherWorkerSupervisor(deps) {
483
464
  entry.rejectSubscribed = reject;
484
465
  });
485
466
  subscriptions.set(id, entry);
486
- if (child === null) {
467
+ if (supervisor.getCurrentProcess() === null) {
487
468
  await start();
488
469
  } else {
489
- sendCommand(child, { cmd: "subscribe", id, path, opts });
470
+ sendCommand({ cmd: "subscribe", id, path, opts });
490
471
  }
491
472
  return promise;
492
473
  }
@@ -505,17 +486,18 @@ function createWatcherWorkerSupervisor(deps) {
505
486
  entry.resolveUnsubscribed = void 0;
506
487
  }
507
488
  subscriptions.clear();
508
- const holder = child;
509
- if (holder === null) return;
510
- sendCommand(holder, { cmd: "shutdown" });
511
- await escalateShutdown(holder);
489
+ const proc = supervisor.getCurrentProcess();
490
+ supervisor.dispose();
491
+ if (proc === null) return;
492
+ sendCommand({ cmd: "shutdown" });
493
+ await escalateShutdown(proc);
512
494
  }
513
- function killWithSignal(holder, signal) {
495
+ function killWithSignal(proc, signal) {
514
496
  log({
515
497
  event: signal === "SIGTERM" ? "watcher_worker_shutdown_sigterm" : "watcher_worker_shutdown_sigkill"
516
498
  });
517
499
  try {
518
- holder.process.kill(signal);
500
+ proc.kill(signal);
519
501
  } catch (err) {
520
502
  log({
521
503
  event: "watcher_worker_kill_failed",
@@ -524,30 +506,29 @@ function createWatcherWorkerSupervisor(deps) {
524
506
  });
525
507
  }
526
508
  }
527
- function escalateShutdown(holder) {
509
+ function escalateShutdown(proc) {
528
510
  return new Promise((resolve) => {
529
- const ctx = { done: false };
511
+ const ctx = { done: false, exited: false };
530
512
  const finish = () => {
531
513
  if (ctx.done) return;
532
514
  ctx.done = true;
533
515
  resolve();
534
516
  };
535
- holder.process.once("exit", finish);
536
- if (holder.exited) {
517
+ proc.once("exit", () => {
518
+ ctx.exited = true;
537
519
  finish();
538
- return;
539
- }
540
- deps.setTimeout(() => onSigtermDeadline(holder, ctx, finish), SHUTDOWN_GRACEFUL_MS);
520
+ });
521
+ deps.setTimeout(() => onSigtermDeadline(proc, ctx, finish), SHUTDOWN_GRACEFUL_MS);
541
522
  });
542
523
  }
543
- function onSigtermDeadline(holder, ctx, finish) {
544
- if (ctx.done || holder.exited) return;
545
- killWithSignal(holder, "SIGTERM");
546
- deps.setTimeout(() => onSigkillDeadline(holder, ctx, finish), SHUTDOWN_SIGTERM_MS);
524
+ function onSigtermDeadline(proc, ctx, finish) {
525
+ if (ctx.done || ctx.exited) return;
526
+ killWithSignal(proc, "SIGTERM");
527
+ deps.setTimeout(() => onSigkillDeadline(proc, ctx, finish), SHUTDOWN_SIGTERM_MS);
547
528
  }
548
- function onSigkillDeadline(holder, ctx, finish) {
549
- if (ctx.done || holder.exited) return;
550
- killWithSignal(holder, "SIGKILL");
529
+ function onSigkillDeadline(proc, ctx, finish) {
530
+ if (ctx.done || ctx.exited) return;
531
+ killWithSignal(proc, "SIGKILL");
551
532
  finish();
552
533
  }
553
534
  return { start, subscribe, shutdown };
@@ -777,7 +758,9 @@ function toGuardedEvent(e) {
777
758
  }
778
759
  function ensureSupervisor() {
779
760
  if (moduleState.supervisor) return moduleState.supervisor;
780
- const workerPath = new URL("./worker.js", import.meta.url).pathname;
761
+ const selfUrl = import.meta.url;
762
+ const isDevMode = selfUrl.endsWith(".ts");
763
+ const workerPath = isDevMode ? new URL("../services/watcher-worker/worker.ts", selfUrl).pathname : new URL("./worker.js", selfUrl).pathname;
781
764
  moduleState.supervisor = createWatcherWorkerSupervisor({
782
765
  fork: nodeFork,
783
766
  workerPath,
@@ -894,10 +877,19 @@ async function performSubscribe(path, consumerCallback, opts, tier) {
894
877
  const priorState = moduleState.perPath.get(path) ?? makeInitialAttemptState();
895
878
  const failureDecision = decideAction(priorState, { kind: "subscribe_failure" }, now);
896
879
  moduleState.perPath.set(path, failureDecision.state);
880
+ const parentExists = pathExistsForLog(dirname(path));
897
881
  deps.log({
898
882
  event: "file_watcher_subscribe_failed",
899
883
  path,
900
- err: err instanceof Error ? err.message : String(err)
884
+ pathExists: pathExistsForLog(path),
885
+ parentExists,
886
+ err: err instanceof Error ? err.message : String(err),
887
+ /**
888
+ * The expected-ENOENT fallback path (file doesn't exist yet but
889
+ * parent does) is a normal poll cycle, not a failure. Downgrade
890
+ * the log level so log triage doesn't flag 40+ of these per task.
891
+ */
892
+ ...parentExists ? { level: "debug" } : {}
901
893
  });
902
894
  emitSignals(path, failureDecision.signals);
903
895
  if (failureDecision.state.circuitOpenedAt !== null) {
@@ -906,6 +898,13 @@ async function performSubscribe(path, consumerCallback, opts, tier) {
906
898
  throw err;
907
899
  }
908
900
  }
901
+ function pathExistsForLog(path) {
902
+ try {
903
+ return existsSync(path);
904
+ } catch {
905
+ return false;
906
+ }
907
+ }
909
908
  function pickOldest(entries, tier) {
910
909
  let target = null;
911
910
  for (const entry of entries) {
@@ -1008,4 +1007,4 @@ export {
1008
1007
  shutdownFileWatcherGuard,
1009
1008
  guardedSubscribe
1010
1009
  };
1011
- //# sourceMappingURL=chunk-3MNPDCO5.js.map
1010
+ //# sourceMappingURL=chunk-WBB4XHLH.js.map