@orkestrel/probe 0.0.11 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,22 +1,39 @@
1
- import { Case } from '@orkestrel/probe';
2
- import { Case as Case_2 } from '@orkestrel/probe';
3
- import { Check } from '@orkestrel/probe';
4
- import { Check as Check_2 } from '@orkestrel/probe';
5
- import { Claim } from '@orkestrel/probe';
6
- import { EmitterInterface } from '@orkestrel/emitter';
7
- import { EventEmitter } from 'node:events';
8
- import { ProbeEventMap } from '@orkestrel/probe';
9
- import { ProbeInterface } from '@orkestrel/probe';
10
- import { ProbeOptions } from '@orkestrel/probe';
11
- import { Project } from '@orkestrel/probe';
12
- import { Project as Project_2 } from '@orkestrel/probe';
13
- import { Stage } from '@orkestrel/probe';
14
- import { Stage as Stage_2 } from '@orkestrel/probe';
15
- import { Toolchain } from '@orkestrel/probe';
16
- import type * as TypeScript from 'typescript';
17
- import { Verdict } from '@orkestrel/probe';
1
+ import type { Case } from '@orkestrel/probe';
2
+ import type { Check } from '@orkestrel/probe';
3
+ import type { Claim } from '@orkestrel/probe';
4
+ import type { EmitterInterface } from '@orkestrel/emitter';
5
+ import type { EventEmitter } from 'node:events';
6
+ import type { Issue } from '@orkestrel/probe';
7
+ import type { LSPRange } from '@orkestrel/lsp';
8
+ import type { ProbeEventMap } from '@orkestrel/probe';
9
+ import type { ProbeInterface } from '@orkestrel/probe';
10
+ import type { ProbeOptions } from '@orkestrel/probe';
11
+ import type { Project } from '@orkestrel/probe';
12
+ import type { Stage } from '@orkestrel/probe';
13
+ import type { Toolchain } from '@orkestrel/probe';
14
+ import type { Verdict } from '@orkestrel/probe';
18
15
  import type * as VitestNode from 'vitest/node';
19
16
 
17
+ /**
18
+ * Builds the fresh sibling path a revision's file is written at, preserving the test's resolution
19
+ * directory.
20
+ *
21
+ * @param workspace - The target workspace root
22
+ * @param path - The workspace-relative test path
23
+ * @param revision - The fresh revision identity
24
+ * @returns The absolute sibling path
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * relativeWorkspaceFile(
29
+ * '/srv/checkout',
30
+ * buildRevisionPath('/srv/checkout', 'tmp/probe/greeting.test.ts', '4821-9f0c'),
31
+ * )
32
+ * // 'tmp/probe/greeting.test.probe-4821-9f0c.ts'
33
+ * ```
34
+ */
35
+ export declare function buildRevisionPath(workspace: string, path: string, revision: string): string;
36
+
20
37
  /**
21
38
  * Records the listeners one emitter carries for a set of events.
22
39
  *
@@ -32,6 +49,27 @@ import type * as VitestNode from 'vitest/node';
32
49
  */
33
50
  export declare function captureListeners(emitter: EventEmitter, events: readonly string[]): ListenerCapture;
34
51
 
52
+ /**
53
+ * Collects every regular file a target workspace holds, skipping the trees no inspection reads.
54
+ *
55
+ * @remarks
56
+ * Skips a directory named `.git`, `dist`, or `node_modules` at any depth, and the directory
57
+ * {@link TYPE_MIRROR} names, which would otherwise carry this package's own mirror into the walk. A
58
+ * directory this host cannot list is skipped rather than raised, so one unreadable directory in a
59
+ * consumer's tree is not a reason to refuse the whole walk. A symbolic link is not carried, whether
60
+ * it names a file or a directory, so a file reached only through one is absent from the result; a
61
+ * `Dirent` that is neither a directory nor a regular file is skipped the same way.
62
+ *
63
+ * @param workspace - The target workspace root
64
+ * @returns The absolute path of every regular file the walk found
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * collectWorkspaceFiles(process.cwd()).some((path) => path.endsWith('package.json')) // true
69
+ * ```
70
+ */
71
+ export declare function collectWorkspaceFiles(workspace: string): readonly string[];
72
+
35
73
  /**
36
74
  * Computes the canonical digest of one value as it stands in a target workspace.
37
75
  *
@@ -52,38 +90,115 @@ export declare function captureListeners(emitter: EventEmitter, events: readonly
52
90
  export declare function computeDigest(workspace: string, value: unknown): string;
53
91
 
54
92
  /**
55
- * Creates a fresh sibling identity while preserving a test's resolution directory.
93
+ * Normalizes a caught or foreign error into readable text.
56
94
  *
57
- * @param workspace - The target workspace root
58
- * @param path - The workspace-relative test path
59
- * @param revision - The fresh revision identity
60
- * @returns An absolute sibling file path
95
+ * @param value - The value to describe
96
+ * @returns Its message when present, or its string representation
61
97
  *
62
98
  * @example
63
99
  * ```ts
64
- * relativeWorkspaceFile(
65
- * '/srv/checkout',
66
- * createRevisionFile('/srv/checkout', 'tmp/probe/greeting.test.ts', '4821-9f0c'),
67
- * )
68
- * // 'tmp/probe/greeting.test.probe-4821-9f0c.ts'
100
+ * describeUnknown(new Error('The lint stage has been destroyed'))
101
+ * // 'The lint stage has been destroyed'
102
+ * describeUnknown(17) // '17'
69
103
  * ```
70
104
  */
71
- export declare function createRevisionFile(workspace: string, path: string, revision: string): string;
105
+ export declare function describeUnknown(value: unknown): string;
72
106
 
73
107
  /**
74
- * Normalizes a caught or foreign error into readable text.
108
+ * Carries one diagnostic line a compiler run reported, in this package's own coordinates.
75
109
  *
76
- * @param value - The value to describe
77
- * @returns Its message when present, or its string representation
110
+ * @remarks
111
+ * `path` and `range` are absent together, because a diagnostic the compiler reports about a
112
+ * project rather than about a file carries no location. `path` is spelled as the compiler printed
113
+ * it, relative to the directory the run started in. `range` holds the zero-based UTF-16 point the
114
+ * compiler reported: the plain-text output carries a start position and no extent, so `end` equals
115
+ * `start`. `message` is the diagnostic text, elaboration lines joined by newlines.
78
116
  *
79
117
  * @example
80
118
  * ```ts
81
- * describeUnknown(new Error('The lint stage has been destroyed'))
82
- * // 'The lint stage has been destroyed'
83
- * describeUnknown(17) // '17'
119
+ * const diagnostic: Diagnostic = {
120
+ * path: 'src/core/greeting.ts',
121
+ * range: { start: { line: 0, character: 13 }, end: { line: 0, character: 13 } },
122
+ * message: "Type 'string' is not assignable to type 'number'.",
123
+ * }
84
124
  * ```
85
125
  */
86
- export declare function describeUnknown(value: unknown): string;
126
+ export declare interface Diagnostic {
127
+ /** Names the file the compiler reported against, or is absent for a project diagnostic. */
128
+ readonly path?: string;
129
+ /** Holds the zero-based UTF-16 point the compiler reported, or is absent with `path`. */
130
+ readonly range?: LSPRange;
131
+ /** Holds the diagnostic text, with every elaboration line joined by a newline. */
132
+ readonly message: string;
133
+ }
134
+
135
+ /**
136
+ * Reports whether one path resolves outside the root it is read against.
137
+ *
138
+ * @remarks
139
+ * Containment decides which paths a claim may reach and which absolute paths a digest may rewrite,
140
+ * so one reading serves every site that asks the question. A target resolving to the root itself is
141
+ * contained, and each caller decides on its own what that empty relative path means for it.
142
+ *
143
+ * The test reads the relative path rather than a string prefix of the root, so a sibling directory
144
+ * whose name begins with the root's own text is outside rather than beneath it. An absolute
145
+ * relative path is the answer a host returns for two paths on different volumes, which no root
146
+ * contains.
147
+ *
148
+ * @param root - The root the target is read against
149
+ * @param target - The path to test, absolute or root-relative
150
+ * @returns True if the target resolves outside the root; false otherwise
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * escapesRoot('/srv/checkout', 'src/core/greeting.ts') // false
155
+ * escapesRoot('/srv/checkout', '../secrets.env') // true
156
+ * escapesRoot('/srv/checkout', '/srv/checkout-backup/secrets.env') // true
157
+ * ```
158
+ */
159
+ export declare function escapesRoot(root: string, target: string): boolean;
160
+
161
+ /**
162
+ * Carries what one spawned workspace command reported when it closed.
163
+ *
164
+ * @remarks
165
+ * `stdout` and `stderr` mirror the POSIX stream names the child wrote to. `status` is the exit
166
+ * code, and it is absent when a signal ended the child, which is what teardown does to a run it
167
+ * abandons. A compiler's exit code is not its verdict — the majors this package supports disagree
168
+ * on it — so read the diagnostics the streams carry rather than this number.
169
+ *
170
+ * @example
171
+ * ```ts
172
+ * const execution: Execution = { status: 0, stdout: '{}\n', stderr: '' }
173
+ * ```
174
+ */
175
+ export declare interface Execution {
176
+ /** Holds the exit code, or is absent when a signal ended the child. */
177
+ readonly status?: number;
178
+ /** Holds everything the child wrote to its standard output. */
179
+ readonly stdout: string;
180
+ /** Holds everything the child wrote to its standard error. */
181
+ readonly stderr: string;
182
+ }
183
+
184
+ /**
185
+ * Filters one issue list to the distinct issues it carries, in the order they arrived.
186
+ *
187
+ * @remarks
188
+ * A stage that reads one candidate through more than one tool run reports that candidate's
189
+ * diagnostic once per run. Two issues are the same issue when their party, path, message, and range
190
+ * all agree, because those are every value an issue carries.
191
+ *
192
+ * @param issues - The issues to filter
193
+ * @returns The distinct issues, in the order the list carried them
194
+ *
195
+ * @example
196
+ * ```ts
197
+ * const issue: Issue = { origin: 'claimant', path: 'src/core/greeting.ts', message: 'not assignable' }
198
+ * filterUniqueIssues([issue, { ...issue }]).length // 1
199
+ * ```
200
+ */
201
+ export declare function filterUniqueIssues(issues: readonly Issue[]): readonly Issue[];
87
202
 
88
203
  /**
89
204
  * Names every draft member of a claim-shaped value whose `path` this package's guard refuses.
@@ -118,9 +233,9 @@ export declare function describeUnknown(value: unknown): string;
118
233
  export declare function findRefusedPaths(value: unknown): readonly string[];
119
234
 
120
235
  /**
121
- * Guards one resident-stage operation with the stage failure contract.
236
+ * Guards one stage operation with the stage failure contract.
122
237
  *
123
- * @param stage - The resident stage serving the operation
238
+ * @param stage - The stage serving the operation
124
239
  * @param operation - The operation to settle
125
240
  * @returns The operation's fulfilled value
126
241
  * @throws The original `ProbeError`, or an instrument-owned malformed failure retaining the cause
@@ -196,9 +311,9 @@ export declare function inferTypeProject(path: string): string;
196
311
  * ```
197
312
  */
198
313
  export declare interface Inspection {
199
- /** The candidate drafts and test one stage inspects. */
314
+ /** Holds the candidate drafts and test one stage inspects. */
200
315
  readonly subject: Case;
201
- /** The claim the subject belongs to. */
316
+ /** Holds the claim the subject belongs to. */
202
317
  readonly claim: Claim;
203
318
  }
204
319
 
@@ -248,7 +363,7 @@ export declare interface InspectionOptions {
248
363
  *
249
364
  * @param file - The path whose creation failed
250
365
  * @param error - The fault the failed operation raised
251
- * @returns True when the fault means the host refuses this name; false otherwise
366
+ * @returns True if the fault means the host refuses this name; false otherwise
252
367
  *
253
368
  * @example
254
369
  * ```ts
@@ -307,9 +422,9 @@ export declare class LintStage implements LintStageInterface {
307
422
  * @param workspace - The target workspace root. Default: the current working directory
308
423
  */
309
424
  constructor(workspace?: string);
310
- get stage(): Stage_2;
425
+ get stage(): Stage;
311
426
  get progress(): number;
312
- inspect(subject: Case_2, options?: InspectionOptions): Promise<Check_2>;
427
+ inspect(subject: Case, options?: InspectionOptions): Promise<Check>;
313
428
  destroy(): Promise<void>;
314
429
  }
315
430
 
@@ -341,6 +456,11 @@ export declare interface LintStageInterface extends StageInterface {
341
456
  * @returns One outcome for this stage
342
457
  * @throws When the caller supplies no bound, when the resident language server cannot start, or
343
458
  * when the stage has already been destroyed
459
+ *
460
+ * @example
461
+ * ```ts
462
+ * const check = await stage.inspect(subject, { signal: AbortSignal.timeout(30_000) })
463
+ * ```
344
464
  */
345
465
  inspect(subject: Case, options?: InspectionOptions): Promise<Check>;
346
466
  }
@@ -365,28 +485,50 @@ export declare interface LintStageInterface extends StageInterface {
365
485
  export declare type ListenerCapture = ReadonlyMap<string, readonly Function[]>;
366
486
 
367
487
  /**
368
- * Loads one installed tool module from a target workspace.
488
+ * Loads the installed `vitest/node` module from a target workspace.
489
+ *
490
+ * @remarks
491
+ * The only tool this package drives in process. The compiler is a process this package spawns
492
+ * rather than a module it loads, so `typescript` is resolved through {@link resolveWorkspaceBinary}
493
+ * instead.
369
494
  *
370
495
  * @param workspace - The target workspace root
371
- * @param specifier - The module specifier to load
372
- * @returns The installed module
373
- * @throws When the workspace cannot load the module
496
+ * @returns The installed `vitest/node` module
497
+ * @throws When the workspace cannot load `vitest/node`
374
498
  *
375
499
  * @example
376
500
  * ```ts
377
- * const typescript = loadWorkspaceModule(process.cwd(), 'typescript')
378
- * console.log(typescript.version)
501
+ * const vitest = loadWorkspaceVitest(process.cwd())
502
+ * typeof vitest.createVitest === 'function' // true
379
503
  * ```
380
504
  */
381
- export declare function loadWorkspaceModule(workspace: string, specifier: 'typescript'): typeof TypeScript;
505
+ export declare function loadWorkspaceVitest(workspace: string): typeof VitestNode;
382
506
 
383
- export declare function loadWorkspaceModule(workspace: string, specifier: 'vitest/node'): typeof VitestNode;
507
+ /**
508
+ * Reports whether the host that wrote one file is still running.
509
+ *
510
+ * @remarks
511
+ * Signal 0 delivers nothing and reports reachability alone. A process this one may not signal
512
+ * reports `EPERM` and reads as running, and a non-positive identity names a process group rather
513
+ * than a process, so both answer true: the safe direction is to keep a file this package cannot
514
+ * account for.
515
+ *
516
+ * @param id - The process id a file's own revision names
517
+ * @returns True if that process is running or cannot be judged; false otherwise
518
+ *
519
+ * @example
520
+ * ```ts
521
+ * matchesLiveProcess(process.pid) // true
522
+ * matchesLiveProcess(0) // true
523
+ * ```
524
+ */
525
+ export declare function matchesLiveProcess(id: number): boolean;
384
526
 
385
527
  /**
386
528
  * Reports whether a path is a workspace module Vitest can cache.
387
529
  *
388
530
  * @param path - The candidate file path
389
- * @returns True for script, TypeScript, Vue, and JSON modules; false otherwise
531
+ * @returns True if the path is a script, TypeScript, Vue, or JSON module; false otherwise
390
532
  *
391
533
  * @example
392
534
  * ```ts
@@ -420,12 +562,12 @@ export declare function normalizePath(path: string): string;
420
562
  * sorts every record's keys.
421
563
  *
422
564
  * @remarks
423
- * A parsed TypeScript project carries the absolute root it was parsed at, so the same commit
424
- * checked out at two paths produces two values that describe one configuration. Rewriting those
425
- * members makes the value portable and stops a host path leaking into anything derived from it. A
426
- * path that escapes the workspace is left as it stands, because rewriting it would name a file
427
- * outside the tree by a relative spelling. Key order is the parser's, not the configuration's, so
428
- * sorting removes a difference that means nothing.
565
+ * `tsc --showConfig` spells a path relative to the project file, so a printed record carries an
566
+ * absolute path only where a project itself declares one. Rewriting a contained absolute path to
567
+ * its relative form keeps one commit checked out at two roots reading to one digest. A path that
568
+ * escapes the workspace is left as it stands, because rewriting it would name a file outside the
569
+ * tree by a relative spelling. Key order is the compiler's own and it differs between the supported
570
+ * majors, so sorting removes a difference that means nothing.
429
571
  *
430
572
  * @param workspace - The target workspace root
431
573
  * @param value - The value to rewrite
@@ -440,7 +582,8 @@ export declare function normalizePath(path: string): string;
440
582
  export declare function normalizeValue(workspace: string, value: unknown): unknown;
441
583
 
442
584
  /**
443
- * Holds the candidate drafts one inspection substitutes for the files a tool would read from disk.
585
+ * Implements `OverlayInterface` over a private map from normalized absolute path to candidate text,
586
+ * minting at construction the `revision` a resident tool caches its answers against.
444
587
  *
445
588
  * @remarks
446
589
  * One overlay belongs to one inspection: the inspection creates it, records every candidate it
@@ -449,39 +592,32 @@ export declare function normalizeValue(workspace: string, value: unknown): unkno
449
592
  * is what makes a resident tool re-read a path this overlay holds, so two inspections that supply
450
593
  * different text for one path never share a cached answer.
451
594
  *
452
- * This overlay matches a lookup key the way the host its stage declares to its tool matches file
453
- * names. A host that resolves two spellings of one file name to one file leaves the tool holding
454
- * whichever spelling it met first — the disk one, where the file is on disk — and the tool asks
455
- * under that, so an overlay matching keys exactly answers nothing and the tool reads the committed
456
- * file instead. Mint the overlay with the sensitivity the stage declares, and one reading decides
457
- * both. The recorded spelling is what `paths` reports and what `covers` matches a directory
458
- * against, so a folded key never reaches the paths a tool is handed and containment stays an exact
459
- * comparison.
595
+ * A lookup key matches a recorded path exactly, after both pass through `normalizePath`, so a tool
596
+ * that reports its own paths with backslashes still reaches a candidate recorded with forward
597
+ * slashes. Case is never folded: the recorded spelling is what `paths` reports, what `covers`
598
+ * compares a directory against, and what `text` answers under. A stage whose tool resolves two
599
+ * spellings of one file name to one file therefore reports the path its tool served rather than
600
+ * matching the two spellings here.
460
601
  *
461
602
  * @example
462
603
  * ```ts
463
604
  * const overlay = new Overlay()
464
- * overlay.set('/srv/checkout/src/core/greeting.ts', "export const GREETING = 'hi'\n")
465
- * console.log(overlay.text('/srv/checkout/src/core/greeting.ts'))
605
+ * const path = '/srv/checkout/src/core/factories.ts'
606
+ * overlay.set(path, "export function createGreeting(): string {\n\treturn 'hi'\n}\n")
607
+ * console.log(overlay.text(path))
466
608
  * overlay.clear()
467
609
  * ```
468
610
  */
469
611
  export declare class Overlay implements OverlayInterface {
470
612
  #private;
471
- /**
472
- * Creates an empty candidate set under a fresh identity.
473
- *
474
- * @param options - Construction options
475
- */
476
- constructor(options?: OverlayOptions);
477
613
  get revision(): string;
478
614
  get paths(): readonly string[];
479
615
  /**
480
616
  * Records one candidate's text against the absolute path it stands in for.
481
617
  *
482
618
  * @remarks
483
- * Recording a candidate under a path this overlay's own matching reads as one already recorded
484
- * replaces that candidate, the way one file holds one text.
619
+ * Recording a candidate under a path this overlay already holds replaces that candidate, the way
620
+ * one file holds one text.
485
621
  *
486
622
  * @param path - The absolute path the candidate replaces
487
623
  * @param text - The candidate's full contents
@@ -502,9 +638,7 @@ export declare class Overlay implements OverlayInterface {
502
638
  * The answer is derived from the paths the overlay holds rather than stored, so it stops being
503
639
  * true exactly when the inspection that declared those candidates clears them. Both sides pass
504
640
  * through `normalizePath` first, because a tool that normalizes its own paths asks about a
505
- * directory in a spelling the recorded path may not share. Case is never folded here: this is a
506
- * containment comparison, and it reads the recorded spelling whatever an overlay minted for a
507
- * case-folding host matches its lookup keys by.
641
+ * directory in a spelling the recorded path may not share.
508
642
  *
509
643
  * @param directory - The absolute directory path to check
510
644
  * @returns True if a candidate path sits beneath the directory; false otherwise
@@ -523,10 +657,10 @@ export declare class Overlay implements OverlayInterface {
523
657
  *
524
658
  * @remarks
525
659
  * A stage records every candidate the inspection carries before it reads any of them, and clears
526
- * the set when the inspection ends, whatever ended it. The entity names no tool: each stage adapts
527
- * one overlay to the host its own tool expects, so a language service, a document protocol, and a
528
- * module resolver read one candidate set through their own adapters rather than through one shared
529
- * filesystem. Paths are absolute and the stage resolves them, because only the stage knows the
660
+ * the set when the inspection ends, whatever ended it. The runtime stage's module resolver reads
661
+ * one candidate set through its adapter and is the stage that holds an overlay; the type stage
662
+ * writes each draft into its mirror and the lint stage opens each draft as a document, so neither
663
+ * holds one. Paths are absolute and the stage resolves them, because only the stage knows the
530
664
  * workspace a candidate's declared path is relative to. `revision` identifies the set, so a
531
665
  * resident tool that caches by version reads fresh text for a path this overlay holds and reads
532
666
  * disk again after `clear`.
@@ -538,15 +672,16 @@ export declare class Overlay implements OverlayInterface {
538
672
  * @example
539
673
  * ```ts
540
674
  * const overlay: OverlayInterface = new Overlay()
541
- * overlay.set('/srv/checkout/src/core/greeting.ts', "export const GREETING = 'hi'\n")
675
+ * const path = '/srv/checkout/src/core/factories.ts'
676
+ * overlay.set(path, "export function createGreeting(): string {\n\treturn 'hi'\n}\n")
542
677
  * overlay.covers('/srv/checkout/src/core') // true
543
678
  * overlay.clear()
544
679
  * ```
545
680
  */
546
681
  export declare interface OverlayInterface {
547
- /** Identity of the candidate set this overlay holds. */
682
+ /** Identifies the candidate set this overlay holds. */
548
683
  readonly revision: string;
549
- /** Absolute path of every candidate this overlay holds. */
684
+ /** Names the absolute path of every candidate this overlay holds. */
550
685
  readonly paths: readonly string[];
551
686
  /**
552
687
  * Records one candidate's text against the absolute path it stands in for.
@@ -554,6 +689,12 @@ export declare interface OverlayInterface {
554
689
  * @param path - The absolute path the candidate replaces
555
690
  * @param text - The candidate's full contents
556
691
  * @returns Nothing
692
+ *
693
+ * @example
694
+ * ```ts
695
+ * const path = '/srv/checkout/src/core/factories.ts'
696
+ * overlay.set(path, "export function createGreeting(): string {\n\treturn 'hi'\n}\n")
697
+ * ```
557
698
  */
558
699
  set(path: string, text: string): void;
559
700
  /**
@@ -573,32 +714,29 @@ export declare interface OverlayInterface {
573
714
  *
574
715
  * @param directory - The absolute directory path to check
575
716
  * @returns True if a candidate path sits beneath the directory; false otherwise
717
+ *
718
+ * @example
719
+ * ```ts
720
+ * const path = '/srv/checkout/src/core/factories.ts'
721
+ * overlay.set(path, "export function createGreeting(): string {\n\treturn 'hi'\n}\n")
722
+ * overlay.covers('/srv/checkout/src/core') // true
723
+ * ```
576
724
  */
577
725
  covers(directory: string): boolean;
578
726
  /**
579
727
  * Releases every candidate.
580
728
  *
581
729
  * @returns Nothing
730
+ *
731
+ * @example
732
+ * ```ts
733
+ * overlay.clear()
734
+ * overlay.paths // []
735
+ * ```
582
736
  */
583
737
  clear(): void;
584
738
  }
585
739
 
586
- /**
587
- * Carries the construction options `Overlay` accepts.
588
- *
589
- * @example
590
- * ```ts
591
- * const options: OverlayOptions = { sensitive: false }
592
- * ```
593
- */
594
- export declare interface OverlayOptions {
595
- /**
596
- * If `true`, a lookup key matches a recorded path exactly; if `false`, it matches with file-name
597
- * case folded. Default: `true`
598
- */
599
- readonly sensitive?: boolean;
600
- }
601
-
602
740
  /**
603
741
  * Overwrites a file that already exists, through a descriptor that refuses a symbolic link at the
604
742
  * final component.
@@ -640,7 +778,50 @@ export declare interface OverlayOptions {
640
778
  export declare function overwriteFile(file: string, text: string): void;
641
779
 
642
780
  /**
643
- * Answers claims through resident TypeScript, Oxlint, and Vitest stages.
781
+ * Parses the configuration one compiler run printed for a TypeScript project.
782
+ *
783
+ * @remarks
784
+ * Reads what `tsc --showConfig` writes: a JSON record carrying the resolved `compilerOptions`
785
+ * beside the project's own file selection. `compilerOptions` is carried unvalidated, because a
786
+ * caller digests it rather than reading a member out of it. `files` and `include` are read only
787
+ * where the printed record carries one whose entries are all strings, so a member the compiler
788
+ * printed in another shape reads as absent rather than as an empty selection. Text that is not a
789
+ * JSON record, including the diagnostic the compiler prints for a project it refuses, yields
790
+ * `undefined`.
791
+ *
792
+ * @param text - The compiler's printed configuration
793
+ * @returns The project's resolved configuration, or `undefined` when the text carries no record
794
+ *
795
+ * @example
796
+ * ```ts
797
+ * parseProjectConfig('{"compilerOptions":{"strict":true}}')?.compilerOptions // { strict: true }
798
+ * parseProjectConfig("error TS5058: The specified path does not exist.") // undefined
799
+ * ```
800
+ */
801
+ export declare function parseProjectConfig(text: string): ProjectConfig | undefined;
802
+
803
+ /**
804
+ * Parses the process id one revision identity names.
805
+ *
806
+ * @remarks
807
+ * Every file and directory this package writes into a target carries the writing host's process id
808
+ * and a fresh UUID, joined by `-`. A sweep reads that id to decide whether the host that wrote the
809
+ * name is gone. The whole identity must match, so a name carrying anything else yields `undefined`
810
+ * and the sweep leaves what it found alone.
811
+ *
812
+ * @param revision - The revision identity a name carries
813
+ * @returns The process id it names, or `undefined` when the text is not a revision identity
814
+ *
815
+ * @example
816
+ * ```ts
817
+ * parseRevisionOwner('4821-1b4e28ba-2fa1-11d2-883f-0016d3cca427') // 4821
818
+ * parseRevisionOwner('4821-9f0c') // undefined
819
+ * ```
820
+ */
821
+ export declare function parseRevisionOwner(revision: string): number | undefined;
822
+
823
+ /**
824
+ * Answers claims through its type, lint, and runtime stages.
644
825
  *
645
826
  * @remarks
646
827
  * Construction resolves the target workspace's toolchain and begins warming every stage. The boot
@@ -652,17 +833,52 @@ export declare function overwriteFile(file: string, text: string): void;
652
833
  * claim costs that claim rather than the process. A failed boot is replaced the same way: the next
653
834
  * claim runs the controls again rather than inheriting a refusal.
654
835
  *
655
- * @example
836
+ * @example The claim that earns a receipt
656
837
  * ```ts
657
- * const probe = new Probe({ workspace: '/srv/checkout' })
838
+ * import type { Claim } from '@orkestrel/probe'
839
+ * import { Probe } from '@orkestrel/probe/server'
840
+ *
841
+ * const claim: Claim = {
842
+ * project: 'configs/src/tsconfig.core.json',
843
+ * case: {
844
+ * files: [
845
+ * {
846
+ * path: 'src/core/factories.ts',
847
+ * text: "export function createGreeting(): string {\n\treturn 'hi'\n}\n",
848
+ * },
849
+ * ],
850
+ * test: {
851
+ * path: 'tmp/probe/greeting.test.ts',
852
+ * text: "import { expect, test } from 'vitest'\nimport { createGreeting } from '../../src/core/factories.js'\ntest('greets', () => expect(createGreeting()).toBe('hi'))\n",
853
+ * },
854
+ * },
855
+ * control: {
856
+ * files: [
857
+ * {
858
+ * path: 'src/core/factories.ts',
859
+ * text: "export function createGreeting(): number {\n\treturn 'hi'\n}\n",
860
+ * },
861
+ * ],
862
+ * test: {
863
+ * path: 'tmp/probe/greeting.test.ts',
864
+ * text: "import { expect, test } from 'vitest'\nimport { createGreeting } from '../../src/core/factories.js'\ntest('greets', () => expect(createGreeting()).toBe('hi'))\n",
865
+ * },
866
+ * stage: 'type',
867
+ * reason: 'a string returned as a number must not compile',
868
+ * },
869
+ * }
870
+ *
871
+ * const probe = new Probe({ workspace: process.cwd() })
658
872
  * const verdict = await probe.prove(claim)
873
+ * verdict.digest // 'fcb88a2dee987b8673c1fc7107979470'
874
+ * verdict.receipt // 'probe:fcb88a2dee987b8673c1fc7107979470:type:typescript@6.0.3:oxlint@1.82.0:vitest@4.1.11:configs/src/tsconfig.core.json@434f59254d58cf2683d453a26bd0d837'
659
875
  * await probe.destroy()
660
876
  * ```
661
877
  */
662
878
  export declare class Probe implements ProbeInterface {
663
879
  #private;
664
880
  /**
665
- * Resolves the target toolchain and starts warming the resident stages.
881
+ * Resolves the target toolchain and starts warming every stage.
666
882
  *
667
883
  * @param options - Workspace, deadline, and initial observation hooks
668
884
  */
@@ -674,7 +890,9 @@ export declare class Probe implements ProbeInterface {
674
890
  }
675
891
 
676
892
  /**
677
- * Serves one probe over this process's Model Context Protocol stdio transport.
893
+ * Implements `ProbeServerInterface` over a `PassThrough` stream this server owns, binding the
894
+ * published `prove` tool and the dual-era dispatcher to this process's Model Context Protocol
895
+ * stdio transport.
678
896
  *
679
897
  * @remarks
680
898
  * Construction creates the probe, publishes the `prove` tool, and binds the dual-era dispatcher to
@@ -719,8 +937,8 @@ export declare class ProbeServer implements ProbeServerInterface {
719
937
  * The server owns the process it runs in. `start` seizes standard input and standard output for
720
938
  * the transport and registers the termination handlers a harness signals, so a host that starts one
721
939
  * has already given the process to it. `destroy` reverses all of that and tears the probe down with
722
- * it, which is why there is no verb that stops serving and leaves the resident engines running: a
723
- * probe nothing is reading from holds its resident tools for nobody.
940
+ * it, which is why there is no verb that stops serving and leaves the stages standing: a probe
941
+ * nothing is reading from holds its tools and its mirror for nobody.
724
942
  *
725
943
  * @example
726
944
  * ```ts
@@ -740,6 +958,12 @@ export declare interface ProbeServerInterface {
740
958
  *
741
959
  * @returns Nothing
742
960
  * @throws When this call comes after teardown begins
961
+ *
962
+ * @example
963
+ * ```ts
964
+ * const server = new ProbeServer({ workspace: process.cwd() })
965
+ * server.start()
966
+ * ```
743
967
  */
744
968
  start(): void;
745
969
  /**
@@ -756,11 +980,65 @@ export declare interface ProbeServerInterface {
756
980
  * `start` and when something else is reading it at release, and a stream nothing had read yet
757
981
  * and nothing else reads is paused.
758
982
  *
759
- * @returns A promise that settles after the probe releases its resident engines
983
+ * @returns A promise that settles after the probe releases every stage's tool and mirror
760
984
  */
761
985
  destroy(): Promise<void>;
762
986
  }
763
987
 
988
+ /**
989
+ * Carries what one TypeScript project resolved to, as the compiler itself printed it.
990
+ *
991
+ * @remarks
992
+ * The type stage reads this from `tsc --showConfig`, which prints the resolved options beside the
993
+ * project's own file selection. `compilerOptions` is the compiler's record and is carried
994
+ * unvalidated, because this package digests it rather than reading a member out of it. `files` is
995
+ * the selection the project resolved to, spelled relative to the project file, and `include` is
996
+ * present only where the project or a project it extends declares one. Every path is the
997
+ * compiler's own spelling, so a copy of the project file placed beside the original reads them
998
+ * unchanged.
999
+ *
1000
+ * @example
1001
+ * ```ts
1002
+ * const config: ProjectConfig = {
1003
+ * compilerOptions: { strict: true, rootDir: '../../src/core' },
1004
+ * files: ['../../src/core/index.ts'],
1005
+ * }
1006
+ * ```
1007
+ */
1008
+ export declare interface ProjectConfig {
1009
+ /** Holds the compiler options the project resolved to, unvalidated. */
1010
+ readonly compilerOptions: unknown;
1011
+ /** Holds the files the project resolved to, or is absent when the compiler printed none. */
1012
+ readonly files?: readonly string[];
1013
+ /** Holds the file patterns the project declares, or is absent when it declares none. */
1014
+ readonly include?: readonly string[];
1015
+ }
1016
+
1017
+ /**
1018
+ * Reads the condition code a native fault carries.
1019
+ *
1020
+ * @remarks
1021
+ * A caller catches `unknown`, so every reading of a caught value's own property calls into code
1022
+ * this package does not own: a proxy whose `has` trap throws and a value whose `code` getter throws
1023
+ * both arrive here. The read is guarded, so a fault that refuses inspection reports no code rather
1024
+ * than raising a second fault over the first. A `code` the host reports as anything other than a
1025
+ * string is no code this package compares against, so it reports none either.
1026
+ *
1027
+ * One reading serves every site that classifies a native fault, so a host condition is admitted the
1028
+ * same way wherever it is read.
1029
+ *
1030
+ * @param error - The caught value to read
1031
+ * @returns The fault's `code` when it carries a string one; `undefined` otherwise
1032
+ *
1033
+ * @example
1034
+ * ```ts
1035
+ * readFaultCode(Object.assign(new Error('no such file'), { code: 'ENOENT' })) // 'ENOENT'
1036
+ * readFaultCode(new Error('the runtime stage was destroyed')) // undefined
1037
+ * readFaultCode('ENOENT') // undefined
1038
+ * ```
1039
+ */
1040
+ export declare function readFaultCode(error: unknown): string | undefined;
1041
+
764
1042
  /**
765
1043
  * Reads one installed package manifest from the target workspace.
766
1044
  *
@@ -867,20 +1145,26 @@ export declare function releaseListeners(emitter: EventEmitter, capture: Listene
867
1145
  /**
868
1146
  * Resolves a package's portable JavaScript binary from the target workspace.
869
1147
  *
1148
+ * @remarks
1149
+ * A package publishes its binaries under keys of its own choosing, and that key is often not the
1150
+ * package name: `typescript` publishes `tsc`. Name the key as `command` wherever the two differ.
1151
+ * Default: the package name.
1152
+ *
870
1153
  * @param workspace - The target workspace root
871
- * @param name - The installed package name and binary key
1154
+ * @param name - The installed package name
1155
+ * @param command - The `bin` key to read. Default: `name`
872
1156
  * @returns The absolute JavaScript entry named by the package's `bin` field
873
- * @throws When the package does not publish a binary under the requested name
1157
+ * @throws When the package does not publish a binary under the requested key
874
1158
  *
875
1159
  * @example
876
1160
  * ```ts
877
1161
  * relativeWorkspaceFile(process.cwd(), resolveWorkspaceBinary(process.cwd(), 'oxlint'))
878
1162
  * // 'node_modules/oxlint/bin/oxlint'
879
- * resolveWorkspaceBinary(process.cwd(), 'typescript')
880
- * // throws: typescript does not publish the typescript binary
1163
+ * relativeWorkspaceFile(process.cwd(), resolveWorkspaceBinary(process.cwd(), 'typescript', 'tsc'))
1164
+ * // 'node_modules/typescript/bin/tsc'
881
1165
  * ```
882
1166
  */
883
- export declare function resolveWorkspaceBinary(workspace: string, name: string): string;
1167
+ export declare function resolveWorkspaceBinary(workspace: string, name: string, command?: string): string;
884
1168
 
885
1169
  /**
886
1170
  * Resolves a path inside a target workspace and rejects traversal outside it.
@@ -942,6 +1226,11 @@ export declare function resolveWorkspaceModule(workspace: string, specifier: str
942
1226
  * The runtime overlay leaves bare specifier resolution to Vite: it replaces a bare import only
943
1227
  * after Vite resolves that import to a covered file. The type stage overlays the declared test
944
1228
  * path, while this stage executes a generated sibling and overlays only the candidate files.
1229
+ * This stage mints its overlay with the default exact-match sensitivity, because it declares no
1230
+ * file-name case sensitivity to Vite. A covered path whose spelling an importer wrote differs from
1231
+ * the recorded candidate path is therefore served by whatever answers first, and `#misses` reports
1232
+ * it as `The workspace configuration served this module before the runtime overlay` with origin
1233
+ * `workspace` rather than leaving it answered silently.
945
1234
  *
946
1235
  * Vite retains one unresolved URL for every specification path, so the stage replaces its whole
947
1236
  * Vitest service after 64 specifications rather than deleting from each map that service owns. Any
@@ -987,24 +1276,72 @@ export declare class RuntimeStage implements StageInterface {
987
1276
  * @param workspace - The target workspace root. Default: the current working directory
988
1277
  */
989
1278
  constructor(workspace?: string);
990
- get stage(): Stage_2;
1279
+ get stage(): Stage;
991
1280
  get progress(): number;
992
- inspect(subject: Case_2): Promise<Check_2>;
1281
+ /**
1282
+ * Inspects one case.
1283
+ *
1284
+ * @param subject - The candidate drafts and test to inspect
1285
+ * @returns One outcome for this stage
1286
+ * @throws When the workspace's own tool cannot start or has already been destroyed
1287
+ */
1288
+ inspect(subject: Case): Promise<Check>;
1289
+ /**
1290
+ * Tears down the resident tool or the mirror and releases its resources.
1291
+ *
1292
+ * @remarks
1293
+ * A stage abandons every inspection it holds rather than waiting behind one, so teardown never
1294
+ * waits for an inspection to return. An abandoned inspection rejects, either at the stage's own
1295
+ * guard or as the owned tool closes. Teardown is bounded whatever the stage's own tool does: a
1296
+ * tool that answers neither its warming exchange nor its ending is signalled and released at the
1297
+ * stage's own deadline. A coordinator replaces a stage whose worker no longer returns because
1298
+ * teardown neither waits for an inspection nor waits past that deadline.
1299
+ *
1300
+ * @returns A promise that settles after the resident tool or the mirror releases its resources
1301
+ */
993
1302
  destroy(): Promise<void>;
994
1303
  }
995
1304
 
996
1305
  /**
997
- * Inspects one case with a resident workspace tool.
1306
+ * Scans the plain-text output of one compiler run into the diagnostics it reported.
1307
+ *
1308
+ * @remarks
1309
+ * Reads the shape `tsc --pretty false` prints: `path(line,column): error TSnnnn: message` for a
1310
+ * diagnostic about a file, and `error TSnnnn: message` for one about a project. A line that carries
1311
+ * neither prefix and begins with whitespace is an elaboration of the diagnostic above it and joins
1312
+ * that message with a newline; any other line is skipped, so a runtime's own failure text yields no
1313
+ * diagnostic and a caller reads that as the fault it is. The compiler counts lines and columns from
1314
+ * one and columns in UTF-16 code units, so each location is lowered to the zero-based UTF-16 point
1315
+ * `Diagnostic.range` fixes and `end` resolves to `start`, which is the extent this output carries.
1316
+ * A warning reads as a diagnostic, because the workspace's own gate reports it the same way. The
1317
+ * `TS\d+` token that follows `error` or `warning` is what recognizes the line; nothing is captured
1318
+ * from it, because `Diagnostic` carries no field for it.
1319
+ *
1320
+ * @param text - The compiler's output
1321
+ * @returns One record per reported diagnostic, in the compiler's own order
1322
+ *
1323
+ * @example
1324
+ * ```ts
1325
+ * scanDiagnostics("src/a.ts(1,14): error TS2322: Type 'string' is not assignable to type 'number'.")
1326
+ * // [{ path: 'src/a.ts', range: { start: { line: 0, character: 13 }, end: { line: 0, character: 13 } }, message: "Type 'string' is not assignable to type 'number'." }]
1327
+ * scanDiagnostics('error TS5058: The specified path does not exist.')
1328
+ * // [{ message: 'The specified path does not exist.' }]
1329
+ * ```
1330
+ */
1331
+ export declare function scanDiagnostics(text: string): readonly Diagnostic[];
1332
+
1333
+ /**
1334
+ * Inspects one case with the workspace's own tool.
998
1335
  *
999
1336
  * @remarks
1000
- * Warming begins at construction. The `inspect` method awaits that one warm operation and reuses
1001
- * the resulting tool across calls. A stage serves one inspection at a time and admits none itself.
1002
- * Await an inspection before starting the next one, or admit through one queue per stage the way
1003
- * `Probe` does: a second concurrent call reaches the same resident tool and the same overlay,
1004
- * document, and specification state the first is still using. A stage never holds a later
1005
- * inspection behind an earlier one, so a caller that abandons an inspection at its own deadline
1006
- * can still use the stage. The `destroy` method permanently tears the stage down and releases
1007
- * every resource it owns.
1337
+ * Warming begins at construction. The `inspect` method awaits that one warm operation, which
1338
+ * builds the resident tool or the mirror it reuses across calls. A stage serves one inspection at
1339
+ * a time and admits none itself. Await an inspection before starting the next one, or admit
1340
+ * through one queue per stage the way `Probe` does: a second concurrent call reaches the same
1341
+ * resident tool or mirror and the same overlay, document, and specification state the first is
1342
+ * still using. A stage never holds a later inspection behind an earlier one, so a caller that
1343
+ * abandons an inspection at its own deadline can still use the stage. The `destroy` method
1344
+ * permanently tears the stage down and releases every resource it owns.
1008
1345
  *
1009
1346
  * @example
1010
1347
  * ```ts
@@ -1014,10 +1351,10 @@ export declare class RuntimeStage implements StageInterface {
1014
1351
  * ```
1015
1352
  */
1016
1353
  export declare interface StageInterface {
1017
- /** The inspection this resident stage performs. */
1354
+ /** Names the inspection this stage performs. */
1018
1355
  readonly stage: Stage;
1019
1356
  /**
1020
- * Claimant-owned progress the coordinator compares with its inspection snapshot.
1357
+ * Reports claimant-owned progress the coordinator compares with its inspection snapshot.
1021
1358
  *
1022
1359
  * @remarks
1023
1360
  * When claimant-owned work is admitted, raise `progress` before awaiting its result. When this
@@ -1032,41 +1369,58 @@ export declare interface StageInterface {
1032
1369
  *
1033
1370
  * @param subject - The candidate drafts and test to inspect
1034
1371
  * @returns One outcome for this stage
1035
- * @throws When the resident tool cannot start or has already been destroyed
1372
+ * @throws When the workspace's own tool cannot start or has already been destroyed
1373
+ *
1374
+ * @example
1375
+ * ```ts
1376
+ * const check = await stage.inspect(subject)
1377
+ * console.log(check.stage, check.elapsed, check.issues.length)
1378
+ * ```
1036
1379
  */
1037
1380
  inspect(subject: Case): Promise<Check>;
1038
1381
  /**
1039
- * Tears down the resident tool and releases its resources.
1382
+ * Tears down the resident tool or the mirror and releases its resources.
1040
1383
  *
1041
1384
  * @remarks
1042
1385
  * A stage abandons every inspection it holds rather than waiting behind one, so teardown never
1043
1386
  * waits for an inspection to return. An abandoned inspection rejects, either at the stage's own
1044
- * guard or as the owned tool closes. Teardown is bounded whatever the resident tool does: a tool
1045
- * that answers neither its warming exchange nor its ending is signalled and released at the
1387
+ * guard or as the owned tool closes. Teardown is bounded whatever the stage's own tool does: a
1388
+ * tool that answers neither its warming exchange nor its ending is signalled and released at the
1046
1389
  * stage's own deadline. A coordinator replaces a stage whose worker no longer returns because
1047
1390
  * teardown neither waits for an inspection nor waits past that deadline.
1048
1391
  *
1049
- * @returns A promise that settles after the resident tool releases its resources
1392
+ * @returns A promise that settles after the resident tool or the mirror releases its resources
1050
1393
  */
1051
1394
  destroy(): Promise<void>;
1052
1395
  }
1053
1396
 
1054
1397
  /**
1055
- * Inspects TypeScript source through resident language services from the target workspace.
1398
+ * Inspects TypeScript source by running the target workspace's own compiler over a mirror of it.
1056
1399
  *
1057
1400
  * @remarks
1058
- * Construction starts loading the workspace's compiler and warming one service per project the
1059
- * workspace declares. A candidate draft is checked against the project a call names, or
1060
- * against its own scoped environment project when a call names none, while the test uses the root
1061
- * project. Disk snapshots use their modification time as the service version so dependency edits
1062
- * cannot leave a warm answer stale. Candidate text lives in an overlay the inspection owns, and
1063
- * the language-service host answers existence, reads, and versions from it, so a candidate that
1064
- * exists only as text is importable and a candidate that shadows a disk file is checked as the
1065
- * text the case supplied. A project outside the declared set holds one recycled slot, so a caller
1066
- * varying the project cannot grow the resident set. A language service checks one candidate
1067
- * synchronously, so the stage hands the host's event loop back at each candidate boundary: a
1068
- * caller's deadline is answered within one candidate's check rather than after the whole
1069
- * inspection, and an inspection abandoned at that deadline stops at the next boundary.
1401
+ * The compiler is a process this stage spawns rather than a module it loads, so nothing here holds
1402
+ * a resident program and the host's event loop is free for the whole check. Construction sweeps a
1403
+ * mirror an earlier host left behind, copies the workspace into a fresh one under
1404
+ * {@link TYPE_MIRROR}, and builds each declared project's incremental state there, so the first
1405
+ * inspection is warm.
1406
+ *
1407
+ * Every inspection refreshes the mirror by content digest, writes each candidate draft and the test
1408
+ * at its mirrored declared path, and runs `tsc --noEmit --pretty false` once per distinct selected
1409
+ * project. A draft therefore shadows the file it replaces: a consumer of that path is checked
1410
+ * against the draft's text, and a draft importing a sibling draft resolves to the sibling draft.
1411
+ * Nothing is written outside `tmp/`, and the workspace's own copy of a drafted file never moves.
1412
+ *
1413
+ * Each run reads a scratch project this stage writes beside the mirrored project it extends, so
1414
+ * every relative path the project declares — its own `rootDir`, `include`, `paths`, and the
1415
+ * projects it extends — resolves inside the mirror without being rewritten. The scratch adds the
1416
+ * drafts as `files`, which the project's own `exclude` does not reach, and its incremental state
1417
+ * lives in the mirror so reuse survives the refresh.
1418
+ *
1419
+ * The diagnostics decide the outcome, never the exit code, which the supported compiler majors
1420
+ * disagree on. A diagnostic naming a project file, and one naming no file at all, is the target
1421
+ * tree's own configuration fault and raises rather than reporting, unless the `.json` file is one
1422
+ * the claim itself drafted; every other diagnostic is a claimant issue at the point the compiler
1423
+ * reported, which is the extent the plain-text output carries.
1070
1424
  *
1071
1425
  * @example
1072
1426
  * ```ts
@@ -1078,12 +1432,12 @@ export declare interface StageInterface {
1078
1432
  export declare class TypeStage implements TypeStageInterface {
1079
1433
  #private;
1080
1434
  /**
1081
- * Starts warming the target workspace's TypeScript service.
1435
+ * Resolves the target workspace's compiler and starts warming its mirror.
1082
1436
  *
1083
1437
  * @param workspace - The target workspace root. Default: the current working directory
1084
1438
  */
1085
1439
  constructor(workspace?: string);
1086
- get stage(): Stage_2;
1440
+ get stage(): Stage;
1087
1441
  get progress(): number;
1088
1442
  /**
1089
1443
  * Inspects one case, against a caller-named project where the caller names one.
@@ -1097,24 +1451,25 @@ export declare class TypeStage implements TypeStageInterface {
1097
1451
  * @param project - The workspace-relative TypeScript project the candidate drafts are checked
1098
1452
  * against. Default: the scoped project each candidate path infers
1099
1453
  * @returns One outcome for this stage
1100
- * @throws When the resident compiler cannot start or the stage has already been destroyed
1454
+ * @throws When the workspace refuses the mirror, when a project the run reads is malformed, or
1455
+ * when the stage has already been destroyed
1101
1456
  */
1102
- inspect(subject: Case_2, project?: string): Promise<Check_2>;
1457
+ inspect(subject: Case, project?: string): Promise<Check>;
1103
1458
  /**
1104
1459
  * Resolves one project to the path and digest this stage applies for it.
1105
1460
  *
1106
1461
  * @remarks
1107
- * Reads the parse this stage itself applies, filling its cache when the project is not already
1108
- * resident, so the reported digest is the configuration the inspection is judged under rather
1109
- * than a second parse a caller ran. The returned record is a value copy, so a later eviction
1110
- * does not move it.
1462
+ * Reads the configuration the compiler itself prints for the project as the mirror holds it,
1463
+ * refreshed from the workspace first on a cache miss, so the digest names the configuration the
1464
+ * check applies. The reading is cached per project for the life of the stage, so a draft written
1465
+ * afterward cannot move it.
1111
1466
  *
1112
1467
  * @param project - The workspace-relative TypeScript project to resolve
1113
1468
  * @returns The resolved workspace-relative path and the digest of its compiler options
1114
- * @throws When the project escapes the workspace, cannot be parsed, or the stage has already
1115
- * been destroyed
1469
+ * @throws When the project escapes the workspace, when the compiler refuses it, or when the
1470
+ * stage has already been destroyed
1116
1471
  */
1117
- resolve(project: string): Promise<Project_2>;
1472
+ resolve(project: string): Promise<Project>;
1118
1473
  destroy(): Promise<void>;
1119
1474
  }
1120
1475
 
@@ -1124,7 +1479,8 @@ export declare class TypeStage implements TypeStageInterface {
1124
1479
  * @remarks
1125
1480
  * The type stage carries members the shared stage contract cannot: the lint and runtime stages
1126
1481
  * read no project, so a project parameter and a project lookup belong here rather than on
1127
- * `StageInterface`.
1482
+ * `StageInterface`. `resolve` reads the compiler's own printed configuration for the workspace's
1483
+ * copy of the project, so a claim's drafts never move the digest it reports.
1128
1484
  *
1129
1485
  * @example
1130
1486
  * ```ts
@@ -1140,7 +1496,13 @@ export declare interface TypeStageInterface extends StageInterface {
1140
1496
  * @param project - The workspace-relative TypeScript project the candidate drafts are checked
1141
1497
  * against. Default: the scoped project each candidate path infers
1142
1498
  * @returns One outcome for this stage
1143
- * @throws When the resident compiler cannot start or the stage has already been destroyed
1499
+ * @throws When the workspace refuses the mirror, when a project the run reads is malformed, or
1500
+ * when the stage has already been destroyed
1501
+ *
1502
+ * @example
1503
+ * ```ts
1504
+ * const check = await stage.inspect(subject, 'configs/src/tsconfig.core.json')
1505
+ * ```
1144
1506
  */
1145
1507
  inspect(subject: Case, project?: string): Promise<Check>;
1146
1508
  /**
@@ -1148,8 +1510,14 @@ export declare interface TypeStageInterface extends StageInterface {
1148
1510
  *
1149
1511
  * @param project - The workspace-relative TypeScript project to resolve
1150
1512
  * @returns The resolved workspace-relative path and the digest of its compiler options
1151
- * @throws When the project escapes the workspace, cannot be parsed, or the stage has already
1152
- * been destroyed
1513
+ * @throws When the project escapes the workspace, when the compiler refuses it, or when the
1514
+ * stage has already been destroyed
1515
+ *
1516
+ * @example
1517
+ * ```ts
1518
+ * const project = await stage.resolve('configs/src/tsconfig.core.json')
1519
+ * console.log(project.path, project.digest)
1520
+ * ```
1153
1521
  */
1154
1522
  resolve(project: string): Promise<Project>;
1155
1523
  }
@@ -1166,9 +1534,9 @@ export declare interface TypeStageInterface extends StageInterface {
1166
1534
  * ```
1167
1535
  */
1168
1536
  export declare interface WorkspaceManifest {
1169
- /** Absolute path of the package manifest. */
1537
+ /** Names the absolute path of the package manifest. */
1170
1538
  readonly path: string;
1171
- /** Parsed manifest record. */
1539
+ /** Holds the parsed manifest record. */
1172
1540
  readonly contents: Readonly<Record<string, unknown>>;
1173
1541
  }
1174
1542