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