@orkestrel/probe 0.0.2 → 0.0.4

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.
@@ -1,16 +1,16 @@
1
1
  import { createRequire } from "node:module";
2
- import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { closeSync, constants, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
5
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
6
  import { attempt, compileGuard, compileSchema, isArray, isRecord, schemaToParameters } from "@orkestrel/contract";
6
- import { CLAIM_SHAPE, ProbeError, computeReceipt, createDestroyedError, formatCheck, formatSpecification, formatVerdict, isClaim, isDraft, isVerdict, matchesSpecification } from "../core/index.js";
7
+ import { CLAIM_SHAPE, ProbeError, computeReceipt, createDestroyedError, formatCheck, formatSpecification, formatVerdict, isClaim, isDraft, isProbeError, isVerdict, matchesSpecification } from "../core/index.js";
7
8
  import { Emitter } from "@orkestrel/emitter";
8
9
  import { createQueue } from "@orkestrel/queue";
9
10
  import { createTimeout } from "@orkestrel/timeout";
10
11
  import { spawn } from "node:child_process";
11
- import { fileURLToPath, pathToFileURL } from "node:url";
12
12
  import { PassThrough } from "node:stream";
13
- import { setImmediate } from "node:timers/promises";
13
+ import { setTimeout } from "node:timers/promises";
14
14
  import { createMCPLegacy, createMCPServer } from "@orkestrel/mcp";
15
15
  import { createStdioServer } from "@orkestrel/mcp/server";
16
16
  import { createTool, createToolManager } from "@orkestrel/tool";
@@ -106,6 +106,46 @@ function resolveWorkspaceFile(workspace, target, mutate = false) {
106
106
  return file;
107
107
  }
108
108
  /**
109
+ * Overwrites a file that already exists, through a descriptor that refuses a symbolic link at the
110
+ * final component.
111
+ *
112
+ * @remarks
113
+ * A containment walk and the write that follows it are separate calls, so a process that swaps the
114
+ * final component between them decides where the bytes land. `writeFileSync` opens with the default
115
+ * `w` flag, which follows a symbolic link at that component and creates the file when it is absent,
116
+ * so the walk's reading does not bind the write. Opening `O_WRONLY | O_TRUNC | O_NOFOLLOW` moves
117
+ * that decision into the call that writes: a link at the final component refuses the open, and the
118
+ * omitted `O_CREAT` fails `ENOENT` for a target that has gone since the walk saw it. This is the
119
+ * mutating counterpart of the `wx` flag every create in this package uses. Which code the refusal
120
+ * carries is the host's; Linux with Node v22.22.2 reported `ELOOP` on 2026-08-24.
121
+ *
122
+ * A directory component stays open, because Node exposes no descriptor-relative call to walk and
123
+ * write through one set of descriptors. Where a host's Node build defines no `O_NOFOLLOW`, that flag
124
+ * contributes nothing to the flag set and the final component is open on that host too.
125
+ *
126
+ * @param file - The absolute path to overwrite
127
+ * @param text - The text to write
128
+ * @returns Nothing
129
+ * @throws The host's own fault when the final component is a symbolic link, when the file is
130
+ * absent, or when the host refuses the descriptor
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * const file = resolveWorkspaceFile('/srv/checkout', 'tmp/probe/arm-type.ts', true)
135
+ * writeFileSync(file, 'export type Signal = string\n', { encoding: 'utf8', flag: 'wx' })
136
+ * overwriteFile(file, 'export type Signal = number\n')
137
+ * readFileSync(file, 'utf8') // 'export type Signal = number\n'
138
+ * ```
139
+ */
140
+ function overwriteFile(file, text) {
141
+ const descriptor = openSync(file, constants.O_WRONLY | constants.O_TRUNC | constants.O_NOFOLLOW);
142
+ try {
143
+ writeFileSync(descriptor, text, "utf8");
144
+ } finally {
145
+ closeSync(descriptor);
146
+ }
147
+ }
148
+ /**
109
149
  * Reports whether a fault means the host refuses the name a caller supplied for a file to create.
110
150
  *
111
151
  * @remarks
@@ -169,6 +209,60 @@ function relativeWorkspaceFile(workspace, file) {
169
209
  return normalizePath(relative(resolve(workspace), resolve(file)));
170
210
  }
171
211
  /**
212
+ * Projects the paths one tool named in a message into the forms this package's issues expose.
213
+ *
214
+ * @remarks
215
+ * An issue's `path` is workspace-relative, and its message is prose a tool wrote about the same
216
+ * tree. Left alone that prose names a file by the host's own layout, so one issue reports a path two
217
+ * ways and a reader on another checkout is sent to a directory that is not theirs. Each spelling of
218
+ * the root is removed: the absolute path, the backslash spelling a Windows tool writes, and the
219
+ * `file:` URL a runtime names a module by. A root the host itself names ends in a separator, and the
220
+ * paths beneath it continue straight from it rather than from one more separator. A path outside the
221
+ * workspace stands as it is, because a relative spelling of it would name a file the tree does not
222
+ * hold.
223
+ *
224
+ * A spelling of the root counts only where a path begins: at the start of the message, or after a
225
+ * character no path carries. A directory whose own name ends in this root's text holds a different
226
+ * tree, so the root inside a longer path names a file this workspace does not hold and that path
227
+ * survives whole.
228
+ *
229
+ * Only the root is removed. A name is otherwise the tool's, including a `.probe-` name that reads
230
+ * like a specification this package generates: the stage that wrote one knows the exact name it
231
+ * wrote and renames that name itself, which is the only reading that separates its own file from a
232
+ * file the target tree owns.
233
+ *
234
+ * Everything else the tool wrote survives verbatim, separators included. A message carries text
235
+ * that is not a path — a runtime escapes a newline as a backslash when it prints a string inline,
236
+ * and a compiler quotes a string literal with its escapes intact — so rewriting every separator
237
+ * would corrupt the evidence the message exists to carry. The cost is that the path left behind
238
+ * keeps the separator the tool chose, which on Windows is not the one `Issue.path` uses.
239
+ *
240
+ * @param workspace - The target workspace root
241
+ * @param message - The message a tool reported
242
+ * @returns The message with the host's own layout removed from every path that begins with it
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * relativeWorkspaceMessage('/srv/checkout', 'Cannot read /srv/checkout/tsconfig.json')
247
+ * // 'Cannot read tsconfig.json'
248
+ * relativeWorkspaceMessage('/srv/checkout', 'Cannot read /mirror/srv/checkout/tsconfig.json')
249
+ * // 'Cannot read /mirror/srv/checkout/tsconfig.json'
250
+ * ```
251
+ */
252
+ function relativeWorkspaceMessage(workspace, message) {
253
+ const root = resolve(workspace);
254
+ const forward = normalizePath(root);
255
+ const url = pathToFileURL(forward).href;
256
+ const spellings = /* @__PURE__ */ new Set([
257
+ url.endsWith("/") ? url : `${url}/`,
258
+ forward.endsWith("/") ? forward : `${forward}/`,
259
+ root.endsWith(sep) ? root : `${root}${sep}`
260
+ ]);
261
+ let text = message;
262
+ for (const spelling of spellings) text = text.replaceAll(spelling, (match, offset, source) => /[^\s"'`()[\]{}<>,;:=|]/u.test(source.charAt(offset - 1)) ? match : "");
263
+ return text;
264
+ }
265
+ /**
172
266
  * Resolves one installed module from the target workspace.
173
267
  *
174
268
  * @param workspace - The target workspace root
@@ -456,6 +550,32 @@ function describeUnknown(value) {
456
550
  return String(value);
457
551
  }
458
552
  /**
553
+ * Guards one resident-stage operation with the stage failure contract.
554
+ *
555
+ * @param stage - The resident stage serving the operation
556
+ * @param operation - The operation to settle
557
+ * @returns The operation's fulfilled value
558
+ * @throws The original `ProbeError`, or an instrument-owned malformed failure retaining the cause
559
+ *
560
+ * @example
561
+ * ```ts
562
+ * await guardStage('type', stage.inspect(subject))
563
+ * ```
564
+ */
565
+ async function guardStage(stage, operation) {
566
+ try {
567
+ return await operation;
568
+ } catch (error) {
569
+ if (error instanceof ProbeError) throw error;
570
+ throw new ProbeError(`The ${stage} stage could not serve (${describeUnknown(error)})`, {
571
+ origin: "instrument",
572
+ code: "malformed",
573
+ context: { stage },
574
+ cause: error
575
+ });
576
+ }
577
+ }
578
+ /**
459
579
  * Names every draft member of a claim-shaped value whose `path` this package's guard refuses.
460
580
  *
461
581
  * @remarks
@@ -685,7 +805,7 @@ var Overlay = class {
685
805
  };
686
806
  //#endregion
687
807
  //#region package.json
688
- var version = "0.0.2";
808
+ var version = "0.0.4";
689
809
  var peerDependencies = {
690
810
  "oxlint": "^1.77.0",
691
811
  "typescript": "^6.0.0",
@@ -751,7 +871,16 @@ var LintStage = class {
751
871
  get progress() {
752
872
  return this.#progress;
753
873
  }
754
- async inspect(subject) {
874
+ inspect(subject) {
875
+ return guardStage(this.stage, this.#inspect(subject));
876
+ }
877
+ destroy() {
878
+ if (this.#closing !== void 0) return this.#closing;
879
+ this.#destroyed = true;
880
+ this.#closing = guardStage(this.stage, this.#destroy());
881
+ return this.#closing;
882
+ }
883
+ async #inspect(subject) {
755
884
  if (this.#destroyed) throw createDestroyedError("lint stage");
756
885
  const started = performance.now();
757
886
  await this.#warmth;
@@ -764,12 +893,6 @@ var LintStage = class {
764
893
  issues
765
894
  };
766
895
  }
767
- destroy() {
768
- if (this.#closing !== void 0) return this.#closing;
769
- this.#destroyed = true;
770
- this.#closing = this.#destroy();
771
- return this.#closing;
772
- }
773
896
  async #destroy() {
774
897
  const child = await this.#warmed();
775
898
  this.#fail(createDestroyedError("lint stage"));
@@ -1057,6 +1180,13 @@ var LintStage = class {
1057
1180
  * workspace module whose disk content or candidate revision changed, runs that specification,
1058
1181
  * evicts its result, and deletes the file. Clearing the overlay makes the next snapshot differ from
1059
1182
  * the candidate revision, so the next inspection invalidates that module and reads disk again.
1183
+ * After the run, the stage checks each covered module reachable from the generated specification
1184
+ * against the overlay paths its loader served. A target-config loader that served first produces a
1185
+ * workspace issue; a module id probe's loader received but failed to match produces an instrument
1186
+ * issue.
1187
+ * The runtime overlay leaves bare specifier resolution to Vite: it replaces a bare import only
1188
+ * after Vite resolves that import to a covered file. The type stage overlays the declared test
1189
+ * path, while this stage executes a generated sibling and overlays only the candidate files.
1060
1190
  *
1061
1191
  * Vite retains one unresolved URL for every specification path, so the stage replaces its whole
1062
1192
  * Vitest service after 64 specifications rather than deleting from each map that service owns. Any
@@ -1080,9 +1210,12 @@ var LintStage = class {
1080
1210
  * test path the host refuses to create is a claimant failure with `code: 'refused'`. Each is thrown
1081
1211
  * rather than reported, because a test that never ran is no evidence about the candidate.
1082
1212
  *
1083
- * The write path's physical-containment guarantee covers the claim inputs and the target tree as
1084
- * inspected. A concurrent process that mutates a path component between the final inspection and
1085
- * the write is outside that guarantee.
1213
+ * Physical containment covers the claim inputs, the target tree as the walk inspected it, and the
1214
+ * final component at the moment this stage writes or unlinks it: a specification is created with the
1215
+ * `wx` flag, which fails rather than following a symbolic link that appeared after the walk, and an
1216
+ * unlink names the final component itself rather than what it points at. A directory component
1217
+ * swapped for a symbolic link between the walk and the write stays open, because Node exposes no
1218
+ * descriptor-relative call to pin the walk and the write to one set of descriptors.
1086
1219
  *
1087
1220
  * @example
1088
1221
  * ```ts
@@ -1095,6 +1228,8 @@ var RuntimeStage = class {
1095
1228
  #workspace;
1096
1229
  #vitest;
1097
1230
  #overlay = new Overlay();
1231
+ #loads = /* @__PURE__ */ new Set();
1232
+ #reads = /* @__PURE__ */ new Set();
1098
1233
  #modules = /* @__PURE__ */ new Map();
1099
1234
  #revisions = /* @__PURE__ */ new Set();
1100
1235
  #specifications = 0;
@@ -1109,8 +1244,7 @@ var RuntimeStage = class {
1109
1244
  constructor(workspace = process.cwd()) {
1110
1245
  this.#workspace = workspace;
1111
1246
  const vitest = loadWorkspaceModule(this.#workspace, "vitest/node");
1112
- this.#vitest = this.#warm(vitest.createVitest);
1113
- this.#vitest.catch(() => {});
1247
+ this.#store(this.#warm(vitest.createVitest));
1114
1248
  }
1115
1249
  get stage() {
1116
1250
  return "runtime";
@@ -1118,7 +1252,16 @@ var RuntimeStage = class {
1118
1252
  get progress() {
1119
1253
  return this.#progress;
1120
1254
  }
1121
- async inspect(subject) {
1255
+ inspect(subject) {
1256
+ return guardStage(this.stage, this.#inspect(subject));
1257
+ }
1258
+ destroy() {
1259
+ if (this.#closing !== void 0) return this.#closing;
1260
+ this.#destroyed = true;
1261
+ this.#closing = guardStage(this.stage, this.#destroy());
1262
+ return this.#closing;
1263
+ }
1264
+ async #inspect(subject) {
1122
1265
  if (this.#destroyed) throw createDestroyedError("runtime stage");
1123
1266
  const started = performance.now();
1124
1267
  const exitCode = process.exitCode;
@@ -1132,6 +1275,8 @@ var RuntimeStage = class {
1132
1275
  };
1133
1276
  const overlay = new Overlay();
1134
1277
  this.#overlay = overlay;
1278
+ this.#loads.clear();
1279
+ this.#reads.clear();
1135
1280
  try {
1136
1281
  for (const draft of subject.files) overlay.set(resolveWorkspaceFile(this.#workspace, draft.path), draft.text);
1137
1282
  this.#revalidate(vitest);
@@ -1151,7 +1296,7 @@ var RuntimeStage = class {
1151
1296
  try {
1152
1297
  try {
1153
1298
  const result = await vitest.runTestSpecifications([task], false);
1154
- issues = this.#issues(result, file, subject.test.path);
1299
+ issues = [...this.#issues(result, file, subject.test.path), ...this.#misses(project, file)];
1155
1300
  } catch (error) {
1156
1301
  if (error instanceof ProbeError) throw error;
1157
1302
  throw new ProbeError(`The runtime stage could not run the generated specification (${describeUnknown(error)})`, {
@@ -1186,15 +1331,11 @@ var RuntimeStage = class {
1186
1331
  issues: [...issues, ...cleanup]
1187
1332
  };
1188
1333
  } finally {
1334
+ this.#loads.clear();
1335
+ this.#reads.clear();
1189
1336
  overlay.clear();
1190
1337
  }
1191
1338
  }
1192
- destroy() {
1193
- if (this.#closing !== void 0) return this.#closing;
1194
- this.#destroyed = true;
1195
- this.#closing = this.#destroy();
1196
- return this.#closing;
1197
- }
1198
1339
  async #destroy() {
1199
1340
  try {
1200
1341
  for (const file of this.#revisions) try {
@@ -1202,13 +1343,15 @@ var RuntimeStage = class {
1202
1343
  if (existsSync(contained)) unlinkSync(contained);
1203
1344
  } catch {}
1204
1345
  this.#revisions.clear();
1205
- const vitest = await this.#vitest.catch(() => void 0);
1346
+ const vitest = await this.#vitest?.catch(() => void 0);
1206
1347
  if (vitest !== void 0) {
1207
1348
  vitest.cancelCurrentRun("keyboard-input").catch(() => {});
1208
1349
  await vitest.close();
1209
1350
  }
1210
1351
  } finally {
1211
1352
  this.#modules.clear();
1353
+ this.#loads.clear();
1354
+ this.#reads.clear();
1212
1355
  this.#overlay.clear();
1213
1356
  }
1214
1357
  }
@@ -1217,8 +1360,9 @@ var RuntimeStage = class {
1217
1360
  const output = new PassThrough();
1218
1361
  output.resume();
1219
1362
  const signals = captureListeners(process, ["SIGINT", "SIGTERM"]);
1363
+ let warming;
1220
1364
  try {
1221
- return create("test", {
1365
+ warming = create("test", {
1222
1366
  root: this.#workspace,
1223
1367
  config: resolveWorkspaceFile(this.#workspace, "vite.config.ts"),
1224
1368
  watch: false,
@@ -1236,9 +1380,16 @@ var RuntimeStage = class {
1236
1380
  stdout: output,
1237
1381
  stderr: process.stderr
1238
1382
  });
1383
+ } catch (error) {
1384
+ throw this.#configuration(error);
1239
1385
  } finally {
1240
1386
  releaseListeners(process, signals);
1241
1387
  }
1388
+ try {
1389
+ return await warming;
1390
+ } catch (error) {
1391
+ throw this.#configuration(error);
1392
+ }
1242
1393
  }
1243
1394
  #configure(config) {
1244
1395
  const test = config.test;
@@ -1265,7 +1416,7 @@ var RuntimeStage = class {
1265
1416
  };
1266
1417
  }
1267
1418
  #resolve(id, importer) {
1268
- const separator = id.lastIndexOf("?");
1419
+ const separator = id.indexOf("?");
1269
1420
  const specifier = separator === -1 ? id : id.slice(0, separator);
1270
1421
  const suffix = separator === -1 ? "" : id.slice(separator);
1271
1422
  if (!specifier.startsWith(".") && !isAbsolute(specifier)) return void 0;
@@ -1277,17 +1428,22 @@ var RuntimeStage = class {
1277
1428
  if (extension === "") candidates.push(`${imported}.ts`);
1278
1429
  for (const candidate of candidates) {
1279
1430
  const resolved = `${candidate}${suffix}`;
1280
- if (this.#load(resolved) !== void 0) return resolved;
1431
+ if (this.#overlay.text(candidate) !== void 0) return resolved;
1281
1432
  }
1282
1433
  }
1283
1434
  #load(id) {
1284
- const text = this.#overlay.text(id);
1285
- if (text !== void 0) return text;
1286
- const separator = id.lastIndexOf("?");
1287
- if (separator === -1) return void 0;
1288
- const query = id.slice(separator + 1);
1289
- if (!query.startsWith("v=") || query.length === 2 || query.includes("&") || query.includes("#") || query.slice(2).includes("?")) return;
1290
- return this.#overlay.text(id.slice(0, separator));
1435
+ this.#loads.add(normalizePath(id));
1436
+ const separator = id.indexOf("?");
1437
+ const path = separator === -1 ? id : id.slice(0, separator);
1438
+ const text = this.#overlay.text(path);
1439
+ if (text === void 0) return void 0;
1440
+ this.#reads.add(normalizePath(path));
1441
+ if (separator !== -1 && /(?:^|&)raw(?:&|$)/u.test(id.slice(separator + 1))) return {
1442
+ code: `export default ${JSON.stringify(text)}`,
1443
+ map: { mappings: "" },
1444
+ moduleType: "js"
1445
+ };
1446
+ return text;
1291
1447
  }
1292
1448
  #specification(test) {
1293
1449
  let creating = false;
@@ -1359,6 +1515,47 @@ var RuntimeStage = class {
1359
1515
  };
1360
1516
  return project;
1361
1517
  }
1518
+ #misses(project, specification) {
1519
+ const file = normalizePath(specification);
1520
+ const issues = [];
1521
+ for (const path of this.#overlay.paths) {
1522
+ if (this.#reads.has(path)) continue;
1523
+ let served = false;
1524
+ let loaded = false;
1525
+ for (const environment of Object.values(project.vite.environments)) {
1526
+ const modules = environment.moduleGraph.getModulesByFile(path);
1527
+ if (modules === void 0) continue;
1528
+ for (const module of modules) {
1529
+ const pending = [...module.importers];
1530
+ const seen = new Set(pending);
1531
+ let reaches = false;
1532
+ while (pending.length > 0) {
1533
+ const importer = pending.pop();
1534
+ if (importer === void 0) break;
1535
+ if (importer.file !== null && normalizePath(importer.file) === file) {
1536
+ reaches = true;
1537
+ break;
1538
+ }
1539
+ for (const parent of importer.importers) {
1540
+ if (seen.has(parent)) continue;
1541
+ seen.add(parent);
1542
+ pending.push(parent);
1543
+ }
1544
+ }
1545
+ if (!reaches) continue;
1546
+ served = true;
1547
+ if (module.id !== null && this.#loads.has(normalizePath(module.id))) loaded = true;
1548
+ }
1549
+ }
1550
+ if (!served) continue;
1551
+ issues.push({
1552
+ origin: loaded ? "instrument" : "workspace",
1553
+ path: relativeWorkspaceFile(this.#workspace, path),
1554
+ message: loaded ? "The runtime overlay did not resolve this module" : "The workspace configuration served this module before the runtime overlay"
1555
+ });
1556
+ }
1557
+ return issues;
1558
+ }
1362
1559
  async #evict(vitest, file) {
1363
1560
  try {
1364
1561
  const ids = [];
@@ -1399,17 +1596,38 @@ var RuntimeStage = class {
1399
1596
  }
1400
1597
  }
1401
1598
  #runner() {
1402
- if (this.#specifications < 64) return this.#vitest;
1403
- this.#specifications = 0;
1404
- this.#vitest = this.#replace(this.#vitest);
1405
- this.#vitest.catch(() => {});
1406
- return this.#vitest;
1599
+ const current = this.#vitest;
1600
+ if (current !== void 0 && this.#specifications < 64) return current;
1601
+ if (current !== void 0) return this.#store(this.#replace(current));
1602
+ const runner = loadWorkspaceModule(this.#workspace, "vitest/node");
1603
+ return this.#store(this.#specifications < 64 ? this.#warm(runner.createVitest) : this.#replace(void 0, runner.createVitest));
1407
1604
  }
1408
- async #replace(current) {
1409
- await (await current).close();
1605
+ async #replace(current, create) {
1606
+ if (current !== void 0) await (await current).close();
1410
1607
  if (this.#destroyed) throw createDestroyedError("runtime stage");
1411
- const runner = loadWorkspaceModule(this.#workspace, "vitest/node");
1412
- return this.#warm(runner.createVitest);
1608
+ const runner = create ?? loadWorkspaceModule(this.#workspace, "vitest/node").createVitest;
1609
+ const replacement = await this.#warm(runner);
1610
+ this.#specifications = 0;
1611
+ return replacement;
1612
+ }
1613
+ #store(vitest) {
1614
+ this.#vitest = vitest;
1615
+ vitest.catch(() => {
1616
+ if (this.#vitest === vitest) this.#vitest = void 0;
1617
+ });
1618
+ return vitest;
1619
+ }
1620
+ #configuration(error) {
1621
+ if (isProbeError(error)) return error;
1622
+ return new ProbeError(`The runtime stage could not load vite.config.ts (${describeUnknown(error)})`, {
1623
+ origin: "workspace",
1624
+ code: "malformed",
1625
+ context: {
1626
+ stage: this.stage,
1627
+ path: "vite.config.ts"
1628
+ },
1629
+ cause: error
1630
+ });
1413
1631
  }
1414
1632
  #revalidate(vitest) {
1415
1633
  const modules = this.#snapshot();
@@ -1554,7 +1772,7 @@ var RuntimeStage = class {
1554
1772
  return outcome.success ? outcome.value : path;
1555
1773
  }
1556
1774
  #issue(error, specification, original) {
1557
- const message = describeUnknown(error);
1775
+ const message = relativeWorkspaceMessage(this.#workspace, describeUnknown(error)).replaceAll(basename(specification), basename(original));
1558
1776
  if (typeof error !== "object" || error === null || !("stacks" in error)) return {
1559
1777
  origin: "claimant",
1560
1778
  path: original,
@@ -1661,7 +1879,33 @@ var TypeStage = class {
1661
1879
  * @returns One outcome for this stage
1662
1880
  * @throws When the resident compiler cannot start or the stage has already been destroyed
1663
1881
  */
1664
- async inspect(subject, project) {
1882
+ inspect(subject, project) {
1883
+ return guardStage(this.stage, this.#inspect(subject, project));
1884
+ }
1885
+ /**
1886
+ * Resolves one project to the path and digest this stage applies for it.
1887
+ *
1888
+ * @remarks
1889
+ * Reads the parse this stage itself applies, filling its cache when the project is not already
1890
+ * resident, so the reported digest is the configuration the inspection is judged under rather
1891
+ * than a second parse a caller ran. The returned record is a value copy, so a later eviction
1892
+ * does not move it.
1893
+ *
1894
+ * @param project - The workspace-relative TypeScript project to resolve
1895
+ * @returns The resolved workspace-relative path and the digest of its compiler options
1896
+ * @throws When the project escapes the workspace, cannot be parsed, or the stage has already
1897
+ * been destroyed
1898
+ */
1899
+ resolve(project) {
1900
+ return guardStage(this.stage, this.#resolve(project));
1901
+ }
1902
+ destroy() {
1903
+ if (this.#closing !== void 0) return this.#closing;
1904
+ this.#destroyed = true;
1905
+ this.#closing = guardStage(this.stage, this.#destroy());
1906
+ return this.#closing;
1907
+ }
1908
+ async #inspect(subject, project) {
1665
1909
  if (this.#destroyed) throw createDestroyedError("type stage");
1666
1910
  const started = performance.now();
1667
1911
  const typescript = await this.#typescript;
@@ -1673,8 +1917,13 @@ var TypeStage = class {
1673
1917
  draft: candidate.draft,
1674
1918
  project: project ?? inferTypeProject(relativeWorkspaceFile(this.#workspace, candidate.path))
1675
1919
  }));
1676
- this.#configure(this.#service(typescript, "tsconfig.json"), "tsconfig.json");
1677
- for (const selection of selections) this.#configure(this.#service(typescript, selection.project), selection.project);
1920
+ const root = this.#service(typescript, "tsconfig.json");
1921
+ this.#configure(root, "tsconfig.json");
1922
+ await this.#unblock();
1923
+ for (const selection of selections) {
1924
+ this.#configure(this.#service(typescript, selection.project), selection.project);
1925
+ await this.#unblock();
1926
+ }
1678
1927
  const overlay = new Overlay();
1679
1928
  this.#overlay = overlay;
1680
1929
  try {
@@ -1683,7 +1932,6 @@ var TypeStage = class {
1683
1932
  this.#progress += 1;
1684
1933
  const issues = [];
1685
1934
  const projects = /* @__PURE__ */ new Set();
1686
- const root = this.#service(typescript, "tsconfig.json");
1687
1935
  issues.push(...this.#issues(typescript, root, subject.test, "tsconfig.json", false, true));
1688
1936
  projects.add("tsconfig.json");
1689
1937
  await this.#unblock();
@@ -1704,37 +1952,19 @@ var TypeStage = class {
1704
1952
  overlay.clear();
1705
1953
  }
1706
1954
  }
1707
- /**
1708
- * Resolves one project to the path and digest this stage applies for it.
1709
- *
1710
- * @remarks
1711
- * Reads the parse this stage itself applies, filling its cache when the project is not already
1712
- * resident, so the reported digest is the configuration the inspection is judged under rather
1713
- * than a second parse a caller ran. The returned record is a value copy, so a later eviction
1714
- * does not move it.
1715
- *
1716
- * @param project - The workspace-relative TypeScript project to resolve
1717
- * @returns The resolved workspace-relative path and the digest of its compiler options
1718
- * @throws When the project escapes the workspace, cannot be parsed, or the stage has already
1719
- * been destroyed
1720
- */
1721
- async resolve(project) {
1955
+ async #resolve(project) {
1722
1956
  if (this.#destroyed) throw createDestroyedError("type stage");
1723
1957
  const typescript = await this.#typescript;
1724
1958
  if (this.#destroyed) throw createDestroyedError("type stage");
1725
1959
  const resolved = resolveWorkspaceFile(this.#workspace, project);
1960
+ this.#progress += 1;
1726
1961
  this.#service(typescript, project);
1962
+ await this.#unblock();
1727
1963
  return {
1728
1964
  path: relativeWorkspaceFile(this.#workspace, resolved),
1729
1965
  digest: computeDigest(this.#workspace, this.#options.get(resolved) ?? {})
1730
1966
  };
1731
1967
  }
1732
- destroy() {
1733
- if (this.#closing !== void 0) return this.#closing;
1734
- this.#destroyed = true;
1735
- this.#closing = this.#destroy();
1736
- return this.#closing;
1737
- }
1738
1968
  async #destroy() {
1739
1969
  await this.#typescript.catch(() => void 0);
1740
1970
  for (const service of this.#services.values()) service.dispose();
@@ -1767,7 +1997,7 @@ var TypeStage = class {
1767
1997
  return projects;
1768
1998
  }
1769
1999
  async #unblock() {
1770
- await setImmediate();
2000
+ await setTimeout(0);
1771
2001
  if (this.#destroyed) throw createDestroyedError("type stage");
1772
2002
  }
1773
2003
  #record(draft, overlay) {
@@ -1779,7 +2009,7 @@ var TypeStage = class {
1779
2009
  if (existing !== void 0) return existing;
1780
2010
  const spelling = normalizePath(path);
1781
2011
  const config = typescript.readConfigFile(spelling, typescript.sys.readFile);
1782
- if (config.error !== void 0) throw new ProbeError(this.#translate(typescript, config.error.messageText, path), {
2012
+ if (config.error !== void 0) throw new ProbeError(this.#translate(typescript, config.error.messageText), {
1783
2013
  origin: "workspace",
1784
2014
  code: "malformed",
1785
2015
  context: {
@@ -1788,7 +2018,7 @@ var TypeStage = class {
1788
2018
  }
1789
2019
  });
1790
2020
  const parsed = typescript.parseJsonConfigFileContent(config.config, typescript.sys, dirname(spelling), void 0, spelling);
1791
- if (parsed.errors.length > 0) throw new ProbeError(this.#translate(typescript, parsed.errors[0]?.messageText, path), {
2021
+ if (parsed.errors.length > 0) throw new ProbeError(this.#translate(typescript, parsed.errors[0]?.messageText), {
1792
2022
  origin: "workspace",
1793
2023
  code: "malformed",
1794
2024
  context: {
@@ -1798,27 +2028,55 @@ var TypeStage = class {
1798
2028
  });
1799
2029
  this.#options.set(path, parsed.options);
1800
2030
  this.#files.set(path, parsed.fileNames);
1801
- const service = typescript.createLanguageService({
1802
- getCompilationSettings: () => this.#options.get(path) ?? {},
1803
- getScriptFileNames: () => [...this.#files.get(path) ?? [], ...this.#overlay.paths],
1804
- getScriptVersion: (file) => this.#version(file),
1805
- getScriptSnapshot: (file) => this.#snapshot(typescript, file),
1806
- getCurrentDirectory: () => this.#workspace,
1807
- getDefaultLibFileName: (options) => typescript.getDefaultLibFilePath(options),
1808
- fileExists: (file) => this.#overlay.text(file) !== void 0 || typescript.sys.fileExists(file),
1809
- readFile: (file) => this.#overlay.text(file) ?? typescript.sys.readFile(file),
2031
+ const host = {
2032
+ getCompilationSettings: this.#compilationSettings.bind(this, path),
2033
+ getScriptFileNames: this.#scriptFiles.bind(this, path),
2034
+ getScriptVersion: this.#version.bind(this),
2035
+ getScriptSnapshot: this.#snapshot.bind(this, typescript),
2036
+ getCurrentDirectory: this.#directory.bind(this),
2037
+ getDefaultLibFileName: this.#defaultLibrary.bind(this, typescript),
2038
+ fileExists: this.#fileExists.bind(this, typescript),
2039
+ readFile: this.#readFile.bind(this, typescript),
1810
2040
  readDirectory: typescript.sys.readDirectory,
1811
- directoryExists: (directory) => typescript.sys.directoryExists(directory) || this.#overlay.covers(directory),
2041
+ directoryExists: this.#directoryExists.bind(this, typescript),
1812
2042
  getDirectories: typescript.sys.getDirectories,
1813
- useCaseSensitiveFileNames: () => typescript.sys.useCaseSensitiveFileNames,
1814
- getNewLine: () => typescript.sys.newLine
1815
- });
2043
+ useCaseSensitiveFileNames: this.#caseSensitive.bind(this, typescript),
2044
+ getNewLine: this.#newline.bind(this, typescript)
2045
+ };
2046
+ const service = typescript.createLanguageService(host);
1816
2047
  this.#services.set(path, service);
1817
2048
  if (!this.#resident.has(path)) this.#recycle(path);
1818
2049
  return service;
1819
2050
  }
1820
- #translate(typescript, message, path) {
1821
- return normalizePath(typescript.flattenDiagnosticMessageText(message, "\n")).replaceAll(normalizePath(path), relativeWorkspaceFile(this.#workspace, path));
2051
+ #compilationSettings(path) {
2052
+ return this.#options.get(path) ?? {};
2053
+ }
2054
+ #scriptFiles(path) {
2055
+ return [...this.#files.get(path) ?? [], ...this.#overlay.paths];
2056
+ }
2057
+ #directory() {
2058
+ return this.#workspace;
2059
+ }
2060
+ #defaultLibrary(typescript, options) {
2061
+ return typescript.getDefaultLibFilePath(options);
2062
+ }
2063
+ #fileExists(typescript, file) {
2064
+ return this.#overlay.text(file) !== void 0 || typescript.sys.fileExists(file);
2065
+ }
2066
+ #readFile(typescript, file) {
2067
+ return this.#overlay.text(file) ?? typescript.sys.readFile(file);
2068
+ }
2069
+ #directoryExists(typescript, directory) {
2070
+ return typescript.sys.directoryExists(directory) || this.#overlay.covers(directory);
2071
+ }
2072
+ #caseSensitive(typescript) {
2073
+ return typescript.sys.useCaseSensitiveFileNames;
2074
+ }
2075
+ #newline(typescript) {
2076
+ return typescript.sys.newLine;
2077
+ }
2078
+ #translate(typescript, message) {
2079
+ return relativeWorkspaceMessage(this.#workspace, typescript.flattenDiagnosticMessageText(message, "\n"));
1822
2080
  }
1823
2081
  #configure(service, project) {
1824
2082
  const path = resolveWorkspaceFile(this.#workspace, project);
@@ -1857,7 +2115,7 @@ var TypeStage = class {
1857
2115
  ].map((diagnostic) => this.#issue(typescript, diagnostic, project, selected));
1858
2116
  }
1859
2117
  #issue(typescript, diagnostic, project, selected) {
1860
- const message = typescript.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
2118
+ const message = this.#translate(typescript, diagnostic.messageText);
1861
2119
  if (diagnostic.file === void 0) {
1862
2120
  if (selected) throw new ProbeError(message, {
1863
2121
  origin: "claimant",
@@ -1868,7 +2126,7 @@ var TypeStage = class {
1868
2126
  }
1869
2127
  });
1870
2128
  return {
1871
- origin: "instrument",
2129
+ origin: "workspace",
1872
2130
  path: project,
1873
2131
  message
1874
2132
  };
@@ -1920,6 +2178,8 @@ var Probe = class {
1920
2178
  #typeQueue;
1921
2179
  #lintQueue;
1922
2180
  #runtimeQueue;
2181
+ #deadlines = /* @__PURE__ */ new WeakSet();
2182
+ #typeTail = Promise.resolve();
1923
2183
  #arming;
1924
2184
  #closing;
1925
2185
  #destroyed = false;
@@ -1946,17 +2206,17 @@ var Probe = class {
1946
2206
  this.#typeQueue = createQueue({
1947
2207
  concurrency: 1,
1948
2208
  retries: 0,
1949
- handler: (inspection) => this.#inspectStage(this.#type, this.#type.progress, this.#type.inspect(inspection.subject, inspection.claim.project), inspection.claim)
2209
+ handler: this.#inspectType.bind(this)
1950
2210
  });
1951
2211
  this.#lintQueue = createQueue({
1952
2212
  concurrency: 1,
1953
2213
  retries: 0,
1954
- handler: (inspection) => this.#inspectStage(this.#lint, this.#lint.progress, this.#lint.inspect(inspection.subject), inspection.claim)
2214
+ handler: this.#inspectLint.bind(this)
1955
2215
  });
1956
2216
  this.#runtimeQueue = createQueue({
1957
2217
  concurrency: 1,
1958
2218
  retries: 0,
1959
- handler: (inspection) => this.#inspectStage(this.#runtime, this.#runtime.progress, this.#runtime.inspect(inspection.subject), inspection.claim)
2219
+ handler: this.#inspectRuntime.bind(this)
1960
2220
  });
1961
2221
  this.#arming = this.#arm();
1962
2222
  this.#arming.catch(() => {});
@@ -1970,11 +2230,12 @@ var Probe = class {
1970
2230
  async prove(claim) {
1971
2231
  try {
1972
2232
  this.#support();
2233
+ this.#admit(claim);
1973
2234
  await this.#ready();
1974
2235
  if (this.#destroyed) throw createDestroyedError("probe");
1975
2236
  const started = performance.now();
1976
2237
  const id = randomUUID();
1977
- const project = await this.#type.resolve(claim.project);
2238
+ const project = await this.#resolve(claim);
1978
2239
  const digest = computeDigest(this.#workspace, {
1979
2240
  case: claim.case,
1980
2241
  control: claim.control
@@ -2112,7 +2373,7 @@ var Probe = class {
2112
2373
  code: "malformed"
2113
2374
  });
2114
2375
  resolveWorkspaceFile(this.#workspace, relative(this.#workspace, typeDependency), true);
2115
- writeFileSync(typeDependency, formatSpecification("export type Signal = number\n", revision), "utf8");
2376
+ overwriteFile(typeDependency, formatSpecification("export type Signal = number\n", revision));
2116
2377
  const afterType = await this.#inspect(typeClaim.control, typeClaim);
2117
2378
  const type = afterType.find((check) => check.stage === typeClaim.control.stage);
2118
2379
  const tolerant = afterType.find((check) => check.stage === "runtime");
@@ -2127,7 +2388,7 @@ var Probe = class {
2127
2388
  context: { stage: "runtime" }
2128
2389
  });
2129
2390
  resolveWorkspaceFile(this.#workspace, relative(this.#workspace, runtimeDependency), true);
2130
- writeFileSync(runtimeDependency, formatSpecification("export const SIGNAL = 'after'\n", revision), "utf8");
2391
+ overwriteFile(runtimeDependency, formatSpecification("export const SIGNAL = 'after'\n", revision));
2131
2392
  const afterRuntime = await this.#inspect(runtimeClaim.control, runtimeClaim);
2132
2393
  const runtime = afterRuntime.find((check) => check.stage === runtimeClaim.control.stage);
2133
2394
  if (runtime === void 0 || runtime.issues.length === 0) throw new ProbeError(`The probe boot runtime control did not detect a mutated dependency\n${afterRuntime.map(formatCheck).join("\n")}`, {
@@ -2156,20 +2417,44 @@ var Probe = class {
2156
2417
  for (const pending of admitted) pending.catch(() => {});
2157
2418
  return Promise.all(admitted);
2158
2419
  }
2420
+ async #inspectType(inspection) {
2421
+ const release = await this.#admitType();
2422
+ try {
2423
+ const stage = this.#type;
2424
+ return await this.#inspectStage(stage, stage.progress, stage.inspect(inspection.subject, inspection.claim.project), inspection.claim);
2425
+ } finally {
2426
+ release();
2427
+ }
2428
+ }
2429
+ #inspectLint(inspection) {
2430
+ return this.#inspectStage(this.#lint, this.#lint.progress, this.#lint.inspect(inspection.subject), inspection.claim);
2431
+ }
2432
+ #inspectRuntime(inspection) {
2433
+ return this.#inspectStage(this.#runtime, this.#runtime.progress, this.#runtime.inspect(inspection.subject), inspection.claim);
2434
+ }
2159
2435
  async #inspectStage(stage, progress, operation, claim) {
2436
+ try {
2437
+ return await this.#bound(operation, `The ${stage.stage} stage exceeded ${this.#deadline} ms`, stage, progress);
2438
+ } catch (error) {
2439
+ this.#emitExpiry(stage, claim);
2440
+ throw error;
2441
+ }
2442
+ }
2443
+ async #bound(operation, message, stage, progress) {
2160
2444
  const timeout = createTimeout({ ms: this.#deadline });
2161
2445
  timeout.start();
2162
2446
  try {
2163
- return await Promise.race([operation, this.#expiry(timeout, `The ${stage.stage} stage exceeded ${this.#deadline} ms`, stage, progress)]);
2447
+ return await Promise.race([operation, this.#expiry(timeout, message, stage, progress)]);
2164
2448
  } catch (error) {
2165
2449
  if (!timeout.expired) throw error;
2166
- if (await this.#recycle(stage)) this.#emitter.emit("expire", claim);
2450
+ await this.#recycle(stage);
2167
2451
  throw error;
2168
2452
  } finally {
2169
2453
  timeout.clear();
2170
2454
  }
2171
2455
  }
2172
2456
  async #recycle(stage) {
2457
+ if (this.#destroyed) return false;
2173
2458
  const timeout = createTimeout({ ms: this.#deadline });
2174
2459
  timeout.start();
2175
2460
  try {
@@ -2192,16 +2477,45 @@ var Probe = class {
2192
2477
  }
2193
2478
  return false;
2194
2479
  }
2480
+ async #admitType() {
2481
+ const previous = this.#typeTail;
2482
+ const turn = Promise.withResolvers();
2483
+ this.#typeTail = turn.promise;
2484
+ await previous;
2485
+ return turn.resolve;
2486
+ }
2487
+ async #resolve(claim) {
2488
+ const release = await this.#admitType();
2489
+ try {
2490
+ const stage = this.#type;
2491
+ try {
2492
+ return await this.#bound(stage.resolve(claim.project), `The type stage project resolution exceeded ${this.#deadline} ms`, stage, stage.progress);
2493
+ } catch (error) {
2494
+ this.#emitExpiry(stage, claim);
2495
+ throw error;
2496
+ }
2497
+ } finally {
2498
+ release();
2499
+ }
2500
+ }
2501
+ #emitExpiry(stage, claim) {
2502
+ if (stage === this.#type || stage === this.#lint || stage === this.#runtime) return;
2503
+ this.#emitter.emit("expire", claim);
2504
+ }
2195
2505
  #expiry(timeout, message, stage, progress) {
2196
2506
  return new Promise((_resolve, reject) => {
2197
- timeout.signal.addEventListener("abort", () => reject(new ProbeError(message, {
2198
- origin: stage.progress > progress ? "claimant" : "instrument",
2199
- code: "deadline",
2200
- context: {
2201
- stage: stage.stage,
2202
- deadline: this.#deadline
2203
- }
2204
- })), { once: true });
2507
+ timeout.signal.addEventListener("abort", () => {
2508
+ const error = new ProbeError(message, {
2509
+ origin: stage.progress > progress ? "claimant" : "instrument",
2510
+ code: "deadline",
2511
+ context: {
2512
+ stage: stage.stage,
2513
+ deadline: this.#deadline
2514
+ }
2515
+ });
2516
+ this.#deadlines.add(error);
2517
+ reject(error);
2518
+ }, { once: true });
2205
2519
  });
2206
2520
  }
2207
2521
  async #destroy() {
@@ -2209,11 +2523,18 @@ var Probe = class {
2209
2523
  await this.#arming;
2210
2524
  } catch {}
2211
2525
  await Promise.all([
2212
- this.#type.destroy(),
2213
- this.#lint.destroy(),
2214
- this.#runtime.destroy()
2526
+ this.#destroyStage(this.#type),
2527
+ this.#destroyStage(this.#lint),
2528
+ this.#destroyStage(this.#runtime)
2215
2529
  ]);
2216
2530
  }
2531
+ async #destroyStage(stage) {
2532
+ try {
2533
+ await this.#bound(stage.destroy(), `The ${stage.stage} stage teardown exceeded ${this.#deadline} ms`, stage, stage.progress);
2534
+ } catch (error) {
2535
+ if (!(error instanceof ProbeError) || !this.#deadlines.has(error)) throw error;
2536
+ }
2537
+ }
2217
2538
  #version(name) {
2218
2539
  const version = readWorkspaceManifest(this.#workspace, name).contents.version;
2219
2540
  if (typeof version !== "string") throw new ProbeError(`${name} publishes no readable version`, {
@@ -2223,6 +2544,21 @@ var Probe = class {
2223
2544
  });
2224
2545
  return version;
2225
2546
  }
2547
+ #admit(claim) {
2548
+ const subject = claim.case;
2549
+ const control = claim.control;
2550
+ if (subject.test.path !== control.test.path) return;
2551
+ if (subject.test.text !== control.test.text) return;
2552
+ if (subject.files.length !== control.files.length) return;
2553
+ if (!subject.files.every((draft, index) => {
2554
+ const other = control.files[index];
2555
+ return other !== void 0 && other.path === draft.path && other.text === draft.text;
2556
+ })) return;
2557
+ throw new ProbeError("The control must differ from the case; it carries the same candidate drafts and the same test", {
2558
+ origin: "claimant",
2559
+ code: "refused"
2560
+ });
2561
+ }
2226
2562
  #support() {
2227
2563
  const version = this.#toolchain.typescript;
2228
2564
  const range = peerDependencies.typescript;
@@ -2342,17 +2678,7 @@ var ProbeServer = class {
2342
2678
  name: "prove",
2343
2679
  description: "Answers whether a TypeScript edit compiles, lints, and passes its test in this workspace — call it before relying on such a claim, instead of reasoning or writing a throwaway probe. Supply the edit you believe is correct and an edit that must break with the stage it breaks at; the closing line is a receipt only when the case ran clean and the control broke exactly at its declared stage, and no receipt otherwise. For a performance claim, measure before proving: write a guarded bench block — if (import.meta.env.MODE === 'benchmark') — beside the probe test, run the workspace bench script, and record only magnitudes; a settled ratio then proves here as an ordinary runtime claim.",
2344
2680
  parameters,
2345
- execute: async (input) => {
2346
- if (!isClaim(input)) {
2347
- const refused = findRefusedPaths(input);
2348
- throw new ProbeError(refused.length === 0 ? "The prove tool requires a claim matching the advertised schema" : `The prove tool refuses ${refused.join(", ")}: a draft path must stay inside the workspace, which the advertised schema does not constrain`, {
2349
- origin: "claimant",
2350
- code: "refused",
2351
- context: { value: input }
2352
- });
2353
- }
2354
- return this.#probe.prove(input);
2355
- }
2681
+ execute: this.#prove.bind(this)
2356
2682
  }));
2357
2683
  return createMCPServer({
2358
2684
  identity: {
@@ -2360,26 +2686,38 @@ var ProbeServer = class {
2360
2686
  version
2361
2687
  },
2362
2688
  tools,
2363
- execution: async ({ call }) => {
2364
- const result = await tools.execute(call);
2365
- if (!result.success) return result;
2366
- if (!isVerdict(result.value)) throw new ProbeError("The prove tool returned an invalid verdict", {
2367
- origin: "instrument",
2368
- code: "malformed",
2369
- context: { value: result.value }
2370
- });
2371
- return {
2372
- resultType: "complete",
2373
- content: [{
2374
- type: "text",
2375
- text: formatVerdict(result.value)
2376
- }]
2377
- };
2378
- }
2689
+ execution: this.#execute.bind(this)
2379
2690
  });
2380
2691
  }
2692
+ async #prove(input) {
2693
+ if (!isClaim(input)) {
2694
+ const refused = findRefusedPaths(input);
2695
+ throw new ProbeError(refused.length === 0 ? "The prove tool requires a claim matching the advertised schema" : `The prove tool refuses ${refused.join(", ")}: a draft path must stay inside the workspace, which the advertised schema does not constrain`, {
2696
+ origin: "claimant",
2697
+ code: "refused",
2698
+ context: { value: input }
2699
+ });
2700
+ }
2701
+ return this.#probe.prove(input);
2702
+ }
2703
+ async #execute(context) {
2704
+ const result = await context.tools.execute(context.call);
2705
+ if (!result.success) return result;
2706
+ if (!isVerdict(result.value)) throw new ProbeError("The prove tool returned an invalid verdict", {
2707
+ origin: "instrument",
2708
+ code: "malformed",
2709
+ context: { value: result.value }
2710
+ });
2711
+ return {
2712
+ resultType: "complete",
2713
+ content: [{
2714
+ type: "text",
2715
+ text: formatVerdict(result.value)
2716
+ }]
2717
+ };
2718
+ }
2381
2719
  };
2382
2720
  //#endregion
2383
- export { LintStage, Overlay, Probe, ProbeServer, RuntimeStage, TypeStage, captureListeners, computeDigest, createRevisionFile, describeUnknown, findRefusedPaths, inferDocumentLanguage, inferTestProject, inferTypeProject, isRefusedName, loadWorkspaceModule, matchesWorkspaceModule, normalizePath, normalizeValue, parseContentLength, readWorkspaceManifest, relativeWorkspaceFile, releaseListeners, resolveWorkspaceBinary, resolveWorkspaceFile, resolveWorkspaceModule };
2721
+ export { LintStage, Overlay, Probe, ProbeServer, RuntimeStage, TypeStage, captureListeners, computeDigest, createRevisionFile, describeUnknown, findRefusedPaths, guardStage, inferDocumentLanguage, inferTestProject, inferTypeProject, isRefusedName, loadWorkspaceModule, matchesWorkspaceModule, normalizePath, normalizeValue, overwriteFile, parseContentLength, readWorkspaceManifest, relativeWorkspaceFile, relativeWorkspaceMessage, releaseListeners, resolveWorkspaceBinary, resolveWorkspaceFile, resolveWorkspaceModule };
2384
2722
 
2385
2723
  //# sourceMappingURL=index.js.map