@orkestrel/probe 0.0.25 → 0.0.27

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.
@@ -7,6 +7,7 @@ let node_path = require("node:path");
7
7
  let node_url = require("node:url");
8
8
  let _orkestrel_contract = require("@orkestrel/contract");
9
9
  let _src_core = require("../core/index.cjs");
10
+ let _orkestrel_process_server = require("@orkestrel/process/server");
10
11
  let _orkestrel_emitter = require("@orkestrel/emitter");
11
12
  let _orkestrel_pool = require("@orkestrel/pool");
12
13
  let _orkestrel_lsp = require("@orkestrel/lsp");
@@ -18,7 +19,7 @@ let node_async_hooks = require("node:async_hooks");
18
19
  let node_child_process = require("node:child_process");
19
20
  let _orkestrel_mcp_server = require("@orkestrel/mcp/server");
20
21
  let _orkestrel_tool = require("@orkestrel/tool");
21
- //#region src/server/errors.ts
22
+ // src/server/errors.ts
22
23
  /**
23
24
  * Creates the protocol failure returned when the MCP handshake cannot arm the probe.
24
25
  *
@@ -36,8 +37,7 @@ function createHandshakeError(error) {
36
37
  code: error.code
37
38
  });
38
39
  }
39
- //#endregion
40
- //#region src/server/helpers.ts
40
+ // src/server/helpers.ts
41
41
  /**
42
42
  * Rewrites one path into the forward-slash spelling this package compares and reports paths in.
43
43
  *
@@ -152,13 +152,13 @@ function resolveWorkspaceFile(workspace, target, mutate = false) {
152
152
  if (!mutate) return file;
153
153
  try {
154
154
  const canonical = (0, node_fs.realpathSync)(root);
155
- let descendant = root;
156
- for (const segment of path.split(node_path.sep)) {
157
- descendant = (0, node_path.resolve)(descendant, segment);
155
+ path.split(node_path.sep).reduce((parent, segment) => {
156
+ if (parent === void 0) return void 0;
157
+ const descendant = (0, node_path.resolve)(parent, segment);
158
158
  const outcome = (0, _orkestrel_contract.attempt)(() => (0, node_fs.lstatSync)(descendant));
159
159
  if (!outcome.success) {
160
160
  const code = readFaultCode(outcome.error);
161
- if (code === "ENOENT" || code === "ENOTDIR") break;
161
+ if (code === "ENOENT" || code === "ENOTDIR") return void 0;
162
162
  throw outcome.error;
163
163
  }
164
164
  if (outcome.value.isSymbolicLink()) throw new _src_core.ProbeError(`Path crosses a symbolic link: ${target}`, {
@@ -166,12 +166,14 @@ function resolveWorkspaceFile(workspace, target, mutate = false) {
166
166
  code: "refused",
167
167
  context: { path: target }
168
168
  });
169
- if (escapesRoot(canonical, (0, node_fs.realpathSync)(descendant))) throw new _src_core.ProbeError(`Path escapes the workspace: ${target}`, {
169
+ const resolved = (0, node_fs.realpathSync)(descendant);
170
+ if (escapesRoot(canonical, resolved)) throw new _src_core.ProbeError(`Path escapes the workspace: ${target}`, {
170
171
  origin: "claimant",
171
172
  code: "refused",
172
173
  context: { path: target }
173
174
  });
174
- }
175
+ return descendant;
176
+ }, root);
175
177
  } catch (error) {
176
178
  if ((0, _src_core.isProbeError)(error)) throw error;
177
179
  const code = readFaultCode(error);
@@ -336,14 +338,11 @@ function relativeWorkspaceMessage(workspace, message) {
336
338
  const root = (0, node_path.resolve)(workspace);
337
339
  const forward = normalizePath(root);
338
340
  const url = (0, node_url.pathToFileURL)(forward).href;
339
- const spellings = /* @__PURE__ */ new Set([
341
+ return [.../* @__PURE__ */ new Set([
340
342
  url.endsWith("/") ? url : `${url}/`,
341
343
  forward.endsWith("/") ? forward : `${forward}/`,
342
344
  root.endsWith(node_path.sep) ? root : `${root}${node_path.sep}`
343
- ]);
344
- let text = message;
345
- for (const spelling of spellings) text = text.replaceAll(spelling, (match, offset, source) => /[^\s"'`()[\]{}<>,;:=|]/u.test(source.charAt(offset - 1)) ? match : "");
346
- return text;
345
+ ])].reduce((text, spelling) => text.replaceAll(spelling, (match, offset, source) => /[^\s"'`()[\]{}<>,;:=|]/u.test(source.charAt(offset - 1)) ? match : ""), message);
347
346
  }
348
347
  /**
349
348
  * Scans the plain-text output of one compiler run into the diagnostics it reported.
@@ -372,37 +371,36 @@ function relativeWorkspaceMessage(workspace, message) {
372
371
  * ```
373
372
  */
374
373
  function scanDiagnostics(text) {
375
- const diagnostics = [];
376
- for (const line of text.split(/\r\n|\n/)) {
374
+ const lines = text.split(/\r\n|\n/);
375
+ const headers = lines.map((line, index) => {
377
376
  const located = /^(.+)\((\d+),(\d+)\): (?:error|warning) TS\d+: (.*)$/u.exec(line);
378
377
  if (located !== null) {
379
378
  const point = {
380
379
  line: Number.parseInt(located[2] ?? "1", 10) - 1,
381
380
  character: Number.parseInt(located[3] ?? "1", 10) - 1
382
381
  };
383
- diagnostics.push({
384
- path: normalizePath(located[1] ?? ""),
385
- range: {
386
- start: point,
387
- end: point
388
- },
389
- message: located[4] ?? ""
390
- });
391
- continue;
382
+ return {
383
+ index,
384
+ diagnostic: {
385
+ path: normalizePath(located[1] ?? ""),
386
+ range: {
387
+ start: point,
388
+ end: point
389
+ },
390
+ message: located[4] ?? ""
391
+ }
392
+ };
392
393
  }
393
394
  const bare = /^(?:error|warning) TS\d+: (.*)$/u.exec(line);
394
- if (bare !== null) {
395
- diagnostics.push({ message: bare[1] ?? "" });
396
- continue;
397
- }
398
- const previous = diagnostics.at(-1);
399
- if (previous === void 0 || !/^\s+\S/u.test(line)) continue;
400
- diagnostics[diagnostics.length - 1] = {
401
- ...previous,
402
- message: `${previous.message}\n${line}`
395
+ return bare === null ? void 0 : {
396
+ index,
397
+ diagnostic: { message: bare[1] ?? "" }
403
398
  };
404
- }
405
- return diagnostics;
399
+ }).filter((header) => header !== void 0);
400
+ return headers.map((header, index) => ({
401
+ ...header.diagnostic,
402
+ message: [header.diagnostic.message, ...lines.slice(header.index + 1, headers[index + 1]?.index).filter((line) => /^\s+\S/u.test(line))].join("\n")
403
+ }));
406
404
  }
407
405
  /**
408
406
  * Resolves one installed module from the target workspace.
@@ -477,10 +475,9 @@ function loadWorkspaceVitest(workspace) {
477
475
  * ```
478
476
  */
479
477
  function readWorkspaceManifest(workspace, name) {
480
- let path;
481
- try {
482
- path = resolveWorkspaceModule(workspace, `${name}/package.json`);
483
- } catch (error) {
478
+ const resolved = (0, _orkestrel_contract.attempt)(() => resolveWorkspaceModule(workspace, `${name}/package.json`));
479
+ if (!resolved.success) {
480
+ const error = resolved.error;
484
481
  if (!(0, _src_core.isProbeError)(error)) throw error;
485
482
  throw new _src_core.ProbeError(`${name} does not publish a readable manifest`, {
486
483
  origin: "workspace",
@@ -489,6 +486,7 @@ function readWorkspaceManifest(workspace, name) {
489
486
  cause: error.cause
490
487
  });
491
488
  }
489
+ const path = resolved.value;
492
490
  const reading = (0, _orkestrel_contract.attempt)(() => (0, node_fs.readFileSync)(path, "utf8"));
493
491
  if (!reading.success) {
494
492
  const error = reading.error;
@@ -504,17 +502,17 @@ function readWorkspaceManifest(workspace, name) {
504
502
  cause: error
505
503
  });
506
504
  }
507
- const parsing = (0, _orkestrel_contract.attempt)(() => JSON.parse(reading.value));
508
- if (!parsing.success) throw new _src_core.ProbeError(`${name} does not publish a readable manifest`, {
505
+ const parsed = (0, _orkestrel_contract.attempt)(() => JSON.parse(reading.value));
506
+ if (!parsed.success) throw new _src_core.ProbeError(`${name} does not publish a readable manifest`, {
509
507
  origin: "workspace",
510
508
  code: "malformed",
511
509
  context: {
512
510
  name,
513
511
  path
514
512
  },
515
- cause: parsing.error
513
+ cause: parsed.error
516
514
  });
517
- const contents = parsing.value;
515
+ const contents = parsed.value;
518
516
  if (!(0, _orkestrel_contract.isRecord)(contents)) throw new _src_core.ProbeError(`${name} does not publish a readable manifest`, {
519
517
  origin: "workspace",
520
518
  code: "malformed",
@@ -685,20 +683,13 @@ function buildRevisionPath(workspace, path, revision) {
685
683
  * ```
686
684
  */
687
685
  function filterUniqueIssues(issues) {
688
- const seen = /* @__PURE__ */ new Set();
689
- const distinct = [];
690
- for (const issue of issues) {
691
- const key = JSON.stringify([
692
- issue.origin,
693
- issue.path,
694
- issue.message,
695
- issue.range
696
- ]);
697
- if (seen.has(key)) continue;
698
- seen.add(key);
699
- distinct.push(issue);
700
- }
701
- return distinct;
686
+ const groups = Map.groupBy(issues, (issue) => JSON.stringify([
687
+ issue.origin,
688
+ issue.path,
689
+ issue.message,
690
+ issue.range
691
+ ]));
692
+ return Iterator.from(groups.values()).flatMap((group) => group.slice(0, 1)).toArray();
702
693
  }
703
694
  /**
704
695
  * Reports whether a path is a workspace module Vitest can cache.
@@ -716,13 +707,11 @@ function matchesWorkspaceModule(path) {
716
707
  return /\.(?:[cm]?[jt]sx?|vue|json)$/.test(path);
717
708
  }
718
709
  /**
719
- * Reports whether the host that wrote one file is still running.
710
+ * Reports whether a file's owning host is running or cannot be judged.
720
711
  *
721
712
  * @remarks
722
- * Signal 0 delivers nothing and reports reachability alone. A process this one may not signal
723
- * reports `EPERM` and reads as running, and a non-positive identity names a process group rather
724
- * than a process, so both answer true: the safe direction is to keep a file this package cannot
725
- * account for.
713
+ * Keeps a file when its identity is invalid or `inspectProcess` reports existence, denied
714
+ * permission, or an indeterminate host failure. Only a confirmed absent process answers false.
726
715
  *
727
716
  * @param id - The process id a file's own revision names
728
717
  * @returns True if that process is running or cannot be judged; false otherwise
@@ -735,12 +724,7 @@ function matchesWorkspaceModule(path) {
735
724
  */
736
725
  function matchesLiveProcess(id) {
737
726
  if (!(0, _orkestrel_contract.isNumber)(id) || !Number.isSafeInteger(id) || id <= 0) return true;
738
- try {
739
- process.kill(id, 0);
740
- return true;
741
- } catch (error) {
742
- return readFaultCode(error) === "EPERM";
743
- }
727
+ return (0, _orkestrel_process_server.inspectProcess)(id) !== false;
744
728
  }
745
729
  /**
746
730
  * Collects every regular file a target workspace holds, skipping the trees no inspection reads.
@@ -768,10 +752,8 @@ function collectWorkspaceFiles(workspace) {
768
752
  while (directories.length > 0) {
769
753
  const directory = directories.pop();
770
754
  if (directory === void 0) break;
771
- let entries = [];
772
- try {
773
- entries = (0, node_fs.readdirSync)(directory, { withFileTypes: true });
774
- } catch {}
755
+ const reading = (0, _orkestrel_contract.attempt)(() => (0, node_fs.readdirSync)(directory, { withFileTypes: true }));
756
+ const entries = reading.success ? reading.value : [];
775
757
  for (const entry of entries) {
776
758
  if (entry.name === ".git" || entry.name === "dist" || entry.name === "node_modules") continue;
777
759
  const path = (0, node_path.join)(directory, entry.name);
@@ -860,17 +842,10 @@ async function guardStage(stage, operation) {
860
842
  */
861
843
  function findRefusedPaths(value) {
862
844
  if (!(0, _orkestrel_contract.compileGuard)(_src_core.CLAIM_SHAPE)(value)) return [];
863
- const members = [];
864
- for (const phase of ["case", "control"]) {
845
+ return ["case", "control"].flatMap((phase) => {
865
846
  const subject = value[phase];
866
- const drafts = /* @__PURE__ */ new Map([[`${phase}.test`, subject.test]]);
867
- for (const [index, file] of subject.files.entries()) drafts.set(`${phase}.files.${index}`, file);
868
- for (const [member, draft] of drafts) {
869
- if ((0, _src_core.isDraft)(draft)) continue;
870
- members.push(`${member}.path`);
871
- }
872
- }
873
- return members;
847
+ return [[`${phase}.test`, subject.test], ...Iterator.from(subject.files.entries()).map(([index, file]) => [`${phase}.files.${index}`, file])].flatMap(([member, draft]) => (0, _src_core.isDraft)(draft) ? [] : [`${member}.path`]);
848
+ });
874
849
  }
875
850
  /**
876
851
  * Rewrites every workspace-contained absolute path in a value to its workspace-relative form and
@@ -882,7 +857,8 @@ function findRefusedPaths(value) {
882
857
  * its relative form keeps one commit checked out at two roots reading to one digest. A path that
883
858
  * escapes the workspace is left as it stands, because rewriting it would name a file outside the
884
859
  * tree by a relative spelling. Key order is the compiler's own and it differs between the supported
885
- * majors, so sorting removes a difference that means nothing.
860
+ * majors, so sorting removes a difference that means nothing. A `__proto__` key is dropped, as
861
+ * the earlier assignment-built record dropped it, so a digest stays the same across releases.
886
862
  *
887
863
  * @param workspace - The target workspace root
888
864
  * @param value - The value to rewrite
@@ -904,11 +880,7 @@ function normalizeValue(workspace, value) {
904
880
  return normalizePath(path);
905
881
  }
906
882
  if ((0, _orkestrel_contract.isArray)(value)) return value.map((entry) => normalizeValue(workspace, entry));
907
- if ((0, _orkestrel_contract.isRecord)(value)) {
908
- const record = {};
909
- for (const key of Object.keys(value).sort()) record[key] = normalizeValue(workspace, value[key]);
910
- return record;
911
- }
883
+ if ((0, _orkestrel_contract.isRecord)(value)) return Object.fromEntries(Object.keys(value).sort().filter((key) => key !== "__proto__").map((key) => [key, normalizeValue(workspace, value[key])]));
912
884
  return value;
913
885
  }
914
886
  /**
@@ -925,10 +897,10 @@ function normalizeValue(workspace, value) {
925
897
  *
926
898
  * @example
927
899
  * ```ts
928
- * computeDigest('/srv/checkout', { strict: true }).length // 32
900
+ * computeWorkspaceDigest('/srv/checkout', { strict: true }).length // 32
929
901
  * ```
930
902
  */
931
- function computeDigest(workspace, value) {
903
+ function computeWorkspaceDigest(workspace, value) {
932
904
  return (0, node_crypto.createHash)("sha256").update(JSON.stringify(normalizeValue(workspace, value))).digest("hex").slice(0, 32);
933
905
  }
934
906
  /**
@@ -945,9 +917,7 @@ function computeDigest(workspace, value) {
945
917
  * ```
946
918
  */
947
919
  function captureListeners(emitter, events) {
948
- const capture = /* @__PURE__ */ new Map();
949
- for (const event of events) capture.set(event, emitter.listeners(event));
950
- return capture;
920
+ return new Map(Iterator.from(events).map((event) => [event, emitter.listeners(event)]));
951
921
  }
952
922
  /**
953
923
  * Removes every listener one emitter gained for the captured events since its capture.
@@ -982,8 +952,7 @@ function releaseListeners(emitter, capture) {
982
952
  emitter.removeListener(event, listener);
983
953
  }
984
954
  }
985
- //#endregion
986
- //#region src/server/parsers.ts
955
+ // src/server/parsers.ts
987
956
  /**
988
957
  * Parses the configuration one compiler run printed for a TypeScript project.
989
958
  *
@@ -1038,8 +1007,7 @@ function parseRevisionOwner(revision) {
1038
1007
  const owner = /^(\d+)-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u.exec(revision)?.[1];
1039
1008
  return owner === void 0 ? void 0 : Number.parseInt(owner, 10);
1040
1009
  }
1041
- //#endregion
1042
- //#region src/server/Overlay.ts
1010
+ // src/server/Overlay.ts
1043
1011
  /**
1044
1012
  * Implements `OverlayInterface` over a private map from normalized absolute path to candidate text,
1045
1013
  * minting at construction the `revision` a resident tool caches its answers against.
@@ -1125,21 +1093,19 @@ var Overlay = class {
1125
1093
  this.#candidates.clear();
1126
1094
  }
1127
1095
  };
1128
- //#endregion
1129
- //#region package.json
1130
- var version = "0.0.25";
1096
+ // package.json
1097
+ var version = "0.0.27";
1131
1098
  var peerDependencies = {
1132
1099
  "typescript": "^6.0.3 || ^7.0.2",
1133
1100
  "vitest": "^4.1.12 || ^5.0.5"
1134
1101
  };
1135
- //#endregion
1136
- //#region src/server/stages/LintStage.ts
1102
+ // src/server/stages/LintStage.ts
1137
1103
  /**
1138
1104
  * Inspects virtual documents through one resident Oxlint language server.
1139
1105
  *
1140
1106
  * @remarks
1141
1107
  * Starting launches the target workspace's Oxlint binary with its Language Server Protocol mode
1142
- * and hands the conversation to `@orkestrel/lsp`: `createStdioClientTransport` owns the child
1108
+ * and hands the conversation to `@orkestrel/lsp`: `createLSPStdioTransport` owns the child
1143
1109
  * process and its bytes, and `createLSPClient` owns the framing, the request correlation, the
1144
1110
  * capabilities this stage advertises, and the choice between pulled and pushed diagnostics. This
1145
1111
  * stage owns the workspace, the candidate identity, and the projection from a diagnostic to an
@@ -1167,7 +1133,7 @@ var peerDependencies = {
1167
1133
  * @example
1168
1134
  * ```ts
1169
1135
  * const stage = new LintStage('/srv/checkout')
1170
- * const check = await stage.inspect(subject, { signal: AbortSignal.timeout(30_000) })
1136
+ * const result = await stage.inspect(subject, { signal: AbortSignal.timeout(30_000) })
1171
1137
  * await stage.destroy()
1172
1138
  * ```
1173
1139
  */
@@ -1240,7 +1206,7 @@ var LintStage = class {
1240
1206
  }
1241
1207
  async #warm() {
1242
1208
  const binary = resolveWorkspaceBinary(this.#workspace, "oxlint");
1243
- const transport = (0, _orkestrel_lsp_server.createStdioClientTransport)({
1209
+ const transport = (0, _orkestrel_lsp_server.createLSPStdioTransport)({
1244
1210
  server: {
1245
1211
  command: [
1246
1212
  process.execPath,
@@ -1346,8 +1312,7 @@ var LintStage = class {
1346
1312
  }));
1347
1313
  }
1348
1314
  };
1349
- //#endregion
1350
- //#region src/server/stages/RuntimeStage.ts
1315
+ // src/server/stages/RuntimeStage.ts
1351
1316
  /**
1352
1317
  * Inspects tests through one resident Vitest service from the target workspace.
1353
1318
  *
@@ -1409,7 +1374,7 @@ var LintStage = class {
1409
1374
  * @example
1410
1375
  * ```ts
1411
1376
  * const stage = new RuntimeStage('/srv/checkout')
1412
- * const check = await stage.inspect(subject)
1377
+ * const result = await stage.inspect(subject)
1413
1378
  * await stage.destroy()
1414
1379
  * ```
1415
1380
  */
@@ -1510,14 +1475,13 @@ var RuntimeStage = class {
1510
1475
  const file = node_path.sep === "\\" ? normalizePath(specification) : specification;
1511
1476
  this.#specifications += 1;
1512
1477
  this.#revisions.add(file);
1513
- let issues = [];
1514
- let cleanup = [];
1478
+ const issues = [];
1515
1479
  const task = project.createSpecification(file, void 0, "threads");
1516
1480
  this.#progress += 1;
1517
1481
  try {
1518
1482
  try {
1519
1483
  const result = await vitest.runTestSpecifications([task], false);
1520
- issues = [...this.#issues(result, file, subject.test.path), ...this.#misses(project, file)];
1484
+ issues.push(...this.#issues(result, file, subject.test.path), ...this.#misses(project, file));
1521
1485
  } catch (error) {
1522
1486
  if ((0, _src_core.isProbeError)(error)) throw error;
1523
1487
  throw new _src_core.ProbeError(`The runtime stage could not run the generated specification (${describeUnknown(error)})`, {
@@ -1534,22 +1498,22 @@ var RuntimeStage = class {
1534
1498
  this.#progress -= 1;
1535
1499
  process.exitCode = exitCode;
1536
1500
  this.#revisions.delete(file);
1537
- cleanup = await this.#evict(vitest, file);
1501
+ issues.push(...await this.#evict(vitest, file));
1538
1502
  try {
1539
1503
  const contained = resolveWorkspaceFile(this.#workspace, (0, node_path.relative)(this.#workspace, file), true);
1540
1504
  if ((0, node_fs.existsSync)(contained)) (0, node_fs.unlinkSync)(contained);
1541
1505
  } catch (error) {
1542
- cleanup = [...cleanup, {
1506
+ issues.push({
1543
1507
  origin: (0, _src_core.isProbeError)(error) && error.origin === "workspace" ? "workspace" : "instrument",
1544
1508
  path: relativeWorkspaceFile(this.#workspace, file),
1545
1509
  message: `The runtime stage could not delete the generated specification (${describeUnknown(error)})`
1546
- }];
1510
+ });
1547
1511
  }
1548
1512
  }
1549
1513
  return {
1550
1514
  stage: this.stage,
1551
1515
  elapsed: Math.round(performance.now() - started),
1552
- issues: [...issues, ...cleanup]
1516
+ issues
1553
1517
  };
1554
1518
  } finally {
1555
1519
  this.#loads.clear();
@@ -1676,47 +1640,52 @@ var RuntimeStage = class {
1676
1640
  return text;
1677
1641
  }
1678
1642
  #specification(test) {
1679
- let creating = false;
1680
- let generated;
1681
- const outcome = (0, _orkestrel_contract.attempt)(() => {
1643
+ const location = (0, _orkestrel_contract.attempt)(() => {
1682
1644
  const revision = `${process.pid}-${(0, node_crypto.randomUUID)()}`;
1683
- const file = buildRevisionPath(this.#workspace, test.path, revision);
1684
- generated = file;
1685
- const target = (0, node_path.relative)(this.#workspace, file);
1686
- resolveWorkspaceFile(this.#workspace, target, true);
1687
- creating = true;
1688
- (0, node_fs.mkdirSync)((0, node_path.dirname)(file), { recursive: true });
1689
- creating = false;
1645
+ return {
1646
+ revision,
1647
+ file: buildRevisionPath(this.#workspace, test.path, revision)
1648
+ };
1649
+ });
1650
+ if (!location.success) return this.#specificationFault(test, location.error);
1651
+ const { revision, file } = location.value;
1652
+ const target = (0, node_path.relative)(this.#workspace, file);
1653
+ const containment = (0, _orkestrel_contract.attempt)(() => resolveWorkspaceFile(this.#workspace, target, true));
1654
+ if (!containment.success) return this.#specificationFault(test, containment.error, file);
1655
+ const directory = (0, _orkestrel_contract.attempt)(() => (0, node_fs.mkdirSync)((0, node_path.dirname)(file), { recursive: true }));
1656
+ if (!directory.success) return this.#specificationFault(test, directory.error, file, true);
1657
+ const written = (0, _orkestrel_contract.attempt)(() => {
1690
1658
  resolveWorkspaceFile(this.#workspace, target, true);
1691
1659
  (0, node_fs.writeFileSync)(file, (0, _src_core.formatSpecification)(test.text, revision), {
1692
1660
  encoding: "utf8",
1693
1661
  flag: "wx"
1694
1662
  });
1695
- return file;
1696
1663
  });
1697
- if (outcome.success) return outcome.value;
1698
- if ((0, _src_core.isProbeError)(outcome.error) && outcome.error.origin === "claimant") throw new _src_core.ProbeError(outcome.error.message, {
1699
- origin: outcome.error.origin,
1700
- code: outcome.error.code,
1664
+ return written.success ? file : this.#specificationFault(test, written.error, file);
1665
+ }
1666
+ #specificationFault(test, error, generated, directory = false) {
1667
+ if ((0, _src_core.isProbeError)(error) && error.origin === "claimant") throw new _src_core.ProbeError(error.message, {
1668
+ origin: error.origin,
1669
+ code: error.code,
1701
1670
  context: {
1702
- ...outcome.error.context,
1671
+ ...error.context,
1703
1672
  path: test.path
1704
1673
  },
1705
- cause: outcome.error.cause
1674
+ cause: error.cause
1706
1675
  });
1707
- if (!creating && generated !== void 0 && isRefusedName(generated, outcome.error)) throw new _src_core.ProbeError(`The runtime stage cannot write a specification beside a test path the host refuses (${describeUnknown(outcome.error)})`, {
1676
+ if (!directory && generated !== void 0 && isRefusedName(generated, error)) throw new _src_core.ProbeError(`The runtime stage cannot write a specification beside a test path the host refuses (${describeUnknown(error)})`, {
1708
1677
  origin: "claimant",
1709
1678
  code: "refused",
1710
1679
  context: {
1711
1680
  stage: this.stage,
1712
1681
  path: test.path
1713
1682
  },
1714
- cause: outcome.error
1683
+ cause: error
1715
1684
  });
1716
1685
  return {
1717
- origin: (0, _src_core.isProbeError)(outcome.error) && outcome.error.origin === "workspace" || creating ? "workspace" : "instrument",
1686
+ origin: (0, _src_core.isProbeError)(error) && error.origin === "workspace" || directory ? "workspace" : "instrument",
1718
1687
  path: test.path,
1719
- message: `The runtime stage could not write the generated specification (${describeUnknown(outcome.error)})`
1688
+ message: `The runtime stage could not write the generated specification (${describeUnknown(error)})`
1720
1689
  };
1721
1690
  }
1722
1691
  #project(vitest, path) {
@@ -1747,44 +1716,35 @@ var RuntimeStage = class {
1747
1716
  }
1748
1717
  #misses(project, specification) {
1749
1718
  const file = normalizePath(specification);
1750
- const issues = [];
1751
- for (const path of this.#overlay.paths) {
1752
- if (this.#reads.has(path)) continue;
1753
- let served = false;
1754
- let loaded = false;
1755
- for (const environment of Object.values(project.vite.environments)) {
1719
+ return this.#overlay.paths.flatMap((path) => {
1720
+ if (this.#reads.has(path)) return [];
1721
+ const served = Object.values(project.vite.environments).flatMap((environment) => {
1756
1722
  const modules = environment.moduleGraph.getModulesByFile(path);
1757
- if (modules === void 0) continue;
1758
- for (const module of modules) {
1723
+ if (modules === void 0) return [];
1724
+ return Iterator.from(modules).flatMap((module) => {
1759
1725
  const pending = [...module.importers];
1760
1726
  const seen = new Set(pending);
1761
- let reaches = false;
1762
1727
  while (pending.length > 0) {
1763
1728
  const importer = pending.pop();
1764
1729
  if (importer === void 0) break;
1765
- if (importer.file !== null && normalizePath(importer.file) === file) {
1766
- reaches = true;
1767
- break;
1768
- }
1730
+ if (importer.file !== null && normalizePath(importer.file) === file) return [module.id !== null && this.#loads.has(normalizePath(module.id))];
1769
1731
  for (const parent of importer.importers) {
1770
1732
  if (seen.has(parent)) continue;
1771
1733
  seen.add(parent);
1772
1734
  pending.push(parent);
1773
1735
  }
1774
1736
  }
1775
- if (!reaches) continue;
1776
- served = true;
1777
- if (module.id !== null && this.#loads.has(normalizePath(module.id))) loaded = true;
1778
- }
1779
- }
1780
- if (!served) continue;
1781
- issues.push({
1737
+ return [];
1738
+ }).toArray();
1739
+ });
1740
+ if (served.length === 0) return [];
1741
+ const loaded = served.some((value) => value);
1742
+ return [{
1782
1743
  origin: loaded ? "instrument" : "workspace",
1783
1744
  path: relativeWorkspaceFile(this.#workspace, path),
1784
1745
  message: loaded ? "The runtime overlay did not resolve this module" : "The workspace configuration served this module before the runtime overlay"
1785
- });
1786
- }
1787
- return issues;
1746
+ }];
1747
+ });
1788
1748
  }
1789
1749
  async #evict(vitest, file) {
1790
1750
  try {
@@ -2026,8 +1986,7 @@ var RuntimeStage = class {
2026
1986
  };
2027
1987
  }
2028
1988
  };
2029
- //#endregion
2030
- //#region src/server/stages/TypeStage.ts
1989
+ // src/server/stages/TypeStage.ts
2031
1990
  /**
2032
1991
  * Inspects TypeScript source by running the target workspace's own compiler over a mirror of it.
2033
1992
  *
@@ -2061,7 +2020,7 @@ var RuntimeStage = class {
2061
2020
  * @example
2062
2021
  * ```ts
2063
2022
  * const stage = new TypeStage('/srv/checkout')
2064
- * const check = await stage.inspect(subject, 'configs/src/tsconfig.core.json')
2023
+ * const result = await stage.inspect(subject, 'configs/src/tsconfig.core.json')
2065
2024
  * await stage.destroy()
2066
2025
  * ```
2067
2026
  */
@@ -2136,6 +2095,14 @@ var TypeStage = class {
2136
2095
  resolve(project) {
2137
2096
  return guardStage(this.stage, this.#resolve(project));
2138
2097
  }
2098
+ /**
2099
+ * Tears down the compiler processes and releases the mirror without awaiting inspections.
2100
+ *
2101
+ * @remarks
2102
+ * On Windows, awaits each tree termination attempt before removing the mirror. Each attempt
2103
+ * uses `PROBE_DEADLINE`, the existing default inspection budget, as its utility timeout.
2104
+ * On POSIX, sends `SIGTERM` to each compiler. Warming settles before the mirror is removed.
2105
+ */
2139
2106
  destroy() {
2140
2107
  if (this.#closing !== void 0) return this.#closing;
2141
2108
  this.#closing = guardStage(this.stage, this.#destroy());
@@ -2192,13 +2159,13 @@ var TypeStage = class {
2192
2159
  }
2193
2160
  return {
2194
2161
  path: contained,
2195
- digest: computeDigest(this.#workspace, config.compilerOptions)
2162
+ digest: computeWorkspaceDigest(this.#workspace, config.compilerOptions)
2196
2163
  };
2197
2164
  }
2198
2165
  async #destroy() {
2199
2166
  const children = [...this.#children];
2200
2167
  this.#children.clear();
2201
- for (const child of children) this.#terminate(child);
2168
+ await Promise.all(children.map((child) => this.#terminate(child)));
2202
2169
  await this.#warming?.catch(() => void 0);
2203
2170
  try {
2204
2171
  (0, node_fs.rmSync)(this.#mirror, {
@@ -2222,18 +2189,11 @@ var TypeStage = class {
2222
2189
  await Promise.all(this.#projects().map((project) => this.#check(project, [])));
2223
2190
  }
2224
2191
  #projects() {
2225
- const projects = ["tsconfig.json"];
2226
- for (const axis of ["src", "app"]) {
2192
+ return ["tsconfig.json", ...["src", "app"].flatMap((axis) => {
2227
2193
  const directory = resolveWorkspaceFile(this.#workspace, `configs/${axis}`);
2228
- let names;
2229
- try {
2230
- names = (0, node_fs.readdirSync)(directory);
2231
- } catch {
2232
- continue;
2233
- }
2234
- for (const name of names.filter((entry) => /^tsconfig\.[^.]+\.json$/.test(entry)).sort()) projects.push(`configs/${axis}/${name}`);
2235
- }
2236
- return projects;
2194
+ const reading = (0, _orkestrel_contract.attempt)(() => (0, node_fs.readdirSync)(directory));
2195
+ return reading.success ? reading.value.filter((entry) => /^tsconfig\.[^.]+\.json$/.test(entry)).sort().map((name) => `configs/${axis}/${name}`) : [];
2196
+ })];
2237
2197
  }
2238
2198
  #refuseDestroyed() {
2239
2199
  if (this.#closing !== void 0) throw (0, _src_core.createDestroyedError)("type stage");
@@ -2248,13 +2208,9 @@ var TypeStage = class {
2248
2208
  }
2249
2209
  #sweep() {
2250
2210
  const root = resolveWorkspaceFile(this.#workspace, _src_core.TYPE_MIRROR);
2251
- let entries = [];
2252
- try {
2253
- entries = (0, node_fs.readdirSync)(root, { withFileTypes: true });
2254
- } catch {
2255
- return;
2256
- }
2257
- for (const entry of entries) {
2211
+ const reading = (0, _orkestrel_contract.attempt)(() => (0, node_fs.readdirSync)(root, { withFileTypes: true }));
2212
+ if (!reading.success) return;
2213
+ for (const entry of reading.value) {
2258
2214
  if (!entry.isDirectory()) continue;
2259
2215
  const owner = parseRevisionOwner(entry.name);
2260
2216
  if (owner === void 0 || matchesLiveProcess(owner)) continue;
@@ -2308,12 +2264,7 @@ var TypeStage = class {
2308
2264
  return contained;
2309
2265
  }
2310
2266
  #displace(target) {
2311
- const ancestors = [];
2312
- let directory = (0, node_path.dirname)(target);
2313
- while (directory !== this.#mirror && directory !== (0, node_path.dirname)(directory)) {
2314
- ancestors.unshift(directory);
2315
- directory = (0, node_path.dirname)(directory);
2316
- }
2267
+ const ancestors = (0, node_path.relative)(this.#mirror, target).split(node_path.sep).slice(0, -1).map((_segment, index, segments) => (0, node_path.join)(this.#mirror, ...segments.slice(0, index + 1)));
2317
2268
  for (const ancestor of [...ancestors, target]) {
2318
2269
  const reading = (0, _orkestrel_contract.attempt)(() => (0, node_fs.lstatSync)(ancestor));
2319
2270
  if (!reading.success) continue;
@@ -2449,40 +2400,43 @@ var TypeStage = class {
2449
2400
  }
2450
2401
  });
2451
2402
  }
2452
- #spawn(args, cwd) {
2403
+ async #spawn(args, cwd) {
2453
2404
  this.#refuseDestroyed();
2454
2405
  const compiler = this.#compiler;
2455
2406
  if (compiler === void 0) throw (0, _src_core.createDestroyedError)("type stage");
2456
- return new Promise((settle, refuse) => {
2457
- const child = (0, node_child_process.spawn)(process.execPath, [compiler, ...args], {
2458
- cwd,
2459
- stdio: [
2460
- "ignore",
2461
- "pipe",
2462
- "pipe"
2463
- ]
2464
- });
2465
- const output = child.stdout;
2466
- const errors = child.stderr;
2467
- if (output === null || errors === null) {
2468
- this.#terminate(child);
2469
- refuse(new _src_core.ProbeError("The compiler was spawned without its own output streams", {
2470
- origin: "instrument",
2471
- code: "malformed",
2472
- context: { stage: this.stage }
2473
- }));
2474
- return;
2407
+ const child = (0, node_child_process.spawn)(process.execPath, [compiler, ...args], {
2408
+ cwd,
2409
+ stdio: [
2410
+ "ignore",
2411
+ "pipe",
2412
+ "pipe"
2413
+ ]
2414
+ });
2415
+ this.#children.add(child);
2416
+ const output = child.stdout;
2417
+ const errors = child.stderr;
2418
+ if (output === null || errors === null) {
2419
+ try {
2420
+ await this.#terminate(child);
2421
+ } finally {
2422
+ this.#children.delete(child);
2475
2423
  }
2476
- this.#children.add(child);
2477
- let stdout = "";
2478
- let stderr = "";
2424
+ throw new _src_core.ProbeError("The compiler was spawned without its own output streams", {
2425
+ origin: "instrument",
2426
+ code: "malformed",
2427
+ context: { stage: this.stage }
2428
+ });
2429
+ }
2430
+ return new Promise((settle, refuse) => {
2431
+ const stdout = [];
2432
+ const stderr = [];
2479
2433
  output.setEncoding("utf8");
2480
2434
  errors.setEncoding("utf8");
2481
2435
  output.on("data", (chunk) => {
2482
- stdout += chunk;
2436
+ stdout.push(chunk);
2483
2437
  });
2484
2438
  errors.on("data", (chunk) => {
2485
- stderr += chunk;
2439
+ stderr.push(chunk);
2486
2440
  });
2487
2441
  child.on("error", (error) => {
2488
2442
  this.#children.delete(child);
@@ -2500,28 +2454,22 @@ var TypeStage = class {
2500
2454
  this.#children.delete(child);
2501
2455
  settle({
2502
2456
  ...code === null ? {} : { status: code },
2503
- stdout,
2504
- stderr
2457
+ stdout: stdout.join(""),
2458
+ stderr: stderr.join("")
2505
2459
  });
2506
2460
  });
2507
2461
  });
2508
2462
  }
2509
- #terminate(child) {
2463
+ async #terminate(child) {
2510
2464
  const id = child.pid;
2511
2465
  if (process.platform === "win32" && id !== void 0) {
2512
- (0, node_child_process.spawnSync)("taskkill", [
2513
- "/pid",
2514
- String(id),
2515
- "/t",
2516
- "/f"
2517
- ], { stdio: "ignore" });
2466
+ await (0, _orkestrel_process_server.killTree)(id, _src_core.PROBE_DEADLINE);
2518
2467
  return;
2519
2468
  }
2520
2469
  child.kill("SIGTERM");
2521
2470
  }
2522
2471
  };
2523
- //#endregion
2524
- //#region src/server/Probe.ts
2472
+ // src/server/Probe.ts
2525
2473
  /**
2526
2474
  * Answers claims through its type, lint, and runtime stages.
2527
2475
  *
@@ -2662,7 +2610,7 @@ var Probe = class {
2662
2610
  const started = performance.now();
2663
2611
  const id = (0, node_crypto.randomUUID)();
2664
2612
  const project = await this.#resolve(claim);
2665
- const digest = computeDigest(this.#workspace, {
2613
+ const digest = computeWorkspaceDigest(this.#workspace, {
2666
2614
  case: claim.case,
2667
2615
  control: claim.control
2668
2616
  });
@@ -2711,11 +2659,12 @@ var Probe = class {
2711
2659
  return this.#starting;
2712
2660
  }
2713
2661
  async #start(filling, warming) {
2714
- let created = false;
2715
- try {
2662
+ const preparation = (0, _orkestrel_contract.attempt)(() => {
2716
2663
  this.#support();
2717
- if (this.#arming === void 0) created = this.#workbench();
2718
- } catch (error) {
2664
+ return this.#arming === void 0 && this.#workbench();
2665
+ });
2666
+ if (!preparation.success) {
2667
+ const error = preparation.error;
2719
2668
  this.#surface(error);
2720
2669
  throw error;
2721
2670
  }
@@ -2726,7 +2675,7 @@ var Probe = class {
2726
2675
  throw this.#refuseArm(error);
2727
2676
  }
2728
2677
  if (this.#arming === void 0) {
2729
- this.#arming = this.#arm(warming, created);
2678
+ this.#arming = this.#arm(warming, preparation.value);
2730
2679
  this.#arming.catch(() => {
2731
2680
  if (this.#refusal === void 0) this.#arming = void 0;
2732
2681
  });
@@ -2825,21 +2774,21 @@ var Probe = class {
2825
2774
  const beforeType = await this.#inspect(typeClaim.case, typeClaim);
2826
2775
  const beforeRuntime = await this.#inspect(runtimeClaim.case, runtimeClaim);
2827
2776
  const before = [...beforeType, ...beforeRuntime];
2828
- if (before.some((check) => check.issues.length > 0)) throw new _src_core.ProbeError(`The probe boot control did not begin clean\n${before.map(_src_core.formatCheck).join("\n")}`, {
2777
+ if (before.some((result) => result.issues.length > 0)) throw new _src_core.ProbeError(`The probe boot control did not begin clean\n${before.map(_src_core.formatStageResult).join("\n")}`, {
2829
2778
  origin: "instrument",
2830
2779
  code: "malformed"
2831
2780
  });
2832
2781
  resolveWorkspaceFile(this.#workspace, (0, node_path.relative)(this.#workspace, typeDependency), true);
2833
2782
  overwriteFile(typeDependency, (0, _src_core.formatSpecification)("export type Signal = number\n", revision));
2834
2783
  const afterType = await this.#inspect(typeClaim.control, typeClaim);
2835
- const type = afterType.find((check) => check.stage === typeClaim.control.stage);
2836
- const tolerant = afterType.find((check) => check.stage === "runtime");
2837
- if (type === void 0 || type.issues.length === 0) throw new _src_core.ProbeError(`The probe boot type control did not detect a mutated dependency\n${afterType.map(_src_core.formatCheck).join("\n")}`, {
2784
+ const type = afterType.find((result) => result.stage === typeClaim.control.stage);
2785
+ const tolerant = afterType.find((result) => result.stage === "runtime");
2786
+ if (type === void 0 || type.issues.length === 0) throw new _src_core.ProbeError(`The probe boot type control did not detect a mutated dependency\n${afterType.map(_src_core.formatStageResult).join("\n")}`, {
2838
2787
  origin: "instrument",
2839
2788
  code: "malformed",
2840
2789
  context: { stage: typeClaim.control.stage }
2841
2790
  });
2842
- if (tolerant === void 0 || tolerant.issues.length > 0) throw new _src_core.ProbeError(`The probe boot type control did not remain runtime-clean\n${afterType.map(_src_core.formatCheck).join("\n")}`, {
2791
+ if (tolerant === void 0 || tolerant.issues.length > 0) throw new _src_core.ProbeError(`The probe boot type control did not remain runtime-clean\n${afterType.map(_src_core.formatStageResult).join("\n")}`, {
2843
2792
  origin: "instrument",
2844
2793
  code: "malformed",
2845
2794
  context: { stage: "runtime" }
@@ -2847,8 +2796,8 @@ var Probe = class {
2847
2796
  resolveWorkspaceFile(this.#workspace, (0, node_path.relative)(this.#workspace, runtimeDependency), true);
2848
2797
  overwriteFile(runtimeDependency, (0, _src_core.formatSpecification)("export const SIGNAL = 'after'\n", revision));
2849
2798
  const afterRuntime = await this.#inspect(runtimeClaim.control, runtimeClaim);
2850
- const runtime = afterRuntime.find((check) => check.stage === runtimeClaim.control.stage);
2851
- if (runtime === void 0 || runtime.issues.length === 0) throw new _src_core.ProbeError(`The probe boot runtime control did not detect a mutated dependency\n${afterRuntime.map(_src_core.formatCheck).join("\n")}`, {
2799
+ const runtime = afterRuntime.find((result) => result.stage === runtimeClaim.control.stage);
2800
+ if (runtime === void 0 || runtime.issues.length === 0) throw new _src_core.ProbeError(`The probe boot runtime control did not detect a mutated dependency\n${afterRuntime.map(_src_core.formatStageResult).join("\n")}`, {
2852
2801
  origin: "instrument",
2853
2802
  code: "malformed",
2854
2803
  context: { stage: runtimeClaim.control.stage }
@@ -3064,8 +3013,7 @@ var Probe = class {
3064
3013
  });
3065
3014
  }
3066
3015
  };
3067
- //#endregion
3068
- //#region src/server/ProbeServer.ts
3016
+ // src/server/ProbeServer.ts
3069
3017
  /**
3070
3018
  * Implements `ProbeServerInterface` over a `PassThrough` stream this server owns, binding the
3071
3019
  * published `prove` tool and the dual-era dispatcher to this process's Model Context Protocol
@@ -3304,7 +3252,6 @@ var ProbeServer = class {
3304
3252
  ] : [rendered, minimal]).find((arm) => (0, _orkestrel_mcp.isBoundedJSON)(arm, bounds)) ?? minimal;
3305
3253
  }
3306
3254
  };
3307
- //#endregion
3308
3255
  exports.LintStage = LintStage;
3309
3256
  exports.Overlay = Overlay;
3310
3257
  exports.Probe = Probe;
@@ -3314,7 +3261,7 @@ exports.TypeStage = TypeStage;
3314
3261
  exports.buildRevisionPath = buildRevisionPath;
3315
3262
  exports.captureListeners = captureListeners;
3316
3263
  exports.collectWorkspaceFiles = collectWorkspaceFiles;
3317
- exports.computeDigest = computeDigest;
3264
+ exports.computeWorkspaceDigest = computeWorkspaceDigest;
3318
3265
  exports.createHandshakeError = createHandshakeError;
3319
3266
  exports.describeUnknown = describeUnknown;
3320
3267
  exports.escapesRoot = escapesRoot;