@suss/adapter-typescript 0.10.0 → 0.11.0

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/index.d.cts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { SourceFile, Node, FunctionDeclaration, FunctionExpression, ArrowFunction, MethodDeclaration, CallExpression, Project, Symbol, Expression } from 'ts-morph';
2
2
  import { TransparentWrapper, RawCondition, DiscoveryPattern, TerminalPattern, InputMappingPattern, LanguageAdapter, PatternPack, ExtractorOptions, InvocationRecognizer, AccessRecognizer, RawCodeStructure, RawTerminal, RawBranch, EffectArg, RawDeclaredContract, ContractPattern, ResponsePropertyMapping } from '@suss/extractor';
3
3
  import { BehavioralSummary, MessageBusSemantics, DeployableUnit, BoundaryBinding, Predicate, TypeShape, ValueRef } from '@suss/behavioral-ir';
4
+ import { Proof, Atom } from '@suss/datalog';
5
+ import { ResolutionExplanation } from '@suss/resolution';
4
6
 
5
7
  /**
6
8
  * cache.ts: the on-disk extraction cache.
@@ -45,7 +47,6 @@ interface CacheDiagnostic {
45
47
  type CacheLookup = {
46
48
  kind: "hit";
47
49
  summaries: BehavioralSummary[];
48
- projectRoot?: string;
49
50
  diagnostic: CacheDiagnostic;
50
51
  } | {
51
52
  kind: "miss";
@@ -199,6 +200,28 @@ interface FileSetQuery {
199
200
  * edges a query follows, so cost tracks how indirect the code is.
200
201
  */
201
202
 
203
+ interface ExplainCallableOptions {
204
+ /** A second file to walk out from; see `resolveCallable`. */
205
+ alsoFrom?: SourceFile;
206
+ /** How many derived nodes deep the proof walk goes; see `proofOf`. */
207
+ maxDepth?: number;
208
+ }
209
+ /** What one witness re-evaluation cost, said rather than hidden. */
210
+ interface ExplainStats {
211
+ /** Facts the demand walk had extracted, which the proof pass reran. */
212
+ baseFacts: number;
213
+ /** Facts the exhaustive pass derived on top of those. */
214
+ derivedFacts: number;
215
+ evaluateMs: number;
216
+ }
217
+ interface ExplainedResolution {
218
+ /** The node the value comes down to. */
219
+ target: Node;
220
+ proof: Proof;
221
+ /** The source node behind a proof atom, when the atom is a node id. */
222
+ nodeFor: (atom: Atom) => Node | undefined;
223
+ stats: ExplainStats;
224
+ }
202
225
  declare class ResolutionStore {
203
226
  private readonly db;
204
227
  private readonly table;
@@ -219,6 +242,21 @@ declare class ResolutionStore {
219
242
  * the walk never reaches on its own.
220
243
  */
221
244
  resolveCallable(value: Node, alsoFrom?: SourceFile): Node | null;
245
+ /**
246
+ * Every function the value comes down to. One is the answer
247
+ * `resolveCallable` gives; several is a value with more than one
248
+ * possible source, which a caller says at the site rather than
249
+ * folding into the same nothing as a chain that went nowhere.
250
+ */
251
+ resolveCallableSources(value: Node, alsoFrom?: SourceFile): Node[];
252
+ /**
253
+ * The witness proof behind `resolveCallable`'s answer. Resolves the
254
+ * value first, which walks files and extracts facts in the usual
255
+ * waves, then re-evaluates the rules over those base facts under the
256
+ * witness algebra and rebuilds the proof of the answer. Null when
257
+ * the value does not resolve at all.
258
+ */
259
+ explainCallable(value: Node, options?: ExplainCallableOptions): ExplainedResolution | null;
222
260
  resolveObject(value: Node): Node | null;
223
261
  /**
224
262
  * For a value that is neither a function nor an object, such as a
@@ -266,10 +304,12 @@ declare class ResolutionStore {
266
304
  */
267
305
  filesImportingTransitively(fileSets: ReadonlyArray<FileSetQuery>): ReadonlyArray<ReadonlySet<SourceFile>>;
268
306
  /**
269
- * Two candidates give null. Picking whichever arrived first would make
270
- * the result depend on the order the facts came in.
307
+ * Null keeps the wave walk widening; any candidate at all ends it,
308
+ * since more files can only add candidates, never take one away. The
309
+ * single-answer policy stays with the callers: picking one of two
310
+ * would make the result depend on the order the facts came in.
271
311
  */
272
- private lookup;
312
+ private lookupSources;
273
313
  private derive;
274
314
  private answersFor;
275
315
  /**
@@ -394,6 +434,8 @@ interface DiscoveredUnit {
394
434
  required: boolean;
395
435
  }>;
396
436
  rootFields: string[];
437
+ /** Spreads in `document` with no definition in it: read partially. */
438
+ unresolvedFragments?: string[];
397
439
  unresolved?: {
398
440
  reference: string;
399
441
  reason: string;
@@ -523,6 +565,11 @@ type DescentBarriers = ReadonlySet<Node>;
523
565
  declare function extractCodeStructure(unit: DiscoveredUnit, pack: PatternPack, invocationRecognizers?: InvocationRecognizer[], accessRecognizers?: AccessRecognizer[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null): RawCodeStructure;
524
566
  interface TypeScriptAdapterConfig {
525
567
  tsConfigFilePath?: string;
568
+ /**
569
+ * Absolute. Every id's file path is relative to this directory. When
570
+ * absent, settled by workspaceRootFor from the tsconfig's directory.
571
+ */
572
+ projectRoot?: string;
526
573
  /** Separates two services in one repository whose file names match. */
527
574
  workspace?: string;
528
575
  project?: Project;
@@ -774,6 +821,71 @@ interface TsDiscoveryContext {
774
821
  }
775
822
  declare function createTsDiscoveryContext(resolution?: ResolutionStore): TsDiscoveryContext;
776
823
 
824
+ /**
825
+ * The session behind `suss ask why`: a ts-morph project over the
826
+ * asked-about source, a way to point at the expression somebody
827
+ * spelled, and the witness proof of what it resolved to, rendered
828
+ * through `@suss/resolution`'s phrases.
829
+ *
830
+ * The CLI points at values with a file, a line, and the text as
831
+ * written, because that is what a person has in hand. Everything
832
+ * ts-morph stays behind this class; callers treat the found nodes as
833
+ * opaque handles to pass back in.
834
+ */
835
+
836
+ interface WhySessionOptions {
837
+ /** The project root, which paths in every answer come out relative to. */
838
+ dir: string;
839
+ }
840
+ /** A value or function said the way an answer prints it. */
841
+ interface ValueLocation {
842
+ name: string;
843
+ /** Relative to the session root when under it, absolute otherwise. */
844
+ file: string;
845
+ line: number;
846
+ }
847
+ interface WhyExplained {
848
+ explanation: ResolutionExplanation;
849
+ /** The chain's atoms, each said in source terms. */
850
+ chain: string[];
851
+ /** The chain and its reasons as printable lines. */
852
+ lines: string[];
853
+ target: ValueLocation;
854
+ stats: ExplainStats;
855
+ }
856
+ declare class WhySession {
857
+ private readonly project;
858
+ private readonly store;
859
+ private readonly root;
860
+ constructor(options: WhySessionOptions);
861
+ /**
862
+ * The smallest expression on `line` of `file` whose text is exactly
863
+ * `text`, or null. Spelled from the person's side: the name as
864
+ * written, not a node id.
865
+ */
866
+ findExpression(file: string, line: number, text: string): Node | null;
867
+ /**
868
+ * The callee of the call written as `calleeText` between `startLine`
869
+ * and `endLine` of `file`, or null. This is how a summary's recorded
870
+ * callee gets back to its node: the summary keeps source text and a
871
+ * range, not ids.
872
+ */
873
+ findCallee(file: string, startLine: number, endLine: number, calleeText: string): Node | null;
874
+ /**
875
+ * Why `value` resolves to what it does: the witness proof, flattened
876
+ * to the chain and rendered. Null when the value does not resolve,
877
+ * which the caller says in its own words.
878
+ */
879
+ explain(value: Node, options?: {
880
+ maxDepth?: number;
881
+ }): WhyExplained | null;
882
+ /** Where a found node is, in the terms an answer prints. */
883
+ locate(node: Node): ValueLocation;
884
+ private sourceFileAt;
885
+ /** A module key: a file path said relative to the root, or a package name. */
886
+ private displayPath;
887
+ }
888
+
777
889
  type ExportedDeclarationMap = ReturnType<SourceFile["getExportedDeclarations"]>;
778
890
  /**
779
891
  * What a module exports, by exported name. Cached, because ts-morph
@@ -867,8 +979,14 @@ declare function isImportedFrom(identifier: Node, expectedModule: string): boole
867
979
  * asks this when the receiver came from somewhere the source does not
868
980
  * spell out: `const redis = await this.getClient()` says nothing about
869
981
  * ioredis, and the type of `redis.get` says everything.
982
+ *
983
+ * A client cached on an untyped global, `global.x || new Redis()`,
984
+ * types as `any`, so the method has no symbol. With `resolve` supplied,
985
+ * what the receiver was written as still says which library: the value
986
+ * comes down to a construction or a factory call of something imported
987
+ * from it.
870
988
  */
871
- declare function methodDeclaredIn(callee: Node, expectedModule: string): boolean;
989
+ declare function methodDeclaredIn(callee: Node, expectedModule: string, resolve?: (value: Node) => Node | null): boolean;
872
990
 
873
991
  /**
874
992
  * What a name-valued expression says, as fixed text with a hole for
@@ -995,6 +1113,37 @@ interface TsJsxAttributeLocation {
995
1113
  }
996
1114
  declare function createTsSubUnitContext(): TsSubUnitContext;
997
1115
 
1116
+ /**
1117
+ * Naming a summary, so that something else can point at it.
1118
+ *
1119
+ * A bare function name is not enough. Reading suss's own source turns up
1120
+ * 404 summaries that share a name with another one, and a large
1121
+ * repository is worse: two services with the same `src/handlers.ts` give
1122
+ * every summary in one an exact twin in the other. Following a call by
1123
+ * matching names was always a guess about which one was meant.
1124
+ *
1125
+ * So the name includes the project the summary came from, the file it is
1126
+ * in, and the path its export is reached by. That is unique across
1127
+ * everything one run can see, and it still looks like something a person
1128
+ * would have written down.
1129
+ */
1130
+
1131
+ /**
1132
+ * The one root a run measures its file paths from: the nearest
1133
+ * directory at or above the run's anchor whose package.json has a
1134
+ * name. The anchor is the tsconfig's directory, or the directory a
1135
+ * run without one was pointed at. When no package.json declares a
1136
+ * name above the anchor, the anchor itself is the root.
1137
+ *
1138
+ * The same directory supplies the workspace segment of an id, so both
1139
+ * parts of an id are measured from one place. The walk starts from the
1140
+ * run's configuration, not from whichever files the run loaded, so a
1141
+ * run over one nested tsconfig spells a file the same way a run over
1142
+ * the whole workspace does, and the same command spells it the same
1143
+ * way twice.
1144
+ */
1145
+ declare function workspaceRootFor(anchor: string): string;
1146
+
998
1147
  declare const ADAPTER_VERSION = "0.2.1";
999
1148
  /**
1000
1149
  * Content hash of the given files, in the order they arrive. Empty when
@@ -1026,4 +1175,4 @@ declare function computeAdapterPacksDigest(packVersions: ReadonlyArray<{
1026
1175
  version?: string;
1027
1176
  }>): string;
1028
1177
 
1029
- export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, type ReadNameOptions, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, methodDeclaredIn, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier };
1178
+ export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExplainCallableOptions, type ExplainStats, type ExplainedResolution, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, type ReadNameOptions, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, type ValueLocation, type WhyExplained, WhySession, type WhySessionOptions, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, methodDeclaredIn, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier, workspaceRootFor };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { SourceFile, Node, FunctionDeclaration, FunctionExpression, ArrowFunction, MethodDeclaration, CallExpression, Project, Symbol, Expression } from 'ts-morph';
2
2
  import { TransparentWrapper, RawCondition, DiscoveryPattern, TerminalPattern, InputMappingPattern, LanguageAdapter, PatternPack, ExtractorOptions, InvocationRecognizer, AccessRecognizer, RawCodeStructure, RawTerminal, RawBranch, EffectArg, RawDeclaredContract, ContractPattern, ResponsePropertyMapping } from '@suss/extractor';
3
3
  import { BehavioralSummary, MessageBusSemantics, DeployableUnit, BoundaryBinding, Predicate, TypeShape, ValueRef } from '@suss/behavioral-ir';
4
+ import { Proof, Atom } from '@suss/datalog';
5
+ import { ResolutionExplanation } from '@suss/resolution';
4
6
 
5
7
  /**
6
8
  * cache.ts: the on-disk extraction cache.
@@ -45,7 +47,6 @@ interface CacheDiagnostic {
45
47
  type CacheLookup = {
46
48
  kind: "hit";
47
49
  summaries: BehavioralSummary[];
48
- projectRoot?: string;
49
50
  diagnostic: CacheDiagnostic;
50
51
  } | {
51
52
  kind: "miss";
@@ -199,6 +200,28 @@ interface FileSetQuery {
199
200
  * edges a query follows, so cost tracks how indirect the code is.
200
201
  */
201
202
 
203
+ interface ExplainCallableOptions {
204
+ /** A second file to walk out from; see `resolveCallable`. */
205
+ alsoFrom?: SourceFile;
206
+ /** How many derived nodes deep the proof walk goes; see `proofOf`. */
207
+ maxDepth?: number;
208
+ }
209
+ /** What one witness re-evaluation cost, said rather than hidden. */
210
+ interface ExplainStats {
211
+ /** Facts the demand walk had extracted, which the proof pass reran. */
212
+ baseFacts: number;
213
+ /** Facts the exhaustive pass derived on top of those. */
214
+ derivedFacts: number;
215
+ evaluateMs: number;
216
+ }
217
+ interface ExplainedResolution {
218
+ /** The node the value comes down to. */
219
+ target: Node;
220
+ proof: Proof;
221
+ /** The source node behind a proof atom, when the atom is a node id. */
222
+ nodeFor: (atom: Atom) => Node | undefined;
223
+ stats: ExplainStats;
224
+ }
202
225
  declare class ResolutionStore {
203
226
  private readonly db;
204
227
  private readonly table;
@@ -219,6 +242,21 @@ declare class ResolutionStore {
219
242
  * the walk never reaches on its own.
220
243
  */
221
244
  resolveCallable(value: Node, alsoFrom?: SourceFile): Node | null;
245
+ /**
246
+ * Every function the value comes down to. One is the answer
247
+ * `resolveCallable` gives; several is a value with more than one
248
+ * possible source, which a caller says at the site rather than
249
+ * folding into the same nothing as a chain that went nowhere.
250
+ */
251
+ resolveCallableSources(value: Node, alsoFrom?: SourceFile): Node[];
252
+ /**
253
+ * The witness proof behind `resolveCallable`'s answer. Resolves the
254
+ * value first, which walks files and extracts facts in the usual
255
+ * waves, then re-evaluates the rules over those base facts under the
256
+ * witness algebra and rebuilds the proof of the answer. Null when
257
+ * the value does not resolve at all.
258
+ */
259
+ explainCallable(value: Node, options?: ExplainCallableOptions): ExplainedResolution | null;
222
260
  resolveObject(value: Node): Node | null;
223
261
  /**
224
262
  * For a value that is neither a function nor an object, such as a
@@ -266,10 +304,12 @@ declare class ResolutionStore {
266
304
  */
267
305
  filesImportingTransitively(fileSets: ReadonlyArray<FileSetQuery>): ReadonlyArray<ReadonlySet<SourceFile>>;
268
306
  /**
269
- * Two candidates give null. Picking whichever arrived first would make
270
- * the result depend on the order the facts came in.
307
+ * Null keeps the wave walk widening; any candidate at all ends it,
308
+ * since more files can only add candidates, never take one away. The
309
+ * single-answer policy stays with the callers: picking one of two
310
+ * would make the result depend on the order the facts came in.
271
311
  */
272
- private lookup;
312
+ private lookupSources;
273
313
  private derive;
274
314
  private answersFor;
275
315
  /**
@@ -394,6 +434,8 @@ interface DiscoveredUnit {
394
434
  required: boolean;
395
435
  }>;
396
436
  rootFields: string[];
437
+ /** Spreads in `document` with no definition in it: read partially. */
438
+ unresolvedFragments?: string[];
397
439
  unresolved?: {
398
440
  reference: string;
399
441
  reason: string;
@@ -523,6 +565,11 @@ type DescentBarriers = ReadonlySet<Node>;
523
565
  declare function extractCodeStructure(unit: DiscoveredUnit, pack: PatternPack, invocationRecognizers?: InvocationRecognizer[], accessRecognizers?: AccessRecognizer[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null): RawCodeStructure;
524
566
  interface TypeScriptAdapterConfig {
525
567
  tsConfigFilePath?: string;
568
+ /**
569
+ * Absolute. Every id's file path is relative to this directory. When
570
+ * absent, settled by workspaceRootFor from the tsconfig's directory.
571
+ */
572
+ projectRoot?: string;
526
573
  /** Separates two services in one repository whose file names match. */
527
574
  workspace?: string;
528
575
  project?: Project;
@@ -774,6 +821,71 @@ interface TsDiscoveryContext {
774
821
  }
775
822
  declare function createTsDiscoveryContext(resolution?: ResolutionStore): TsDiscoveryContext;
776
823
 
824
+ /**
825
+ * The session behind `suss ask why`: a ts-morph project over the
826
+ * asked-about source, a way to point at the expression somebody
827
+ * spelled, and the witness proof of what it resolved to, rendered
828
+ * through `@suss/resolution`'s phrases.
829
+ *
830
+ * The CLI points at values with a file, a line, and the text as
831
+ * written, because that is what a person has in hand. Everything
832
+ * ts-morph stays behind this class; callers treat the found nodes as
833
+ * opaque handles to pass back in.
834
+ */
835
+
836
+ interface WhySessionOptions {
837
+ /** The project root, which paths in every answer come out relative to. */
838
+ dir: string;
839
+ }
840
+ /** A value or function said the way an answer prints it. */
841
+ interface ValueLocation {
842
+ name: string;
843
+ /** Relative to the session root when under it, absolute otherwise. */
844
+ file: string;
845
+ line: number;
846
+ }
847
+ interface WhyExplained {
848
+ explanation: ResolutionExplanation;
849
+ /** The chain's atoms, each said in source terms. */
850
+ chain: string[];
851
+ /** The chain and its reasons as printable lines. */
852
+ lines: string[];
853
+ target: ValueLocation;
854
+ stats: ExplainStats;
855
+ }
856
+ declare class WhySession {
857
+ private readonly project;
858
+ private readonly store;
859
+ private readonly root;
860
+ constructor(options: WhySessionOptions);
861
+ /**
862
+ * The smallest expression on `line` of `file` whose text is exactly
863
+ * `text`, or null. Spelled from the person's side: the name as
864
+ * written, not a node id.
865
+ */
866
+ findExpression(file: string, line: number, text: string): Node | null;
867
+ /**
868
+ * The callee of the call written as `calleeText` between `startLine`
869
+ * and `endLine` of `file`, or null. This is how a summary's recorded
870
+ * callee gets back to its node: the summary keeps source text and a
871
+ * range, not ids.
872
+ */
873
+ findCallee(file: string, startLine: number, endLine: number, calleeText: string): Node | null;
874
+ /**
875
+ * Why `value` resolves to what it does: the witness proof, flattened
876
+ * to the chain and rendered. Null when the value does not resolve,
877
+ * which the caller says in its own words.
878
+ */
879
+ explain(value: Node, options?: {
880
+ maxDepth?: number;
881
+ }): WhyExplained | null;
882
+ /** Where a found node is, in the terms an answer prints. */
883
+ locate(node: Node): ValueLocation;
884
+ private sourceFileAt;
885
+ /** A module key: a file path said relative to the root, or a package name. */
886
+ private displayPath;
887
+ }
888
+
777
889
  type ExportedDeclarationMap = ReturnType<SourceFile["getExportedDeclarations"]>;
778
890
  /**
779
891
  * What a module exports, by exported name. Cached, because ts-morph
@@ -867,8 +979,14 @@ declare function isImportedFrom(identifier: Node, expectedModule: string): boole
867
979
  * asks this when the receiver came from somewhere the source does not
868
980
  * spell out: `const redis = await this.getClient()` says nothing about
869
981
  * ioredis, and the type of `redis.get` says everything.
982
+ *
983
+ * A client cached on an untyped global, `global.x || new Redis()`,
984
+ * types as `any`, so the method has no symbol. With `resolve` supplied,
985
+ * what the receiver was written as still says which library: the value
986
+ * comes down to a construction or a factory call of something imported
987
+ * from it.
870
988
  */
871
- declare function methodDeclaredIn(callee: Node, expectedModule: string): boolean;
989
+ declare function methodDeclaredIn(callee: Node, expectedModule: string, resolve?: (value: Node) => Node | null): boolean;
872
990
 
873
991
  /**
874
992
  * What a name-valued expression says, as fixed text with a hole for
@@ -995,6 +1113,37 @@ interface TsJsxAttributeLocation {
995
1113
  }
996
1114
  declare function createTsSubUnitContext(): TsSubUnitContext;
997
1115
 
1116
+ /**
1117
+ * Naming a summary, so that something else can point at it.
1118
+ *
1119
+ * A bare function name is not enough. Reading suss's own source turns up
1120
+ * 404 summaries that share a name with another one, and a large
1121
+ * repository is worse: two services with the same `src/handlers.ts` give
1122
+ * every summary in one an exact twin in the other. Following a call by
1123
+ * matching names was always a guess about which one was meant.
1124
+ *
1125
+ * So the name includes the project the summary came from, the file it is
1126
+ * in, and the path its export is reached by. That is unique across
1127
+ * everything one run can see, and it still looks like something a person
1128
+ * would have written down.
1129
+ */
1130
+
1131
+ /**
1132
+ * The one root a run measures its file paths from: the nearest
1133
+ * directory at or above the run's anchor whose package.json has a
1134
+ * name. The anchor is the tsconfig's directory, or the directory a
1135
+ * run without one was pointed at. When no package.json declares a
1136
+ * name above the anchor, the anchor itself is the root.
1137
+ *
1138
+ * The same directory supplies the workspace segment of an id, so both
1139
+ * parts of an id are measured from one place. The walk starts from the
1140
+ * run's configuration, not from whichever files the run loaded, so a
1141
+ * run over one nested tsconfig spells a file the same way a run over
1142
+ * the whole workspace does, and the same command spells it the same
1143
+ * way twice.
1144
+ */
1145
+ declare function workspaceRootFor(anchor: string): string;
1146
+
998
1147
  declare const ADAPTER_VERSION = "0.2.1";
999
1148
  /**
1000
1149
  * Content hash of the given files, in the order they arrive. Empty when
@@ -1026,4 +1175,4 @@ declare function computeAdapterPacksDigest(packVersions: ReadonlyArray<{
1026
1175
  version?: string;
1027
1176
  }>): string;
1028
1177
 
1029
- export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, type ReadNameOptions, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, methodDeclaredIn, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier };
1178
+ export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExplainCallableOptions, type ExplainStats, type ExplainedResolution, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, type ReadNameOptions, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, type ValueLocation, type WhyExplained, WhySession, type WhySessionOptions, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, methodDeclaredIn, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier, workspaceRootFor };