@orkestrel/probe 0.0.1 → 0.0.3
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/src/server/index.cjs +164 -60
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +43 -5
- package/dist/src/server/index.d.ts +43 -5
- package/dist/src/server/index.js +164 -61
- package/dist/src/server/index.js.map +1 -1
- package/package.json +13 -11
|
@@ -187,6 +187,43 @@ export declare interface Inspection {
|
|
|
187
187
|
readonly claim: Claim;
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Reports whether a fault means the host refuses the name a caller supplied for a file to create.
|
|
192
|
+
*
|
|
193
|
+
* @remarks
|
|
194
|
+
* A host reports one refusal with a code of its own and several unrelated conditions with one
|
|
195
|
+
* shared code, so the code alone does not separate a name the host will not accept from a file
|
|
196
|
+
* that is merely absent. `ENAMETOOLONG` names the refusal outright. `ERR_INVALID_ARG_VALUE` names
|
|
197
|
+
* every argument Node rejects, so it names the refusal only for a path carrying the NUL byte Node
|
|
198
|
+
* refuses; the same code arrives for a bad `flag` and a bad encoding, which say nothing about the
|
|
199
|
+
* name. An `ENOENT` raised while the parent stats as a directory names the refusal too, because an
|
|
200
|
+
* ordinary absent file beneath an existing directory would have been created instead; a Windows
|
|
201
|
+
* host reports an overlong component and a character its filesystem reserves that way. Measured on
|
|
202
|
+
* 2026-08-21 on Windows 11 with Node v24.18.1 over NTFS, `writeFileSync` reported `ENOENT` for a
|
|
203
|
+
* 300-character final component and never reported `ENAMETOOLONG`.
|
|
204
|
+
*
|
|
205
|
+
* This reads the fault the host reported rather than applying a length or character policy of its
|
|
206
|
+
* own, so a host that accepts a name another host refuses is not second-guessed and no platform
|
|
207
|
+
* branch decides the answer. Every read of the fault is guarded, so it is total over every value a
|
|
208
|
+
* published caller can supply: a proxy whose `has` trap throws, a value whose `code` getter throws,
|
|
209
|
+
* a fault carrying no code, and a parent this host cannot stat each report false.
|
|
210
|
+
*
|
|
211
|
+
* @param file - The path whose creation failed
|
|
212
|
+
* @param error - The fault the failed operation raised
|
|
213
|
+
* @returns True when the fault means the host refuses this name; false otherwise
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```ts
|
|
217
|
+
* try {
|
|
218
|
+
* writeFileSync('tmp/probe/greeting\0.test.ts', '')
|
|
219
|
+
* } catch (error) {
|
|
220
|
+
* isRefusedName('tmp/probe/greeting\0.test.ts', error) // true
|
|
221
|
+
* }
|
|
222
|
+
* isRefusedName('tmp/probe/greeting.test.ts', new Error('the runtime stage was destroyed')) // false
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
export declare function isRefusedName(file: string, error: unknown): boolean;
|
|
226
|
+
|
|
190
227
|
/**
|
|
191
228
|
* Inspects virtual documents through one resident Oxlint language server.
|
|
192
229
|
*
|
|
@@ -728,11 +765,12 @@ export declare function resolveWorkspaceModule(workspace: string, specifier: str
|
|
|
728
765
|
* as a path string, into which the stage can install no overlay, and a specification path that
|
|
729
766
|
* crosses a symbolic link, whose existing components this host cannot inspect, or whose directory
|
|
730
767
|
* the target tree blocks probe from creating. An `origin: 'instrument'` issue names this package's
|
|
731
|
-
* own machinery: a specification it could not write after its directory exists
|
|
732
|
-
* not run, evict, or delete, in each case for a
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
*
|
|
768
|
+
* own machinery: a specification it could not write after its directory exists and the host did not
|
|
769
|
+
* refuse the caller's own name, or one it could not run, evict, or delete, in each case for a
|
|
770
|
+
* reason the target tree does not own, and a run that reported no test. An unmapped caller test and
|
|
771
|
+
* a test whose named project is absent are claimant failures with `code: 'missing'`, and a declared
|
|
772
|
+
* test path the host refuses to create is a claimant failure with `code: 'refused'`. Each is thrown
|
|
773
|
+
* rather than reported, because a test that never ran is no evidence about the candidate.
|
|
736
774
|
*
|
|
737
775
|
* The write path's physical-containment guarantee covers the claim inputs and the target tree as
|
|
738
776
|
* inspected. A concurrent process that mutates a path component between the final inspection and
|
|
@@ -187,6 +187,43 @@ export declare interface Inspection {
|
|
|
187
187
|
readonly claim: Claim;
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Reports whether a fault means the host refuses the name a caller supplied for a file to create.
|
|
192
|
+
*
|
|
193
|
+
* @remarks
|
|
194
|
+
* A host reports one refusal with a code of its own and several unrelated conditions with one
|
|
195
|
+
* shared code, so the code alone does not separate a name the host will not accept from a file
|
|
196
|
+
* that is merely absent. `ENAMETOOLONG` names the refusal outright. `ERR_INVALID_ARG_VALUE` names
|
|
197
|
+
* every argument Node rejects, so it names the refusal only for a path carrying the NUL byte Node
|
|
198
|
+
* refuses; the same code arrives for a bad `flag` and a bad encoding, which say nothing about the
|
|
199
|
+
* name. An `ENOENT` raised while the parent stats as a directory names the refusal too, because an
|
|
200
|
+
* ordinary absent file beneath an existing directory would have been created instead; a Windows
|
|
201
|
+
* host reports an overlong component and a character its filesystem reserves that way. Measured on
|
|
202
|
+
* 2026-08-21 on Windows 11 with Node v24.18.1 over NTFS, `writeFileSync` reported `ENOENT` for a
|
|
203
|
+
* 300-character final component and never reported `ENAMETOOLONG`.
|
|
204
|
+
*
|
|
205
|
+
* This reads the fault the host reported rather than applying a length or character policy of its
|
|
206
|
+
* own, so a host that accepts a name another host refuses is not second-guessed and no platform
|
|
207
|
+
* branch decides the answer. Every read of the fault is guarded, so it is total over every value a
|
|
208
|
+
* published caller can supply: a proxy whose `has` trap throws, a value whose `code` getter throws,
|
|
209
|
+
* a fault carrying no code, and a parent this host cannot stat each report false.
|
|
210
|
+
*
|
|
211
|
+
* @param file - The path whose creation failed
|
|
212
|
+
* @param error - The fault the failed operation raised
|
|
213
|
+
* @returns True when the fault means the host refuses this name; false otherwise
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```ts
|
|
217
|
+
* try {
|
|
218
|
+
* writeFileSync('tmp/probe/greeting\0.test.ts', '')
|
|
219
|
+
* } catch (error) {
|
|
220
|
+
* isRefusedName('tmp/probe/greeting\0.test.ts', error) // true
|
|
221
|
+
* }
|
|
222
|
+
* isRefusedName('tmp/probe/greeting.test.ts', new Error('the runtime stage was destroyed')) // false
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
export declare function isRefusedName(file: string, error: unknown): boolean;
|
|
226
|
+
|
|
190
227
|
/**
|
|
191
228
|
* Inspects virtual documents through one resident Oxlint language server.
|
|
192
229
|
*
|
|
@@ -728,11 +765,12 @@ export declare function resolveWorkspaceModule(workspace: string, specifier: str
|
|
|
728
765
|
* as a path string, into which the stage can install no overlay, and a specification path that
|
|
729
766
|
* crosses a symbolic link, whose existing components this host cannot inspect, or whose directory
|
|
730
767
|
* the target tree blocks probe from creating. An `origin: 'instrument'` issue names this package's
|
|
731
|
-
* own machinery: a specification it could not write after its directory exists
|
|
732
|
-
* not run, evict, or delete, in each case for a
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
*
|
|
768
|
+
* own machinery: a specification it could not write after its directory exists and the host did not
|
|
769
|
+
* refuse the caller's own name, or one it could not run, evict, or delete, in each case for a
|
|
770
|
+
* reason the target tree does not own, and a run that reported no test. An unmapped caller test and
|
|
771
|
+
* a test whose named project is absent are claimant failures with `code: 'missing'`, and a declared
|
|
772
|
+
* test path the host refuses to create is a claimant failure with `code: 'refused'`. Each is thrown
|
|
773
|
+
* rather than reported, because a test that never ran is no evidence about the candidate.
|
|
736
774
|
*
|
|
737
775
|
* The write path's physical-containment guarantee covers the claim inputs and the target tree as
|
|
738
776
|
* inspected. A concurrent process that mutates a path component between the final inspection and
|
package/dist/src/server/index.js
CHANGED
|
@@ -106,6 +106,53 @@ function resolveWorkspaceFile(workspace, target, mutate = false) {
|
|
|
106
106
|
return file;
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
109
|
+
* Reports whether a fault means the host refuses the name a caller supplied for a file to create.
|
|
110
|
+
*
|
|
111
|
+
* @remarks
|
|
112
|
+
* A host reports one refusal with a code of its own and several unrelated conditions with one
|
|
113
|
+
* shared code, so the code alone does not separate a name the host will not accept from a file
|
|
114
|
+
* that is merely absent. `ENAMETOOLONG` names the refusal outright. `ERR_INVALID_ARG_VALUE` names
|
|
115
|
+
* every argument Node rejects, so it names the refusal only for a path carrying the NUL byte Node
|
|
116
|
+
* refuses; the same code arrives for a bad `flag` and a bad encoding, which say nothing about the
|
|
117
|
+
* name. An `ENOENT` raised while the parent stats as a directory names the refusal too, because an
|
|
118
|
+
* ordinary absent file beneath an existing directory would have been created instead; a Windows
|
|
119
|
+
* host reports an overlong component and a character its filesystem reserves that way. Measured on
|
|
120
|
+
* 2026-08-21 on Windows 11 with Node v24.18.1 over NTFS, `writeFileSync` reported `ENOENT` for a
|
|
121
|
+
* 300-character final component and never reported `ENAMETOOLONG`.
|
|
122
|
+
*
|
|
123
|
+
* This reads the fault the host reported rather than applying a length or character policy of its
|
|
124
|
+
* own, so a host that accepts a name another host refuses is not second-guessed and no platform
|
|
125
|
+
* branch decides the answer. Every read of the fault is guarded, so it is total over every value a
|
|
126
|
+
* published caller can supply: a proxy whose `has` trap throws, a value whose `code` getter throws,
|
|
127
|
+
* a fault carrying no code, and a parent this host cannot stat each report false.
|
|
128
|
+
*
|
|
129
|
+
* @param file - The path whose creation failed
|
|
130
|
+
* @param error - The fault the failed operation raised
|
|
131
|
+
* @returns True when the fault means the host refuses this name; false otherwise
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```ts
|
|
135
|
+
* try {
|
|
136
|
+
* writeFileSync('tmp/probe/greeting\0.test.ts', '')
|
|
137
|
+
* } catch (error) {
|
|
138
|
+
* isRefusedName('tmp/probe/greeting\0.test.ts', error) // true
|
|
139
|
+
* }
|
|
140
|
+
* isRefusedName('tmp/probe/greeting.test.ts', new Error('the runtime stage was destroyed')) // false
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
function isRefusedName(file, error) {
|
|
144
|
+
if (typeof error !== "object" || error === null) return false;
|
|
145
|
+
const fault = error;
|
|
146
|
+
const reading = attempt(() => "code" in fault ? fault.code : void 0);
|
|
147
|
+
if (!reading.success) return false;
|
|
148
|
+
const code = reading.value;
|
|
149
|
+
if (code === "ENAMETOOLONG") return true;
|
|
150
|
+
if (code === "ERR_INVALID_ARG_VALUE") return file.includes("\0");
|
|
151
|
+
if (code !== "ENOENT") return false;
|
|
152
|
+
const parent = attempt(() => statSync(dirname(file), { throwIfNoEntry: false }));
|
|
153
|
+
return parent.success && parent.value !== void 0 && parent.value.isDirectory();
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
109
156
|
* Projects an absolute tool path into the workspace-relative form issues expose.
|
|
110
157
|
*
|
|
111
158
|
* @param workspace - The target workspace root
|
|
@@ -638,11 +685,11 @@ var Overlay = class {
|
|
|
638
685
|
};
|
|
639
686
|
//#endregion
|
|
640
687
|
//#region package.json
|
|
641
|
-
var version = "0.0.
|
|
688
|
+
var version = "0.0.3";
|
|
642
689
|
var peerDependencies = {
|
|
643
|
-
"oxlint": "^1.
|
|
644
|
-
"typescript": "^6.0.
|
|
645
|
-
"vitest": "^4.1.
|
|
690
|
+
"oxlint": "^1.79.0",
|
|
691
|
+
"typescript": "^6.0.3",
|
|
692
|
+
"vitest": "^4.1.11"
|
|
646
693
|
};
|
|
647
694
|
//#endregion
|
|
648
695
|
//#region src/server/stages/LintStage.ts
|
|
@@ -1026,11 +1073,12 @@ var LintStage = class {
|
|
|
1026
1073
|
* as a path string, into which the stage can install no overlay, and a specification path that
|
|
1027
1074
|
* crosses a symbolic link, whose existing components this host cannot inspect, or whose directory
|
|
1028
1075
|
* the target tree blocks probe from creating. An `origin: 'instrument'` issue names this package's
|
|
1029
|
-
* own machinery: a specification it could not write after its directory exists
|
|
1030
|
-
* not run, evict, or delete, in each case for a
|
|
1031
|
-
*
|
|
1032
|
-
*
|
|
1033
|
-
*
|
|
1076
|
+
* own machinery: a specification it could not write after its directory exists and the host did not
|
|
1077
|
+
* refuse the caller's own name, or one it could not run, evict, or delete, in each case for a
|
|
1078
|
+
* reason the target tree does not own, and a run that reported no test. An unmapped caller test and
|
|
1079
|
+
* a test whose named project is absent are claimant failures with `code: 'missing'`, and a declared
|
|
1080
|
+
* test path the host refuses to create is a claimant failure with `code: 'refused'`. Each is thrown
|
|
1081
|
+
* rather than reported, because a test that never ran is no evidence about the candidate.
|
|
1034
1082
|
*
|
|
1035
1083
|
* The write path's physical-containment guarantee covers the claim inputs and the target tree as
|
|
1036
1084
|
* inspected. A concurrent process that mutates a path component between the final inspection and
|
|
@@ -1093,7 +1141,7 @@ var RuntimeStage = class {
|
|
|
1093
1141
|
elapsed: Math.round(performance.now() - started),
|
|
1094
1142
|
issues: [specification]
|
|
1095
1143
|
};
|
|
1096
|
-
const file = specification;
|
|
1144
|
+
const file = sep === "\\" ? normalizePath(specification) : specification;
|
|
1097
1145
|
this.#specifications += 1;
|
|
1098
1146
|
this.#revisions.add(file);
|
|
1099
1147
|
let issues = [];
|
|
@@ -1243,9 +1291,11 @@ var RuntimeStage = class {
|
|
|
1243
1291
|
}
|
|
1244
1292
|
#specification(test) {
|
|
1245
1293
|
let creating = false;
|
|
1294
|
+
let generated;
|
|
1246
1295
|
const outcome = attempt(() => {
|
|
1247
1296
|
const revision = `${process.pid}-${randomUUID()}`;
|
|
1248
1297
|
const file = createRevisionFile(this.#workspace, test.path, revision);
|
|
1298
|
+
generated = file;
|
|
1249
1299
|
const target = relative(this.#workspace, file);
|
|
1250
1300
|
resolveWorkspaceFile(this.#workspace, target, true);
|
|
1251
1301
|
creating = true;
|
|
@@ -1268,6 +1318,15 @@ var RuntimeStage = class {
|
|
|
1268
1318
|
},
|
|
1269
1319
|
cause: outcome.error.cause
|
|
1270
1320
|
});
|
|
1321
|
+
if (!creating && generated !== void 0 && isRefusedName(generated, outcome.error)) throw new ProbeError(`The runtime stage cannot write a specification beside a test path the host refuses (${describeUnknown(outcome.error)})`, {
|
|
1322
|
+
origin: "claimant",
|
|
1323
|
+
code: "refused",
|
|
1324
|
+
context: {
|
|
1325
|
+
stage: this.stage,
|
|
1326
|
+
path: test.path
|
|
1327
|
+
},
|
|
1328
|
+
cause: outcome.error
|
|
1329
|
+
});
|
|
1271
1330
|
return {
|
|
1272
1331
|
origin: outcome.error instanceof ProbeError && outcome.error.origin === "workspace" || creating ? "workspace" : "instrument",
|
|
1273
1332
|
path: test.path,
|
|
@@ -1366,8 +1425,9 @@ var RuntimeStage = class {
|
|
|
1366
1425
|
for (const [path, digest] of modules) this.#modules.set(path, digest);
|
|
1367
1426
|
}
|
|
1368
1427
|
#invalidate(vitest, path) {
|
|
1369
|
-
|
|
1370
|
-
vitest.
|
|
1428
|
+
const id = sep === "\\" ? normalizePath(path) : path;
|
|
1429
|
+
vitest.invalidateFile(id);
|
|
1430
|
+
vitest.watcher.invalidates.add(id);
|
|
1371
1431
|
}
|
|
1372
1432
|
#snapshot() {
|
|
1373
1433
|
const modules = /* @__PURE__ */ new Map();
|
|
@@ -1717,8 +1777,9 @@ var TypeStage = class {
|
|
|
1717
1777
|
const path = resolveWorkspaceFile(this.#workspace, project);
|
|
1718
1778
|
const existing = this.#services.get(path);
|
|
1719
1779
|
if (existing !== void 0) return existing;
|
|
1720
|
-
const
|
|
1721
|
-
|
|
1780
|
+
const spelling = normalizePath(path);
|
|
1781
|
+
const config = typescript.readConfigFile(spelling, typescript.sys.readFile);
|
|
1782
|
+
if (config.error !== void 0) throw new ProbeError(this.#translate(typescript, config.error.messageText, path), {
|
|
1722
1783
|
origin: "workspace",
|
|
1723
1784
|
code: "malformed",
|
|
1724
1785
|
context: {
|
|
@@ -1726,8 +1787,8 @@ var TypeStage = class {
|
|
|
1726
1787
|
project
|
|
1727
1788
|
}
|
|
1728
1789
|
});
|
|
1729
|
-
const parsed = typescript.parseJsonConfigFileContent(config.config, typescript.sys, dirname(
|
|
1730
|
-
if (parsed.errors.length > 0) throw new ProbeError(typescript
|
|
1790
|
+
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), {
|
|
1731
1792
|
origin: "workspace",
|
|
1732
1793
|
code: "malformed",
|
|
1733
1794
|
context: {
|
|
@@ -1737,25 +1798,56 @@ var TypeStage = class {
|
|
|
1737
1798
|
});
|
|
1738
1799
|
this.#options.set(path, parsed.options);
|
|
1739
1800
|
this.#files.set(path, parsed.fileNames);
|
|
1740
|
-
const
|
|
1741
|
-
getCompilationSettings:
|
|
1742
|
-
getScriptFileNames:
|
|
1743
|
-
getScriptVersion:
|
|
1744
|
-
getScriptSnapshot:
|
|
1745
|
-
getCurrentDirectory: ()
|
|
1746
|
-
getDefaultLibFileName: (
|
|
1747
|
-
fileExists:
|
|
1748
|
-
readFile:
|
|
1801
|
+
const host = {
|
|
1802
|
+
getCompilationSettings: this.#compilationSettings.bind(this, path),
|
|
1803
|
+
getScriptFileNames: this.#scriptFiles.bind(this, path),
|
|
1804
|
+
getScriptVersion: this.#version.bind(this),
|
|
1805
|
+
getScriptSnapshot: this.#snapshot.bind(this, typescript),
|
|
1806
|
+
getCurrentDirectory: this.#directory.bind(this),
|
|
1807
|
+
getDefaultLibFileName: this.#defaultLibrary.bind(this, typescript),
|
|
1808
|
+
fileExists: this.#fileExists.bind(this, typescript),
|
|
1809
|
+
readFile: this.#readFile.bind(this, typescript),
|
|
1749
1810
|
readDirectory: typescript.sys.readDirectory,
|
|
1750
|
-
directoryExists:
|
|
1811
|
+
directoryExists: this.#directoryExists.bind(this, typescript),
|
|
1751
1812
|
getDirectories: typescript.sys.getDirectories,
|
|
1752
|
-
useCaseSensitiveFileNames: (
|
|
1753
|
-
getNewLine: (
|
|
1754
|
-
}
|
|
1813
|
+
useCaseSensitiveFileNames: this.#caseSensitive.bind(this, typescript),
|
|
1814
|
+
getNewLine: this.#newline.bind(this, typescript)
|
|
1815
|
+
};
|
|
1816
|
+
const service = typescript.createLanguageService(host);
|
|
1755
1817
|
this.#services.set(path, service);
|
|
1756
1818
|
if (!this.#resident.has(path)) this.#recycle(path);
|
|
1757
1819
|
return service;
|
|
1758
1820
|
}
|
|
1821
|
+
#compilationSettings(path) {
|
|
1822
|
+
return this.#options.get(path) ?? {};
|
|
1823
|
+
}
|
|
1824
|
+
#scriptFiles(path) {
|
|
1825
|
+
return [...this.#files.get(path) ?? [], ...this.#overlay.paths];
|
|
1826
|
+
}
|
|
1827
|
+
#directory() {
|
|
1828
|
+
return this.#workspace;
|
|
1829
|
+
}
|
|
1830
|
+
#defaultLibrary(typescript, options) {
|
|
1831
|
+
return typescript.getDefaultLibFilePath(options);
|
|
1832
|
+
}
|
|
1833
|
+
#fileExists(typescript, file) {
|
|
1834
|
+
return this.#overlay.text(file) !== void 0 || typescript.sys.fileExists(file);
|
|
1835
|
+
}
|
|
1836
|
+
#readFile(typescript, file) {
|
|
1837
|
+
return this.#overlay.text(file) ?? typescript.sys.readFile(file);
|
|
1838
|
+
}
|
|
1839
|
+
#directoryExists(typescript, directory) {
|
|
1840
|
+
return typescript.sys.directoryExists(directory) || this.#overlay.covers(directory);
|
|
1841
|
+
}
|
|
1842
|
+
#caseSensitive(typescript) {
|
|
1843
|
+
return typescript.sys.useCaseSensitiveFileNames;
|
|
1844
|
+
}
|
|
1845
|
+
#newline(typescript) {
|
|
1846
|
+
return typescript.sys.newLine;
|
|
1847
|
+
}
|
|
1848
|
+
#translate(typescript, message, path) {
|
|
1849
|
+
return normalizePath(typescript.flattenDiagnosticMessageText(message, "\n")).replaceAll(normalizePath(path), relativeWorkspaceFile(this.#workspace, path));
|
|
1850
|
+
}
|
|
1759
1851
|
#configure(service, project) {
|
|
1760
1852
|
const path = resolveWorkspaceFile(this.#workspace, project);
|
|
1761
1853
|
if (this.#diagnostics.has(path)) return;
|
|
@@ -1882,17 +1974,17 @@ var Probe = class {
|
|
|
1882
1974
|
this.#typeQueue = createQueue({
|
|
1883
1975
|
concurrency: 1,
|
|
1884
1976
|
retries: 0,
|
|
1885
|
-
handler:
|
|
1977
|
+
handler: this.#inspectType.bind(this)
|
|
1886
1978
|
});
|
|
1887
1979
|
this.#lintQueue = createQueue({
|
|
1888
1980
|
concurrency: 1,
|
|
1889
1981
|
retries: 0,
|
|
1890
|
-
handler:
|
|
1982
|
+
handler: this.#inspectLint.bind(this)
|
|
1891
1983
|
});
|
|
1892
1984
|
this.#runtimeQueue = createQueue({
|
|
1893
1985
|
concurrency: 1,
|
|
1894
1986
|
retries: 0,
|
|
1895
|
-
handler:
|
|
1987
|
+
handler: this.#inspectRuntime.bind(this)
|
|
1896
1988
|
});
|
|
1897
1989
|
this.#arming = this.#arm();
|
|
1898
1990
|
this.#arming.catch(() => {});
|
|
@@ -2092,6 +2184,15 @@ var Probe = class {
|
|
|
2092
2184
|
for (const pending of admitted) pending.catch(() => {});
|
|
2093
2185
|
return Promise.all(admitted);
|
|
2094
2186
|
}
|
|
2187
|
+
#inspectType(inspection) {
|
|
2188
|
+
return this.#inspectStage(this.#type, this.#type.progress, this.#type.inspect(inspection.subject, inspection.claim.project), inspection.claim);
|
|
2189
|
+
}
|
|
2190
|
+
#inspectLint(inspection) {
|
|
2191
|
+
return this.#inspectStage(this.#lint, this.#lint.progress, this.#lint.inspect(inspection.subject), inspection.claim);
|
|
2192
|
+
}
|
|
2193
|
+
#inspectRuntime(inspection) {
|
|
2194
|
+
return this.#inspectStage(this.#runtime, this.#runtime.progress, this.#runtime.inspect(inspection.subject), inspection.claim);
|
|
2195
|
+
}
|
|
2095
2196
|
async #inspectStage(stage, progress, operation, claim) {
|
|
2096
2197
|
const timeout = createTimeout({ ms: this.#deadline });
|
|
2097
2198
|
timeout.start();
|
|
@@ -2276,19 +2377,9 @@ var ProbeServer = class {
|
|
|
2276
2377
|
const tools = createToolManager();
|
|
2277
2378
|
tools.add(createTool({
|
|
2278
2379
|
name: "prove",
|
|
2279
|
-
description: "
|
|
2380
|
+
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.",
|
|
2280
2381
|
parameters,
|
|
2281
|
-
execute:
|
|
2282
|
-
if (!isClaim(input)) {
|
|
2283
|
-
const refused = findRefusedPaths(input);
|
|
2284
|
-
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`, {
|
|
2285
|
-
origin: "claimant",
|
|
2286
|
-
code: "refused",
|
|
2287
|
-
context: { value: input }
|
|
2288
|
-
});
|
|
2289
|
-
}
|
|
2290
|
-
return this.#probe.prove(input);
|
|
2291
|
-
}
|
|
2382
|
+
execute: this.#prove.bind(this)
|
|
2292
2383
|
}));
|
|
2293
2384
|
return createMCPServer({
|
|
2294
2385
|
identity: {
|
|
@@ -2296,26 +2387,38 @@ var ProbeServer = class {
|
|
|
2296
2387
|
version
|
|
2297
2388
|
},
|
|
2298
2389
|
tools,
|
|
2299
|
-
execution:
|
|
2300
|
-
const result = await tools.execute(call);
|
|
2301
|
-
if (!result.success) return result;
|
|
2302
|
-
if (!isVerdict(result.value)) throw new ProbeError("The prove tool returned an invalid verdict", {
|
|
2303
|
-
origin: "instrument",
|
|
2304
|
-
code: "malformed",
|
|
2305
|
-
context: { value: result.value }
|
|
2306
|
-
});
|
|
2307
|
-
return {
|
|
2308
|
-
resultType: "complete",
|
|
2309
|
-
content: [{
|
|
2310
|
-
type: "text",
|
|
2311
|
-
text: formatVerdict(result.value)
|
|
2312
|
-
}]
|
|
2313
|
-
};
|
|
2314
|
-
}
|
|
2390
|
+
execution: this.#execute.bind(this)
|
|
2315
2391
|
});
|
|
2316
2392
|
}
|
|
2393
|
+
async #prove(input) {
|
|
2394
|
+
if (!isClaim(input)) {
|
|
2395
|
+
const refused = findRefusedPaths(input);
|
|
2396
|
+
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`, {
|
|
2397
|
+
origin: "claimant",
|
|
2398
|
+
code: "refused",
|
|
2399
|
+
context: { value: input }
|
|
2400
|
+
});
|
|
2401
|
+
}
|
|
2402
|
+
return this.#probe.prove(input);
|
|
2403
|
+
}
|
|
2404
|
+
async #execute(context) {
|
|
2405
|
+
const result = await context.tools.execute(context.call);
|
|
2406
|
+
if (!result.success) return result;
|
|
2407
|
+
if (!isVerdict(result.value)) throw new ProbeError("The prove tool returned an invalid verdict", {
|
|
2408
|
+
origin: "instrument",
|
|
2409
|
+
code: "malformed",
|
|
2410
|
+
context: { value: result.value }
|
|
2411
|
+
});
|
|
2412
|
+
return {
|
|
2413
|
+
resultType: "complete",
|
|
2414
|
+
content: [{
|
|
2415
|
+
type: "text",
|
|
2416
|
+
text: formatVerdict(result.value)
|
|
2417
|
+
}]
|
|
2418
|
+
};
|
|
2419
|
+
}
|
|
2317
2420
|
};
|
|
2318
2421
|
//#endregion
|
|
2319
|
-
export { LintStage, Overlay, Probe, ProbeServer, RuntimeStage, TypeStage, captureListeners, computeDigest, createRevisionFile, describeUnknown, findRefusedPaths, inferDocumentLanguage, inferTestProject, inferTypeProject, loadWorkspaceModule, matchesWorkspaceModule, normalizePath, normalizeValue, parseContentLength, readWorkspaceManifest, relativeWorkspaceFile, releaseListeners, resolveWorkspaceBinary, resolveWorkspaceFile, resolveWorkspaceModule };
|
|
2422
|
+
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 };
|
|
2320
2423
|
|
|
2321
2424
|
//# sourceMappingURL=index.js.map
|