@orkestrel/probe 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/core/index.d.cts +18 -4
- package/dist/src/core/index.d.ts +18 -4
- package/dist/src/server/index.cjs +398 -96
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +105 -3
- package/dist/src/server/index.d.ts +105 -3
- package/dist/src/server/index.js +399 -100
- package/dist/src/server/index.js.map +1 -1
- package/package.json +5 -4
|
@@ -117,6 +117,21 @@ export declare function describeUnknown(value: unknown): string;
|
|
|
117
117
|
*/
|
|
118
118
|
export declare function findRefusedPaths(value: unknown): readonly string[];
|
|
119
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Guards one resident-stage operation with the stage failure contract.
|
|
122
|
+
*
|
|
123
|
+
* @param stage - The resident stage serving the operation
|
|
124
|
+
* @param operation - The operation to settle
|
|
125
|
+
* @returns The operation's fulfilled value
|
|
126
|
+
* @throws The original `ProbeError`, or an instrument-owned malformed failure retaining the cause
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts
|
|
130
|
+
* await guardStage('type', stage.inspect(subject))
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export declare function guardStage<T>(stage: Stage, operation: Promise<T>): Promise<T>;
|
|
134
|
+
|
|
120
135
|
/**
|
|
121
136
|
* Selects the Language Server Protocol language identifier for a source path.
|
|
122
137
|
*
|
|
@@ -482,6 +497,40 @@ export declare interface OverlayInterface {
|
|
|
482
497
|
clear(): void;
|
|
483
498
|
}
|
|
484
499
|
|
|
500
|
+
/**
|
|
501
|
+
* Overwrites a file that already exists, through a descriptor that refuses a symbolic link at the
|
|
502
|
+
* final component.
|
|
503
|
+
*
|
|
504
|
+
* @remarks
|
|
505
|
+
* A containment walk and the write that follows it are separate calls, so a process that swaps the
|
|
506
|
+
* final component between them decides where the bytes land. `writeFileSync` opens with the default
|
|
507
|
+
* `w` flag, which follows a symbolic link at that component and creates the file when it is absent,
|
|
508
|
+
* so the walk's reading does not bind the write. Opening `O_WRONLY | O_TRUNC | O_NOFOLLOW` moves
|
|
509
|
+
* that decision into the call that writes: a link at the final component refuses the open, and the
|
|
510
|
+
* omitted `O_CREAT` fails `ENOENT` for a target that has gone since the walk saw it. This is the
|
|
511
|
+
* mutating counterpart of the `wx` flag every create in this package uses. Which code the refusal
|
|
512
|
+
* carries is the host's; Linux with Node v22.22.2 reported `ELOOP` on 2026-08-24.
|
|
513
|
+
*
|
|
514
|
+
* A directory component stays open, because Node exposes no descriptor-relative call to walk and
|
|
515
|
+
* write through one set of descriptors. Where a host's Node build defines no `O_NOFOLLOW`, that flag
|
|
516
|
+
* contributes nothing to the flag set and the final component is open on that host too.
|
|
517
|
+
*
|
|
518
|
+
* @param file - The absolute path to overwrite
|
|
519
|
+
* @param text - The text to write
|
|
520
|
+
* @returns Nothing
|
|
521
|
+
* @throws The host's own fault when the final component is a symbolic link, when the file is
|
|
522
|
+
* absent, or when the host refuses the descriptor
|
|
523
|
+
*
|
|
524
|
+
* @example
|
|
525
|
+
* ```ts
|
|
526
|
+
* const file = resolveWorkspaceFile('/srv/checkout', 'tmp/probe/arm-type.ts', true)
|
|
527
|
+
* writeFileSync(file, 'export type Signal = string\n', { encoding: 'utf8', flag: 'wx' })
|
|
528
|
+
* overwriteFile(file, 'export type Signal = number\n')
|
|
529
|
+
* readFileSync(file, 'utf8') // 'export type Signal = number\n'
|
|
530
|
+
* ```
|
|
531
|
+
*/
|
|
532
|
+
export declare function overwriteFile(file: string, text: string): void;
|
|
533
|
+
|
|
485
534
|
/**
|
|
486
535
|
* Reads a JSON-RPC frame's declared byte length.
|
|
487
536
|
*
|
|
@@ -649,6 +698,49 @@ export declare function readWorkspaceManifest(workspace: string, name: string):
|
|
|
649
698
|
*/
|
|
650
699
|
export declare function relativeWorkspaceFile(workspace: string, file: string): string;
|
|
651
700
|
|
|
701
|
+
/**
|
|
702
|
+
* Projects the paths one tool named in a message into the forms this package's issues expose.
|
|
703
|
+
*
|
|
704
|
+
* @remarks
|
|
705
|
+
* An issue's `path` is workspace-relative, and its message is prose a tool wrote about the same
|
|
706
|
+
* tree. Left alone that prose names a file by the host's own layout, so one issue reports a path two
|
|
707
|
+
* ways and a reader on another checkout is sent to a directory that is not theirs. Each spelling of
|
|
708
|
+
* the root is removed: the absolute path, the backslash spelling a Windows tool writes, and the
|
|
709
|
+
* `file:` URL a runtime names a module by. A root the host itself names ends in a separator, and the
|
|
710
|
+
* paths beneath it continue straight from it rather than from one more separator. A path outside the
|
|
711
|
+
* workspace stands as it is, because a relative spelling of it would name a file the tree does not
|
|
712
|
+
* hold.
|
|
713
|
+
*
|
|
714
|
+
* A spelling of the root counts only where a path begins: at the start of the message, or after a
|
|
715
|
+
* character no path carries. A directory whose own name ends in this root's text holds a different
|
|
716
|
+
* tree, so the root inside a longer path names a file this workspace does not hold and that path
|
|
717
|
+
* survives whole.
|
|
718
|
+
*
|
|
719
|
+
* Only the root is removed. A name is otherwise the tool's, including a `.probe-` name that reads
|
|
720
|
+
* like a specification this package generates: the stage that wrote one knows the exact name it
|
|
721
|
+
* wrote and renames that name itself, which is the only reading that separates its own file from a
|
|
722
|
+
* file the target tree owns.
|
|
723
|
+
*
|
|
724
|
+
* Everything else the tool wrote survives verbatim, separators included. A message carries text
|
|
725
|
+
* that is not a path — a runtime escapes a newline as a backslash when it prints a string inline,
|
|
726
|
+
* and a compiler quotes a string literal with its escapes intact — so rewriting every separator
|
|
727
|
+
* would corrupt the evidence the message exists to carry. The cost is that the path left behind
|
|
728
|
+
* keeps the separator the tool chose, which on Windows is not the one `Issue.path` uses.
|
|
729
|
+
*
|
|
730
|
+
* @param workspace - The target workspace root
|
|
731
|
+
* @param message - The message a tool reported
|
|
732
|
+
* @returns The message with the host's own layout removed from every path that begins with it
|
|
733
|
+
*
|
|
734
|
+
* @example
|
|
735
|
+
* ```ts
|
|
736
|
+
* relativeWorkspaceMessage('/srv/checkout', 'Cannot read /srv/checkout/tsconfig.json')
|
|
737
|
+
* // 'Cannot read tsconfig.json'
|
|
738
|
+
* relativeWorkspaceMessage('/srv/checkout', 'Cannot read /mirror/srv/checkout/tsconfig.json')
|
|
739
|
+
* // 'Cannot read /mirror/srv/checkout/tsconfig.json'
|
|
740
|
+
* ```
|
|
741
|
+
*/
|
|
742
|
+
export declare function relativeWorkspaceMessage(workspace: string, message: string): string;
|
|
743
|
+
|
|
652
744
|
/**
|
|
653
745
|
* Removes every listener one emitter gained for the captured events since its capture.
|
|
654
746
|
*
|
|
@@ -749,6 +841,13 @@ export declare function resolveWorkspaceModule(workspace: string, specifier: str
|
|
|
749
841
|
* workspace module whose disk content or candidate revision changed, runs that specification,
|
|
750
842
|
* evicts its result, and deletes the file. Clearing the overlay makes the next snapshot differ from
|
|
751
843
|
* the candidate revision, so the next inspection invalidates that module and reads disk again.
|
|
844
|
+
* After the run, the stage checks each covered module reachable from the generated specification
|
|
845
|
+
* against the overlay paths its loader served. A target-config loader that served first produces a
|
|
846
|
+
* workspace issue; a module id probe's loader received but failed to match produces an instrument
|
|
847
|
+
* issue.
|
|
848
|
+
* The runtime overlay leaves bare specifier resolution to Vite: it replaces a bare import only
|
|
849
|
+
* after Vite resolves that import to a covered file. The type stage overlays the declared test
|
|
850
|
+
* path, while this stage executes a generated sibling and overlays only the candidate files.
|
|
752
851
|
*
|
|
753
852
|
* Vite retains one unresolved URL for every specification path, so the stage replaces its whole
|
|
754
853
|
* Vitest service after 64 specifications rather than deleting from each map that service owns. Any
|
|
@@ -772,9 +871,12 @@ export declare function resolveWorkspaceModule(workspace: string, specifier: str
|
|
|
772
871
|
* test path the host refuses to create is a claimant failure with `code: 'refused'`. Each is thrown
|
|
773
872
|
* rather than reported, because a test that never ran is no evidence about the candidate.
|
|
774
873
|
*
|
|
775
|
-
*
|
|
776
|
-
*
|
|
777
|
-
*
|
|
874
|
+
* Physical containment covers the claim inputs, the target tree as the walk inspected it, and the
|
|
875
|
+
* final component at the moment this stage writes or unlinks it: a specification is created with the
|
|
876
|
+
* `wx` flag, which fails rather than following a symbolic link that appeared after the walk, and an
|
|
877
|
+
* unlink names the final component itself rather than what it points at. A directory component
|
|
878
|
+
* swapped for a symbolic link between the walk and the write stays open, because Node exposes no
|
|
879
|
+
* descriptor-relative call to pin the walk and the write to one set of descriptors.
|
|
778
880
|
*
|
|
779
881
|
* @example
|
|
780
882
|
* ```ts
|
|
@@ -117,6 +117,21 @@ export declare function describeUnknown(value: unknown): string;
|
|
|
117
117
|
*/
|
|
118
118
|
export declare function findRefusedPaths(value: unknown): readonly string[];
|
|
119
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Guards one resident-stage operation with the stage failure contract.
|
|
122
|
+
*
|
|
123
|
+
* @param stage - The resident stage serving the operation
|
|
124
|
+
* @param operation - The operation to settle
|
|
125
|
+
* @returns The operation's fulfilled value
|
|
126
|
+
* @throws The original `ProbeError`, or an instrument-owned malformed failure retaining the cause
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts
|
|
130
|
+
* await guardStage('type', stage.inspect(subject))
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export declare function guardStage<T>(stage: Stage, operation: Promise<T>): Promise<T>;
|
|
134
|
+
|
|
120
135
|
/**
|
|
121
136
|
* Selects the Language Server Protocol language identifier for a source path.
|
|
122
137
|
*
|
|
@@ -482,6 +497,40 @@ export declare interface OverlayInterface {
|
|
|
482
497
|
clear(): void;
|
|
483
498
|
}
|
|
484
499
|
|
|
500
|
+
/**
|
|
501
|
+
* Overwrites a file that already exists, through a descriptor that refuses a symbolic link at the
|
|
502
|
+
* final component.
|
|
503
|
+
*
|
|
504
|
+
* @remarks
|
|
505
|
+
* A containment walk and the write that follows it are separate calls, so a process that swaps the
|
|
506
|
+
* final component between them decides where the bytes land. `writeFileSync` opens with the default
|
|
507
|
+
* `w` flag, which follows a symbolic link at that component and creates the file when it is absent,
|
|
508
|
+
* so the walk's reading does not bind the write. Opening `O_WRONLY | O_TRUNC | O_NOFOLLOW` moves
|
|
509
|
+
* that decision into the call that writes: a link at the final component refuses the open, and the
|
|
510
|
+
* omitted `O_CREAT` fails `ENOENT` for a target that has gone since the walk saw it. This is the
|
|
511
|
+
* mutating counterpart of the `wx` flag every create in this package uses. Which code the refusal
|
|
512
|
+
* carries is the host's; Linux with Node v22.22.2 reported `ELOOP` on 2026-08-24.
|
|
513
|
+
*
|
|
514
|
+
* A directory component stays open, because Node exposes no descriptor-relative call to walk and
|
|
515
|
+
* write through one set of descriptors. Where a host's Node build defines no `O_NOFOLLOW`, that flag
|
|
516
|
+
* contributes nothing to the flag set and the final component is open on that host too.
|
|
517
|
+
*
|
|
518
|
+
* @param file - The absolute path to overwrite
|
|
519
|
+
* @param text - The text to write
|
|
520
|
+
* @returns Nothing
|
|
521
|
+
* @throws The host's own fault when the final component is a symbolic link, when the file is
|
|
522
|
+
* absent, or when the host refuses the descriptor
|
|
523
|
+
*
|
|
524
|
+
* @example
|
|
525
|
+
* ```ts
|
|
526
|
+
* const file = resolveWorkspaceFile('/srv/checkout', 'tmp/probe/arm-type.ts', true)
|
|
527
|
+
* writeFileSync(file, 'export type Signal = string\n', { encoding: 'utf8', flag: 'wx' })
|
|
528
|
+
* overwriteFile(file, 'export type Signal = number\n')
|
|
529
|
+
* readFileSync(file, 'utf8') // 'export type Signal = number\n'
|
|
530
|
+
* ```
|
|
531
|
+
*/
|
|
532
|
+
export declare function overwriteFile(file: string, text: string): void;
|
|
533
|
+
|
|
485
534
|
/**
|
|
486
535
|
* Reads a JSON-RPC frame's declared byte length.
|
|
487
536
|
*
|
|
@@ -649,6 +698,49 @@ export declare function readWorkspaceManifest(workspace: string, name: string):
|
|
|
649
698
|
*/
|
|
650
699
|
export declare function relativeWorkspaceFile(workspace: string, file: string): string;
|
|
651
700
|
|
|
701
|
+
/**
|
|
702
|
+
* Projects the paths one tool named in a message into the forms this package's issues expose.
|
|
703
|
+
*
|
|
704
|
+
* @remarks
|
|
705
|
+
* An issue's `path` is workspace-relative, and its message is prose a tool wrote about the same
|
|
706
|
+
* tree. Left alone that prose names a file by the host's own layout, so one issue reports a path two
|
|
707
|
+
* ways and a reader on another checkout is sent to a directory that is not theirs. Each spelling of
|
|
708
|
+
* the root is removed: the absolute path, the backslash spelling a Windows tool writes, and the
|
|
709
|
+
* `file:` URL a runtime names a module by. A root the host itself names ends in a separator, and the
|
|
710
|
+
* paths beneath it continue straight from it rather than from one more separator. A path outside the
|
|
711
|
+
* workspace stands as it is, because a relative spelling of it would name a file the tree does not
|
|
712
|
+
* hold.
|
|
713
|
+
*
|
|
714
|
+
* A spelling of the root counts only where a path begins: at the start of the message, or after a
|
|
715
|
+
* character no path carries. A directory whose own name ends in this root's text holds a different
|
|
716
|
+
* tree, so the root inside a longer path names a file this workspace does not hold and that path
|
|
717
|
+
* survives whole.
|
|
718
|
+
*
|
|
719
|
+
* Only the root is removed. A name is otherwise the tool's, including a `.probe-` name that reads
|
|
720
|
+
* like a specification this package generates: the stage that wrote one knows the exact name it
|
|
721
|
+
* wrote and renames that name itself, which is the only reading that separates its own file from a
|
|
722
|
+
* file the target tree owns.
|
|
723
|
+
*
|
|
724
|
+
* Everything else the tool wrote survives verbatim, separators included. A message carries text
|
|
725
|
+
* that is not a path — a runtime escapes a newline as a backslash when it prints a string inline,
|
|
726
|
+
* and a compiler quotes a string literal with its escapes intact — so rewriting every separator
|
|
727
|
+
* would corrupt the evidence the message exists to carry. The cost is that the path left behind
|
|
728
|
+
* keeps the separator the tool chose, which on Windows is not the one `Issue.path` uses.
|
|
729
|
+
*
|
|
730
|
+
* @param workspace - The target workspace root
|
|
731
|
+
* @param message - The message a tool reported
|
|
732
|
+
* @returns The message with the host's own layout removed from every path that begins with it
|
|
733
|
+
*
|
|
734
|
+
* @example
|
|
735
|
+
* ```ts
|
|
736
|
+
* relativeWorkspaceMessage('/srv/checkout', 'Cannot read /srv/checkout/tsconfig.json')
|
|
737
|
+
* // 'Cannot read tsconfig.json'
|
|
738
|
+
* relativeWorkspaceMessage('/srv/checkout', 'Cannot read /mirror/srv/checkout/tsconfig.json')
|
|
739
|
+
* // 'Cannot read /mirror/srv/checkout/tsconfig.json'
|
|
740
|
+
* ```
|
|
741
|
+
*/
|
|
742
|
+
export declare function relativeWorkspaceMessage(workspace: string, message: string): string;
|
|
743
|
+
|
|
652
744
|
/**
|
|
653
745
|
* Removes every listener one emitter gained for the captured events since its capture.
|
|
654
746
|
*
|
|
@@ -749,6 +841,13 @@ export declare function resolveWorkspaceModule(workspace: string, specifier: str
|
|
|
749
841
|
* workspace module whose disk content or candidate revision changed, runs that specification,
|
|
750
842
|
* evicts its result, and deletes the file. Clearing the overlay makes the next snapshot differ from
|
|
751
843
|
* the candidate revision, so the next inspection invalidates that module and reads disk again.
|
|
844
|
+
* After the run, the stage checks each covered module reachable from the generated specification
|
|
845
|
+
* against the overlay paths its loader served. A target-config loader that served first produces a
|
|
846
|
+
* workspace issue; a module id probe's loader received but failed to match produces an instrument
|
|
847
|
+
* issue.
|
|
848
|
+
* The runtime overlay leaves bare specifier resolution to Vite: it replaces a bare import only
|
|
849
|
+
* after Vite resolves that import to a covered file. The type stage overlays the declared test
|
|
850
|
+
* path, while this stage executes a generated sibling and overlays only the candidate files.
|
|
752
851
|
*
|
|
753
852
|
* Vite retains one unresolved URL for every specification path, so the stage replaces its whole
|
|
754
853
|
* Vitest service after 64 specifications rather than deleting from each map that service owns. Any
|
|
@@ -772,9 +871,12 @@ export declare function resolveWorkspaceModule(workspace: string, specifier: str
|
|
|
772
871
|
* test path the host refuses to create is a claimant failure with `code: 'refused'`. Each is thrown
|
|
773
872
|
* rather than reported, because a test that never ran is no evidence about the candidate.
|
|
774
873
|
*
|
|
775
|
-
*
|
|
776
|
-
*
|
|
777
|
-
*
|
|
874
|
+
* Physical containment covers the claim inputs, the target tree as the walk inspected it, and the
|
|
875
|
+
* final component at the moment this stage writes or unlinks it: a specification is created with the
|
|
876
|
+
* `wx` flag, which fails rather than following a symbolic link that appeared after the walk, and an
|
|
877
|
+
* unlink names the final component itself rather than what it points at. A directory component
|
|
878
|
+
* swapped for a symbolic link between the walk and the write stays open, because Node exposes no
|
|
879
|
+
* descriptor-relative call to pin the walk and the write to one set of descriptors.
|
|
778
880
|
*
|
|
779
881
|
* @example
|
|
780
882
|
* ```ts
|