@orkestrel/probe 0.0.11 → 0.0.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.
@@ -38,6 +38,64 @@ function normalizePath(path) {
38
38
  return path.replaceAll("\\", "/");
39
39
  }
40
40
  /**
41
+ * Reads the condition code a native fault carries.
42
+ *
43
+ * @remarks
44
+ * A caller catches `unknown`, so every reading of a caught value's own property calls into code
45
+ * this package does not own: a proxy whose `has` trap throws and a value whose `code` getter throws
46
+ * both arrive here. The read is guarded, so a fault that refuses inspection reports no code rather
47
+ * than raising a second fault over the first. A `code` the host reports as anything other than a
48
+ * string is no code this package compares against, so it reports none either.
49
+ *
50
+ * One reading serves every site that classifies a native fault, so a host condition is admitted the
51
+ * same way wherever it is read.
52
+ *
53
+ * @param error - The caught value to read
54
+ * @returns The fault's `code` when it carries a string one; `undefined` otherwise
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * readFaultCode(Object.assign(new Error('no such file'), { code: 'ENOENT' })) // 'ENOENT'
59
+ * readFaultCode(new Error('the runtime stage was destroyed')) // undefined
60
+ * readFaultCode('ENOENT') // undefined
61
+ * ```
62
+ */
63
+ function readFaultCode(error) {
64
+ if (typeof error !== "object" || error === null) return void 0;
65
+ const fault = error;
66
+ const reading = (0, _orkestrel_contract.attempt)(() => "code" in fault ? fault.code : void 0);
67
+ if (!reading.success) return void 0;
68
+ return typeof reading.value === "string" ? reading.value : void 0;
69
+ }
70
+ /**
71
+ * Reports whether one path resolves outside the root it is read against.
72
+ *
73
+ * @remarks
74
+ * Containment decides which paths a claim may reach and which absolute paths a digest may rewrite,
75
+ * so one reading serves every site that asks the question. A target resolving to the root itself is
76
+ * contained, and each caller decides on its own what that empty relative path means for it.
77
+ *
78
+ * The test reads the relative path rather than a string prefix of the root, so a sibling directory
79
+ * whose name begins with the root's own text is outside rather than beneath it. An absolute
80
+ * relative path is the answer a host returns for two paths on different volumes, which no root
81
+ * contains.
82
+ *
83
+ * @param root - The root the target is read against
84
+ * @param target - The path to test, absolute or root-relative
85
+ * @returns True if the target resolves outside the root; false otherwise
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * escapesRoot('/srv/checkout', 'src/core/greeting.ts') // false
90
+ * escapesRoot('/srv/checkout', '../secrets.env') // true
91
+ * escapesRoot('/srv/checkout', '/srv/checkout-backup/secrets.env') // true
92
+ * ```
93
+ */
94
+ function escapesRoot(root, target) {
95
+ const path = (0, node_path.relative)((0, node_path.resolve)(root), (0, node_path.resolve)(root, target));
96
+ return path === ".." || path.startsWith(`..${node_path.sep}`) || (0, node_path.isAbsolute)(path);
97
+ }
98
+ /**
41
99
  * Resolves a path inside a target workspace and rejects traversal outside it.
42
100
  *
43
101
  * @remarks
@@ -65,7 +123,7 @@ function resolveWorkspaceFile(workspace, target, mutate = false) {
65
123
  const root = (0, node_path.resolve)(workspace);
66
124
  const file = (0, node_path.resolve)(root, target);
67
125
  const path = (0, node_path.relative)(root, file);
68
- if (path === "" || path === ".." || path.startsWith(`..${node_path.sep}`) || (0, node_path.isAbsolute)(path)) throw new _src_core.ProbeError(`Path escapes the workspace: ${target}`, {
126
+ if (path === "" || escapesRoot(root, file)) throw new _src_core.ProbeError(`Path escapes the workspace: ${target}`, {
69
127
  origin: "claimant",
70
128
  code: "refused",
71
129
  context: { path: target }
@@ -78,18 +136,16 @@ function resolveWorkspaceFile(workspace, target, mutate = false) {
78
136
  descendant = (0, node_path.resolve)(descendant, segment);
79
137
  const outcome = (0, _orkestrel_contract.attempt)(() => (0, node_fs.lstatSync)(descendant));
80
138
  if (!outcome.success) {
81
- const error = outcome.error;
82
- if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR")) break;
83
- throw error;
139
+ const code = readFaultCode(outcome.error);
140
+ if (code === "ENOENT" || code === "ENOTDIR") break;
141
+ throw outcome.error;
84
142
  }
85
143
  if (outcome.value.isSymbolicLink()) throw new _src_core.ProbeError(`Path crosses a symbolic link: ${target}`, {
86
144
  origin: "workspace",
87
145
  code: "refused",
88
146
  context: { path: target }
89
147
  });
90
- const resolved = (0, node_fs.realpathSync)(descendant);
91
- const remainder = (0, node_path.relative)(canonical, resolved);
92
- if (remainder === ".." || remainder.startsWith(`..${node_path.sep}`) || (0, node_path.isAbsolute)(remainder)) throw new _src_core.ProbeError(`Path escapes the workspace: ${target}`, {
148
+ if (escapesRoot(canonical, (0, node_fs.realpathSync)(descendant))) throw new _src_core.ProbeError(`Path escapes the workspace: ${target}`, {
93
149
  origin: "claimant",
94
150
  code: "refused",
95
151
  context: { path: target }
@@ -97,7 +153,8 @@ function resolveWorkspaceFile(workspace, target, mutate = false) {
97
153
  }
98
154
  } catch (error) {
99
155
  if (error instanceof _src_core.ProbeError) throw error;
100
- const claimant = typeof error === "object" && error !== null && "code" in error && (error.code === "ENAMETOOLONG" || error.code === "ERR_INVALID_ARG_VALUE");
156
+ const code = readFaultCode(error);
157
+ const claimant = code === "ENAMETOOLONG" || code === "ERR_INVALID_ARG_VALUE";
101
158
  throw new _src_core.ProbeError(`The workspace path cannot be inspected: ${target}`, {
102
159
  origin: claimant ? "claimant" : "workspace",
103
160
  code: claimant ? "refused" : "malformed",
@@ -177,7 +234,7 @@ function overwriteFile(file, text) {
177
234
  *
178
235
  * @param file - The path whose creation failed
179
236
  * @param error - The fault the failed operation raised
180
- * @returns True when the fault means the host refuses this name; false otherwise
237
+ * @returns True if the fault means the host refuses this name; false otherwise
181
238
  *
182
239
  * @example
183
240
  * ```ts
@@ -190,11 +247,7 @@ function overwriteFile(file, text) {
190
247
  * ```
191
248
  */
192
249
  function isRefusedName(file, error) {
193
- if (typeof error !== "object" || error === null) return false;
194
- const fault = error;
195
- const reading = (0, _orkestrel_contract.attempt)(() => "code" in fault ? fault.code : void 0);
196
- if (!reading.success) return false;
197
- const code = reading.value;
250
+ const code = readFaultCode(error);
198
251
  if (code === "ENAMETOOLONG") return true;
199
252
  if (code === "ERR_INVALID_ARG_VALUE") return file.includes("\0");
200
253
  if (code !== "ENOENT") return false;
@@ -289,7 +342,7 @@ function resolveWorkspaceModule(workspace, specifier) {
289
342
  const outcome = (0, _orkestrel_contract.attempt)(() => (0, node_module.createRequire)((0, node_path.resolve)(workspace, "package.json")).resolve(specifier));
290
343
  if (outcome.success) return outcome.value;
291
344
  const error = outcome.error;
292
- const missing = typeof error === "object" && error !== null && "code" in error && error.code === "MODULE_NOT_FOUND";
345
+ const missing = readFaultCode(error) === "MODULE_NOT_FOUND";
293
346
  throw new _src_core.ProbeError(`The workspace cannot resolve ${specifier}`, {
294
347
  origin: "workspace",
295
348
  code: missing ? "missing" : "malformed",
@@ -304,7 +357,7 @@ function loadWorkspaceModule(workspace, specifier) {
304
357
  });
305
358
  if (outcome.success) return outcome.value;
306
359
  const error = outcome.error;
307
- const missing = typeof error === "object" && error !== null && "code" in error && error.code === "MODULE_NOT_FOUND";
360
+ const missing = readFaultCode(error) === "MODULE_NOT_FOUND";
308
361
  throw new _src_core.ProbeError(`The workspace cannot load ${specifier}`, {
309
362
  origin: "workspace",
310
363
  code: missing ? "missing" : "malformed",
@@ -342,7 +395,8 @@ function readWorkspaceManifest(workspace, name) {
342
395
  const reading = (0, _orkestrel_contract.attempt)(() => (0, node_fs.readFileSync)(path, "utf8"));
343
396
  if (!reading.success) {
344
397
  const error = reading.error;
345
- const missing = typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
398
+ const code = readFaultCode(error);
399
+ const missing = code === "ENOENT" || code === "ENOTDIR";
346
400
  throw new _src_core.ProbeError(`${name} does not publish a readable manifest`, {
347
401
  origin: "workspace",
348
402
  code: missing ? "missing" : "malformed",
@@ -486,23 +540,24 @@ function inferDocumentLanguage(path) {
486
540
  return "typescript";
487
541
  }
488
542
  /**
489
- * Creates a fresh sibling identity while preserving a test's resolution directory.
543
+ * Builds the fresh sibling path a revision's file is written at, preserving the test's resolution
544
+ * directory.
490
545
  *
491
546
  * @param workspace - The target workspace root
492
547
  * @param path - The workspace-relative test path
493
548
  * @param revision - The fresh revision identity
494
- * @returns An absolute sibling file path
549
+ * @returns The absolute sibling path
495
550
  *
496
551
  * @example
497
552
  * ```ts
498
553
  * relativeWorkspaceFile(
499
554
  * '/srv/checkout',
500
- * createRevisionFile('/srv/checkout', 'tmp/probe/greeting.test.ts', '4821-9f0c'),
555
+ * buildRevisionPath('/srv/checkout', 'tmp/probe/greeting.test.ts', '4821-9f0c'),
501
556
  * )
502
557
  * // 'tmp/probe/greeting.test.probe-4821-9f0c.ts'
503
558
  * ```
504
559
  */
505
- function createRevisionFile(workspace, path, revision) {
560
+ function buildRevisionPath(workspace, path, revision) {
506
561
  const file = resolveWorkspaceFile(workspace, path);
507
562
  const extension = (0, node_path.extname)(file);
508
563
  return `${extension === "" ? file : file.slice(0, -extension.length)}.probe-${revision}${extension}`;
@@ -511,7 +566,7 @@ function createRevisionFile(workspace, path, revision) {
511
566
  * Reports whether a path is a workspace module Vitest can cache.
512
567
  *
513
568
  * @param path - The candidate file path
514
- * @returns True for script, TypeScript, Vue, and JSON modules; false otherwise
569
+ * @returns True if the path is a script, TypeScript, Vue, or JSON module; false otherwise
515
570
  *
516
571
  * @example
517
572
  * ```ts
@@ -638,7 +693,7 @@ function normalizeValue(workspace, value) {
638
693
  if (!(0, node_path.isAbsolute)(value)) return value;
639
694
  const path = (0, node_path.relative)(root, (0, node_path.resolve)(value));
640
695
  if (path === "") return ".";
641
- if (path === ".." || path.startsWith(`..${node_path.sep}`) || (0, node_path.isAbsolute)(path)) return value;
696
+ if (escapesRoot(root, value)) return value;
642
697
  return normalizePath(path);
643
698
  }
644
699
  if ((0, _orkestrel_contract.isArray)(value)) return value.map((entry) => normalizeValue(workspace, entry));
@@ -824,11 +879,11 @@ var Overlay = class {
824
879
  };
825
880
  //#endregion
826
881
  //#region package.json
827
- var version = "0.0.11";
882
+ var version = "0.0.12";
828
883
  var peerDependencies = {
829
- "oxlint": "^1.77.0",
830
- "typescript": "^6.0.0",
831
- "vitest": "^4.1.0"
884
+ "oxlint": "^1.80.0",
885
+ "typescript": "^6.0.3",
886
+ "vitest": "^4.1.11"
832
887
  };
833
888
  //#endregion
834
889
  //#region src/server/stages/LintStage.ts
@@ -878,7 +933,6 @@ var LintStage = class {
878
933
  #closing;
879
934
  #progress = 0;
880
935
  #revision = 0;
881
- #destroyed = false;
882
936
  /**
883
937
  * Starts warming the target workspace's Oxlint language server.
884
938
  *
@@ -900,12 +954,11 @@ var LintStage = class {
900
954
  }
901
955
  destroy() {
902
956
  if (this.#closing !== void 0) return this.#closing;
903
- this.#destroyed = true;
904
957
  this.#closing = guardStage(this.stage, this.#destroy());
905
958
  return this.#closing;
906
959
  }
907
960
  async #inspect(subject, options) {
908
- if (this.#destroyed) throw (0, _src_core.createDestroyedError)("lint stage");
961
+ if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("lint stage");
909
962
  if (options === void 0) throw new _src_core.ProbeError("The lint stage inspects only under a bound its caller supplies", {
910
963
  origin: "claimant",
911
964
  code: "refused",
@@ -913,7 +966,7 @@ var LintStage = class {
913
966
  });
914
967
  const started = performance.now();
915
968
  const client = await this.#warmed();
916
- if (this.#destroyed) throw (0, _src_core.createDestroyedError)("lint stage");
969
+ if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("lint stage");
917
970
  const issues = [];
918
971
  for (const draft of [...subject.files, subject.test]) issues.push(...await this.#document(client, draft, options.signal));
919
972
  return {
@@ -998,7 +1051,7 @@ var LintStage = class {
998
1051
  });
999
1052
  }
1000
1053
  #translate(error, path) {
1001
- if (this.#destroyed) return (0, _src_core.createDestroyedError)("lint stage");
1054
+ if (this.#closing !== void 0) return (0, _src_core.createDestroyedError)("lint stage");
1002
1055
  const ending = this.#ending;
1003
1056
  if (ending !== void 0) return this.#fault(`The Oxlint language server exited with ${ending}`, error, path);
1004
1057
  if (error instanceof Error) return error;
@@ -1053,6 +1106,11 @@ var LintStage = class {
1053
1106
  * The runtime overlay leaves bare specifier resolution to Vite: it replaces a bare import only
1054
1107
  * after Vite resolves that import to a covered file. The type stage overlays the declared test
1055
1108
  * path, while this stage executes a generated sibling and overlays only the candidate files.
1109
+ * This stage mints its overlay with the default exact-match sensitivity, because it declares no
1110
+ * file-name case sensitivity to Vite. A covered path whose spelling an importer wrote differs from
1111
+ * the recorded candidate path is therefore served by whatever answers first, and `#misses` reports
1112
+ * it as `The workspace configuration served this module before the runtime overlay` with origin
1113
+ * `workspace` rather than leaving it answered silently.
1056
1114
  *
1057
1115
  * Vite retains one unresolved URL for every specification path, so the stage replaces its whole
1058
1116
  * Vitest service after 64 specifications rather than deleting from each map that service owns. Any
@@ -1101,7 +1159,6 @@ var RuntimeStage = class {
1101
1159
  #specifications = 0;
1102
1160
  #closing;
1103
1161
  #progress = 0;
1104
- #destroyed = false;
1105
1162
  /**
1106
1163
  * Starts warming the target workspace's Vitest service.
1107
1164
  *
@@ -1123,16 +1180,15 @@ var RuntimeStage = class {
1123
1180
  }
1124
1181
  destroy() {
1125
1182
  if (this.#closing !== void 0) return this.#closing;
1126
- this.#destroyed = true;
1127
1183
  this.#closing = guardStage(this.stage, this.#destroy());
1128
1184
  return this.#closing;
1129
1185
  }
1130
1186
  async #inspect(subject) {
1131
- if (this.#destroyed) throw (0, _src_core.createDestroyedError)("runtime stage");
1187
+ if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("runtime stage");
1132
1188
  const started = performance.now();
1133
1189
  const exitCode = process.exitCode;
1134
1190
  const vitest = await this.#runner();
1135
- if (this.#destroyed) throw (0, _src_core.createDestroyedError)("runtime stage");
1191
+ if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("runtime stage");
1136
1192
  const project = this.#project(vitest, subject.test.path);
1137
1193
  if ("message" in project) return {
1138
1194
  stage: this.stage,
@@ -1274,7 +1330,7 @@ var RuntimeStage = class {
1274
1330
  return {
1275
1331
  ...config,
1276
1332
  plugins: [...config.plugins ?? [], {
1277
- name: "orkestrel-runtime-overlay",
1333
+ name: _src_core.RUNTIME_PLUGIN,
1278
1334
  enforce: "pre",
1279
1335
  resolveId: this.#resolve.bind(this),
1280
1336
  load: this.#load.bind(this)
@@ -1316,7 +1372,7 @@ var RuntimeStage = class {
1316
1372
  let generated;
1317
1373
  const outcome = (0, _orkestrel_contract.attempt)(() => {
1318
1374
  const revision = `${process.pid}-${(0, node_crypto.randomUUID)()}`;
1319
- const file = createRevisionFile(this.#workspace, test.path, revision);
1375
+ const file = buildRevisionPath(this.#workspace, test.path, revision);
1320
1376
  generated = file;
1321
1377
  const target = (0, node_path.relative)(this.#workspace, file);
1322
1378
  resolveWorkspaceFile(this.#workspace, target, true);
@@ -1374,7 +1430,7 @@ var RuntimeStage = class {
1374
1430
  path
1375
1431
  }
1376
1432
  });
1377
- if (!project.vite.config.plugins.some((plugin) => plugin.name === "orkestrel-runtime-overlay")) return {
1433
+ if (!project.vite.config.plugins.some((plugin) => plugin.name === _src_core.RUNTIME_PLUGIN)) return {
1378
1434
  origin: "workspace",
1379
1435
  path,
1380
1436
  message: `The runtime stage cannot instrument the string-declared Vitest project ${name} because its configuration carries no runtime overlay plugin`
@@ -1463,14 +1519,14 @@ var RuntimeStage = class {
1463
1519
  }
1464
1520
  #runner() {
1465
1521
  const current = this.#vitest;
1466
- if (current !== void 0 && this.#specifications < 64) return current;
1522
+ if (current !== void 0 && this.#specifications < _src_core.PROBE_SPECIFICATIONS) return current;
1467
1523
  if (current !== void 0) return this.#store(this.#replace(current));
1468
1524
  const runner = loadWorkspaceModule(this.#workspace, "vitest/node");
1469
- return this.#store(this.#specifications < 64 ? this.#warm(runner.createVitest) : this.#replace(void 0, runner.createVitest));
1525
+ return this.#store(this.#specifications < _src_core.PROBE_SPECIFICATIONS ? this.#warm(runner.createVitest) : this.#replace(void 0, runner.createVitest));
1470
1526
  }
1471
1527
  async #replace(current, create) {
1472
1528
  if (current !== void 0) await (await current).close();
1473
- if (this.#destroyed) throw (0, _src_core.createDestroyedError)("runtime stage");
1529
+ if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("runtime stage");
1474
1530
  const runner = create ?? loadWorkspaceModule(this.#workspace, "vitest/node").createVitest;
1475
1531
  const replacement = await this.#warm(runner);
1476
1532
  this.#specifications = 0;
@@ -1548,7 +1604,7 @@ var RuntimeStage = class {
1548
1604
  process.kill(id, 0);
1549
1605
  return true;
1550
1606
  } catch (error) {
1551
- return error instanceof Error && "code" in error && error.code === "EPERM";
1607
+ return readFaultCode(error) === "EPERM";
1552
1608
  }
1553
1609
  }
1554
1610
  *#walk() {
@@ -1721,7 +1777,6 @@ var TypeStage = class {
1721
1777
  #recycled;
1722
1778
  #closing;
1723
1779
  #progress = 0;
1724
- #destroyed = false;
1725
1780
  /**
1726
1781
  * Starts warming the target workspace's TypeScript service.
1727
1782
  *
@@ -1775,15 +1830,14 @@ var TypeStage = class {
1775
1830
  }
1776
1831
  destroy() {
1777
1832
  if (this.#closing !== void 0) return this.#closing;
1778
- this.#destroyed = true;
1779
1833
  this.#closing = guardStage(this.stage, this.#destroy());
1780
1834
  return this.#closing;
1781
1835
  }
1782
1836
  async #inspect(subject, project) {
1783
- if (this.#destroyed) throw (0, _src_core.createDestroyedError)("type stage");
1837
+ if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("type stage");
1784
1838
  const started = performance.now();
1785
1839
  const typescript = await this.#typescript;
1786
- if (this.#destroyed) throw (0, _src_core.createDestroyedError)("type stage");
1840
+ if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("type stage");
1787
1841
  const selections = subject.files.map((draft) => ({
1788
1842
  draft,
1789
1843
  path: resolveWorkspaceFile(this.#workspace, draft.path)
@@ -1827,9 +1881,9 @@ var TypeStage = class {
1827
1881
  }
1828
1882
  }
1829
1883
  async #resolve(project) {
1830
- if (this.#destroyed) throw (0, _src_core.createDestroyedError)("type stage");
1884
+ if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("type stage");
1831
1885
  const typescript = await this.#typescript;
1832
- if (this.#destroyed) throw (0, _src_core.createDestroyedError)("type stage");
1886
+ if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("type stage");
1833
1887
  const resolved = resolveWorkspaceFile(this.#workspace, project);
1834
1888
  this.#progress += 1;
1835
1889
  this.#service(typescript, project);
@@ -1872,7 +1926,7 @@ var TypeStage = class {
1872
1926
  }
1873
1927
  async #unblock() {
1874
1928
  await (0, node_timers_promises.setTimeout)(0);
1875
- if (this.#destroyed) throw (0, _src_core.createDestroyedError)("type stage");
1929
+ if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("type stage");
1876
1930
  }
1877
1931
  #record(draft, overlay) {
1878
1932
  overlay.set(resolveWorkspaceFile(this.#workspace, draft.path), draft.text);
@@ -2060,7 +2114,6 @@ var Probe = class {
2060
2114
  #typeTail = Promise.resolve();
2061
2115
  #arming;
2062
2116
  #closing;
2063
- #destroyed = false;
2064
2117
  /**
2065
2118
  * Resolves the target toolchain and starts warming the resident stages.
2066
2119
  *
@@ -2110,7 +2163,7 @@ var Probe = class {
2110
2163
  this.#support();
2111
2164
  this.#admit(claim);
2112
2165
  await this.#ready();
2113
- if (this.#destroyed) throw (0, _src_core.createDestroyedError)("probe");
2166
+ if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("probe");
2114
2167
  const started = performance.now();
2115
2168
  const id = (0, node_crypto.randomUUID)();
2116
2169
  const project = await this.#resolve(claim);
@@ -2144,7 +2197,6 @@ var Probe = class {
2144
2197
  }
2145
2198
  destroy() {
2146
2199
  if (this.#closing !== void 0) return this.#closing;
2147
- this.#destroyed = true;
2148
2200
  this.#closing = this.#destroy();
2149
2201
  return this.#closing;
2150
2202
  }
@@ -2154,7 +2206,7 @@ var Probe = class {
2154
2206
  await attempt;
2155
2207
  return;
2156
2208
  } catch (error) {
2157
- if (this.#destroyed) throw error;
2209
+ if (this.#closing !== void 0) throw error;
2158
2210
  }
2159
2211
  if (this.#arming === attempt) {
2160
2212
  this.#arming = this.#arm();
@@ -2206,8 +2258,8 @@ var Probe = class {
2206
2258
  }
2207
2259
  async #boot(created) {
2208
2260
  const revision = `${process.pid}-${(0, node_crypto.randomUUID)()}`;
2209
- const typeDependency = createRevisionFile(this.#workspace, "tmp/probe/arm-type.ts", revision);
2210
- const runtimeDependency = createRevisionFile(this.#workspace, "tmp/probe/arm-runtime.ts", revision);
2261
+ const typeDependency = buildRevisionPath(this.#workspace, "tmp/probe/arm-type.ts", revision);
2262
+ const runtimeDependency = buildRevisionPath(this.#workspace, "tmp/probe/arm-runtime.ts", revision);
2211
2263
  const typeModule = (0, node_path.basename)(typeDependency, ".ts");
2212
2264
  const runtimeModule = (0, node_path.basename)(runtimeDependency, ".ts");
2213
2265
  const typeTest = {
@@ -2348,7 +2400,7 @@ var Probe = class {
2348
2400
  }
2349
2401
  }
2350
2402
  async #recycle(stage) {
2351
- if (this.#destroyed) return false;
2403
+ if (this.#closing !== void 0) return false;
2352
2404
  const timeout = (0, _orkestrel_timeout.createTimeout)({ ms: this.#deadline });
2353
2405
  timeout.start();
2354
2406
  try {
@@ -2356,7 +2408,7 @@ var Probe = class {
2356
2408
  } catch {} finally {
2357
2409
  timeout.clear();
2358
2410
  }
2359
- if (this.#destroyed) return false;
2411
+ if (this.#closing !== void 0) return false;
2360
2412
  if (stage === this.#type) {
2361
2413
  this.#type = new TypeStage(this.#workspace);
2362
2414
  return true;
@@ -2414,13 +2466,17 @@ var Probe = class {
2414
2466
  }
2415
2467
  async #destroy() {
2416
2468
  try {
2417
- await this.#arming;
2418
- } catch {}
2419
- await Promise.all([
2420
- this.#destroyStage(this.#type),
2421
- this.#destroyStage(this.#lint),
2422
- this.#destroyStage(this.#runtime)
2423
- ]);
2469
+ try {
2470
+ await this.#arming;
2471
+ } catch {}
2472
+ await Promise.all([
2473
+ this.#destroyStage(this.#type),
2474
+ this.#destroyStage(this.#lint),
2475
+ this.#destroyStage(this.#runtime)
2476
+ ]);
2477
+ } finally {
2478
+ this.#emitter.destroy();
2479
+ }
2424
2480
  }
2425
2481
  async #destroyStage(stage) {
2426
2482
  try {
@@ -2643,10 +2699,11 @@ exports.Probe = Probe;
2643
2699
  exports.ProbeServer = ProbeServer;
2644
2700
  exports.RuntimeStage = RuntimeStage;
2645
2701
  exports.TypeStage = TypeStage;
2702
+ exports.buildRevisionPath = buildRevisionPath;
2646
2703
  exports.captureListeners = captureListeners;
2647
2704
  exports.computeDigest = computeDigest;
2648
- exports.createRevisionFile = createRevisionFile;
2649
2705
  exports.describeUnknown = describeUnknown;
2706
+ exports.escapesRoot = escapesRoot;
2650
2707
  exports.findRefusedPaths = findRefusedPaths;
2651
2708
  exports.guardStage = guardStage;
2652
2709
  exports.inferDocumentLanguage = inferDocumentLanguage;
@@ -2658,6 +2715,7 @@ exports.matchesWorkspaceModule = matchesWorkspaceModule;
2658
2715
  exports.normalizePath = normalizePath;
2659
2716
  exports.normalizeValue = normalizeValue;
2660
2717
  exports.overwriteFile = overwriteFile;
2718
+ exports.readFaultCode = readFaultCode;
2661
2719
  exports.readWorkspaceManifest = readWorkspaceManifest;
2662
2720
  exports.relativeWorkspaceFile = relativeWorkspaceFile;
2663
2721
  exports.relativeWorkspaceMessage = relativeWorkspaceMessage;