@nudojs/service 1.0.1 → 1.1.1

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.ts CHANGED
@@ -1,327 +1,47 @@
1
- import { Node, File } from '@babel/types';
2
- import { Abs, PolyFn, AbsModuleExports, AstEnv, Phi, BMemberDiag, BCallRecord, TranspiledCallResult, NudoConstraint } from '@nudojs/core';
3
- export { AbsInlay, BMemberDiag, collectAbsInlays } from '@nudojs/core';
4
- import { C as CallRecord } from './config-NqDRWWpn.js';
5
- export { I as InterfaceConfig, N as NudoConfig, f as findProjectConfig, i as interfaceConfig, m as matchesEmitAllowlist } from './config-NqDRWWpn.js';
6
- import { HarvestedEnv } from '@nudojs/harvester';
7
- import { FunctionWithDirectives } from '@nudojs/parser';
1
+ import { a as AnalyzeLoadModule, D as DirectiveCaseMode, A as AnalysisResult } from './analyzer-types-CfBrPK9L.js';
2
+ export { B as BindingInfo, C as CaseHint, b as CaseResult, c as CompletionItem, d as Diagnostic, e as DiagnosticSeverity, f as DiagnosticTag, F as FunctionAnalysis, R as ReferenceInfo, S as SourceLocation, g as SymbolInfo, h as SymbolTable } from './analyzer-types-CfBrPK9L.js';
3
+ export { A as AbsGraphOptions, a as AbsModuleCacheEntry, b as AbsModuleGraphResult, c as AbsModuleLoadIssue, B as BPathRunResult, E as EnvHarvestConflict, M as MergeHarvestOptions, d as ModuleGraphCache, e as analyzeFile, f as analyzeFileAsync, g as buildModuleGraph, h as clearAbsModuleCache, i as clearBPathCache, j as collectAbsBindingsFromGraph, k as collectBPathReplacements, l as collectCallRecords, m as collectEnvGlobals, n as collectEnvModules, o as collectEnvNames, p as computeDirtySet, q as defaultAbsLoadModule, r as diagnosticsLevelForFile, s as evalAbsModuleGraph, t as evictAbsModuleCacheFiles, u as evictBPathCacheForFiles, v as filterDiagnosticsByLevel, w as getAbsModuleCacheSize, x as getBPathCacheSize, y as getEnvHarvestConflictCollector, z as isBPathCapable, C as locFromNode, D as mergeHarvestUnderEnv, F as resolveModule, G as setEnvHarvestConflictCollector, H as shouldAnalyzeFile, I as sourceHasNudoDirectives, J as topoSortDirty, K as trimBPathCache, L as tryBPathCall, N as tryBPathCallFull, O as tryRunBPath } from './analysis-_DlXLC-L.js';
4
+ import { C as CallRecord } from './call-record-CkyCFkT9.js';
5
+ export { c as clearPathEnvCaches, g as getPathEnvCacheSizes } from './env-loader-fj0TSCcA.js';
6
+ import { N as NudoConfig } from './config-DDB588oA.js';
7
+ export { A as AnalysisConfig, a as AnalysisMode, C as CheckConfig, e as DEFAULT_ANALYSIS_MODE, D as DiagnosticsLevel, I as InterfaceConfig, b as analysisConfig, g as applyBForkBudgetFromConfig, c as checkConfig, h as currentBForkBudgetLimit, d as diskCacheRoot, f as findProjectConfig, i as interfaceConfig, m as matchesEmitAllowlist } from './config-DDB588oA.js';
8
+ import { File, Node } from '@babel/types';
9
+ import { PolyFn, Abs, AbsModuleExports } from '@nudojs/core';
10
+ import { L as LoadModule } from './what-if-mIo7I5Ii.js';
11
+ export { T as TypeBinding, d as defaultLoadModule, i as injectBindings, t as typeExprToDirective } from './what-if-mIo7I5Ii.js';
12
+ import { FunctionWithDirectives, FileDirective } from '@nudojs/parser';
13
+ import '@nudojs/core/internal';
14
+
15
+ declare function analysisFileCacheKey(filePath: string, source: string, activeCases?: Map<string, number>, externalCallRecords?: CallRecord[], analysisCfg?: {
16
+ mode: string;
17
+ evalMissingSlot: string;
18
+ callSiteBudget: number;
19
+ diagnostics: string;
20
+ }, loadModule?: AnalyzeLoadModule, projectEnvNames?: string[],
21
+ /** ambient 侧车绑定:变更必须 miss(dep 指纹故意不编码 autoBind) */
22
+ autoBind?: boolean, caseMode?: DirectiveCaseMode): {
23
+ filePath: string;
24
+ source: string;
25
+ auxKey: string;
26
+ noCache?: boolean;
27
+ };
8
28
 
9
29
  /**
10
30
  * Per-function FunctionAnalysis cache (body-edit: recompute only dirty fns).
11
31
  * Cleared together with B-path / whole-file analysis caches.
12
32
  */
13
33
 
34
+ /** 测试/诊断:当前条目数(≤ getSessionCacheLimits().maxFns) */
35
+ declare function getFnAnalysisCacheSize(): number;
14
36
  declare function clearFnAnalysisCache(): void;
37
+ /** 立刻压到当前 maxFns(调低上限时收内存) */
38
+ declare function trimFnAnalysisCache(): void;
15
39
  /**
16
40
  * Dependency content changed: drop every per-fn entry for these entry files.
17
41
  * Keys are `filePath\0...`, so a prefix scan is sound and cheap at LRU size.
18
42
  */
19
43
  declare function evictFnAnalysisCacheForFiles(files: string[]): number;
20
44
 
21
- type SourceLocation = {
22
- start: {
23
- line: number;
24
- column: number;
25
- };
26
- end: {
27
- line: number;
28
- column: number;
29
- };
30
- };
31
- type DiagnosticSeverity = "error" | "warning" | "info";
32
- type DiagnosticTag = "unnecessary";
33
- type Diagnostic = {
34
- range: SourceLocation;
35
- severity: DiagnosticSeverity;
36
- message: string;
37
- tags?: DiagnosticTag[];
38
- code?: string;
39
- suggestions?: string[];
40
- data?: unknown;
41
- /** provenance of the receiver value (callsite argument that flowed into the error) */
42
- origin?: {
43
- line: number;
44
- column: number;
45
- };
46
- };
47
- type CaseResult = {
48
- name: string;
49
- /** 无损参数 Abs */
50
- argAbs: Abs[];
51
- /** 无损结果 Abs */
52
- abs: Abs;
53
- /** 无损抛出 Abs(未抛为 never) */
54
- throwsAbs: Abs;
55
- throwLoc?: SourceLocation;
56
- source?: "directive" | "callsite";
57
- /** `@nudo:case "name" (…) => expected` — presence means the case is a test assertion */
58
- expected?: Abs;
59
- /** number of additional call sites folded into a symbolic case */
60
- aggregatedFrom?: number;
61
- /**
62
- * 内涵摘要(代数 generalize):无损 Abs + term/pred/conf。
63
- */
64
- intension?: {
65
- display?: string;
66
- term?: string;
67
- pred?: string;
68
- conf?: string;
69
- /** 无损 Abs 单行(formatAbs) */
70
- abs?: string;
71
- /** 无损 Abs 多行(formatAbsMultiline) */
72
- absMultiline?: string;
73
- };
74
- };
75
- type FunctionAnalysis = {
76
- name: string;
77
- loc: SourceLocation;
78
- paramNames: string[];
79
- cases: CaseResult[];
80
- /** cases 结果 Abs 的 join;dts 返回位源 */
81
- combinedAbs?: Abs;
82
- entryOnly?: boolean;
83
- skipped?: boolean;
84
- /**
85
- * True for functions collected from CJS-style bindings/assignments
86
- * (`exports.X = fn`, `module.exports = fn`, `const f = fn`): their name has
87
- * no declaration-level stability, so .d.ts generation skips them while
88
- * infer/JSON output still reports them.
89
- */
90
- noDeclaration?: boolean;
91
- /** absolute path of the module this function is imported from (externalFunctions only) */
92
- fromModule?: string;
93
- };
94
- type BindingInfo = {
95
- /** 无损 Abs */
96
- abs: Abs;
97
- loc?: SourceLocation;
98
- };
99
- type CaseHint = {
100
- line: number;
101
- label: string;
102
- ok: boolean;
103
- };
104
- type AnalysisResult = {
105
- functions: FunctionAnalysis[];
106
- diagnostics: Diagnostic[];
107
- bindings: Map<string, BindingInfo>;
108
- /**
109
- * Node identity is from the analysis-time parse. A later re-parse of the
110
- * same source returns a *different* File (new Nodes) if the AST LRU evicted
111
- * the original — lookups must use the File that produced this result, not a
112
- * freshly parsed one. getTypeAtPosition rebuilds its own map and is unaffected.
113
- */
114
- /** 无损节点 Abs */
115
- nodeAbsMap: Map<Node, Abs>;
116
- caseHints: CaseHint[];
117
- /** functions imported from other modules, synthesized from cross-file call sites observed while analyzing this file */
118
- externalFunctions?: FunctionAnalysis[];
119
- };
120
- type CompletionItem = {
121
- label: string;
122
- kind: "property" | "method" | "variable";
123
- detail?: string;
124
- };
125
- type SymbolInfo = {
126
- name: string;
127
- kind: "function" | "variable" | "class" | "parameter";
128
- loc: SourceLocation;
129
- uri?: string;
130
- };
131
- type ReferenceInfo = {
132
- name: string;
133
- loc: SourceLocation;
134
- uri?: string;
135
- };
136
- type SymbolTable = {
137
- definitions: Map<string, SymbolInfo>;
138
- references: ReferenceInfo[];
139
- };
140
- /** mtime 边缓存:key 为文件路径,edges 为已抽取的相对 import 边(与 buildModuleGraph 返回语义一致)。 */
141
- type ModuleGraphCache = Map<string, {
142
- mtimeMs: number;
143
- size: number;
144
- edges: string[];
145
- }>;
146
- /** Statically extract each file's relative import edges (extension resolution identical to CLI resolveModule: ''/'.js'/'.ts'/'.mjs'; bare npm specifiers skipped). */
147
- declare function buildModuleGraph(files: string[], cache?: ModuleGraphCache): {
148
- imports: Map<string, Set<string>>;
149
- dependents: Map<string, Set<string>>;
150
- };
151
- /** changed plus its transitive dependents (reverse-edge BFS); cycle-safe via visited. */
152
- declare function computeDirtySet(dependents: Map<string, Set<string>>, changedFile: string): string[];
153
- /** Topological order with dependencies before dependents (only imports edges internal to dirty; cycles tolerated — remaining files appended in arbitrary order). */
154
- declare function topoSortDirty(imports: Map<string, Set<string>>, dirty: string[]): string[];
155
- /**
156
- * Async entry to analyzeFile: preloads path-based env files
157
- * (`/// @nudo:env ./nudo-harvest-node.ts`) via dynamic import — impossible
158
- * synchronously in ESM — then runs the sync analysis, which picks the
159
- * preloaded factories up from the env-loader cache. The sync analyzeFile
160
- * signature is unchanged for existing consumers (LSP, MCP, vite-plugin).
161
- */
162
- declare function analyzeFileAsync(filePath: string, source: string, activeCases?: Map<string, number>, externalCallRecords?: CallRecord[]): Promise<AnalysisResult>;
163
- /**
164
- * 调用点发现(阶段一):在"使用现场"文件(测试 / 上层应用)中求值
165
- * 顶层代码,收集它对(外部模块导出的)函数的调用记录。每条记录带
166
- * 真实的实参类型与结果类型——后续 analyzeFile 将其注入合成 case,
167
- * 使被使用方从 entry-only(参数全 unknown)升级为真实调用形态。
168
- *
169
- * Abs 路径(TypeValue evaluateProgram 已删):evalProgramAbs + AbsCallRecord。
170
- * 只做求值与记录,不产出诊断;求值异常不抛出(使用现场文件可能
171
- * 依赖未 mock 的全局,收集不到就收集不到,不能拖垮主分析)。
172
- */
173
- declare function collectCallRecords(filePath: string, source: string): CallRecord[];
174
- /**
175
- * 整文件分析。同 (path, source, cases, external) 命中 memo → O(1)。
176
- * 不再每次 clearBPathCache:B 路径按本文件 source 键控。
177
- *
178
- * 宿主契约:入口 source 未变但依赖模块内容变了时,必须调用
179
- * `evictBPathCacheForFiles` / `evictAnalysisFileCacheForFiles` /
180
- * `evictFnAnalysisCacheForFiles`(LSP 已接好)。非 LSP 宿主
181
- * (CLI watch / vite-plugin)在 dep 变更时应 `clearBPathCache()` 或上述逐出。
182
- */
183
- declare function analyzeFile(filePath: string, source: string, activeCases?: Map<string, number>, externalCallRecords?: CallRecord[]): AnalysisResult;
184
-
185
- type CaseInfo = {
186
- functionName: string;
187
- caseName: string;
188
- caseIndex: number;
189
- };
190
- declare function getCasesForFile(filePath: string, source: string): {
191
- functionName: string;
192
- cases: {
193
- name: string;
194
- index: number;
195
- }[];
196
- loc: SourceLocation;
197
- }[];
198
- /** Async entry to getTypeAtPosition with path-env preloading (see analyzeFileAsync). */
199
- declare function getTypeAtPositionAsync(filePath: string, source: string, line: number, column: number, activeCases?: Map<string, number>): Promise<Abs | null>;
200
- /** Async entry to getAbsAtPosition(与 getTypeAtPositionAsync 同预加载口径) */
201
- declare function getAbsAtPositionAsync(filePath: string, source: string, line: number, column: number, activeCases?: Map<string, number>): Promise<Abs | null>;
202
- /**
203
- * 光标处无损 Abs。B-path 节点表优先;用例函数体走 Abs 重放。
204
- */
205
- declare function getAbsAtPosition(filePath: string, source: string, line: number, column: number, activeCases?: Map<string, number>): Abs | null;
206
- /** 光标处类型(Abs)。B-path 节点表优先;用例函数体走 Abs 重放。 */
207
- declare function getTypeAtPosition(filePath: string, source: string, line: number, column: number, activeCases?: Map<string, number>): Abs | null;
208
- type HoverInfo = {
209
- /** 外延展示(formatShape / formatAbs) */
210
- typeText: string;
211
- /** 内涵签名(代数 generalize) */
212
- intension?: string;
213
- /** 无损 Abs 单行展示(shape / term / pred / conf) */
214
- abs?: string;
215
- /** 无损 Abs 多行展示 */
216
- absMultiline?: string;
217
- };
218
- /**
219
- * LSP hover:优先无损 Abs(类型即计算本体)。
220
- * 节点表也是 Abs(collectAbsNodeTypes),不经 bridge。
221
- *
222
- * 函数名/调用 callee 位置(design-hof-relations §7):
223
- * intension 一律走 generalize/formatPoly(HOF fnRels 在这里);
224
- * typeText 仍落 B-path Abs(调用点显示结果类型,不是函数签名)。
225
- * 禁止用 B-path 的 arity-only fn Abs 冒充权威关系源。
226
- */
227
- declare function getHoverAtPosition(filePath: string, source: string, line: number, column: number, activeCases?: Map<string, number>): HoverInfo | null;
228
- declare function getCompletionsAtPosition(filePath: string, source: string, line: number, column: number): CompletionItem[];
229
-
230
- /**
231
- * `nudo infer --json` 稳定契约 v1(CI / Agent)。
232
- *
233
- * 字段只增不改语义:
234
- * - args / result / throws / combined:formatShape 外延投影(有损,兼容)
235
- * - intension.abs*:无损 Abs 展示(主线)
236
- * - argsAbs / resultAbs:CaseResult 上的无损 Abs(formatAbs);有则补齐
237
- */
238
-
239
- type InferJsonCase = {
240
- name: string;
241
- /** TypeValue 投影(有损外延) */
242
- args: string[];
243
- result: string;
244
- throws: string | null;
245
- source: string | null;
246
- aggregatedFrom?: number;
247
- /** 无损参数 Abs 展示(与 args 对齐;缺失位省略) */
248
- argsAbs?: string[];
249
- /** 无损结果 Abs 展示 */
250
- resultAbs?: string;
251
- /** 无损内涵(Abs);无则省略 */
252
- intension?: {
253
- display?: string;
254
- abs?: string;
255
- absMultiline?: string;
256
- term?: string;
257
- pred?: string;
258
- conf?: string;
259
- };
260
- };
261
- type InferJsonFunction = {
262
- name: string;
263
- loc: SourceLocation;
264
- entryOnly: boolean;
265
- noDeclaration?: boolean;
266
- cases: InferJsonCase[];
267
- combined?: string;
268
- /** 无损 combined Abs 展示 */
269
- combinedAbs?: string;
270
- };
271
- type InferJson = {
272
- version: 1;
273
- file: string;
274
- summary: {
275
- functions: number;
276
- externalFunctions: number;
277
- cases: number;
278
- diagnostics: number;
279
- };
280
- functions: InferJsonFunction[];
281
- externalFunctions?: Array<{
282
- name: string;
283
- fromModule?: string;
284
- cases: InferJsonCase[];
285
- }>;
286
- diagnostics: Array<{
287
- range: SourceLocation;
288
- severity: string;
289
- message: string;
290
- code?: string;
291
- suggestions?: string[];
292
- tags?: string[];
293
- origin?: {
294
- line: number;
295
- column: number;
296
- };
297
- }>;
298
- };
299
- declare function serializeInferJson(result: AnalysisResult, file: string): InferJson;
300
-
301
- /**
302
- * nudo 推断目标文件判定(纯扩展名规则,路径无需存在)。
303
- *
304
- * 规则:.js / .mjs / .ts 可作为推断目标;其余扩展(.cjs/.tsx/.jsx/.mts/.d.ts…)
305
- * 一律 false。显式排除:
306
- * - .d.ts —— 类型声明文件(harvester 的输入),不是可求值的实现源码;
307
- * - .tsx / .jsx —— JSX 构造的求值超出 nudo 推断器范围;
308
- * - *.nudo.js / *.nudo.ts —— 侧车契约模块(interface 绑定源),不是源码
309
- * 推断目标;目录级 check/infer/doctor 展开不得把它们当实现分析。
310
- *
311
- * 消费方:CLI 的 collectNudoFiles/watch 过滤/doctor 目录展开(.ts 放开后统一
312
- * 走本函数,避免各处手写 endsWith 漂移),以及 LSP 的 isNudoFile(接线由
313
- * LSP 侧负责)。
314
- */
315
- declare function isNudoTargetPath(path: string): boolean;
316
-
317
- /**
318
- * 相对/绝对 specifier → 模块源码。
319
- * CLI / LSP / vite / check 共用同一扩展名表,避免门禁结果分叉。
320
- */
321
- type LoadModule = (spec: string, fromFile: string) => string | undefined;
322
- /** 默认 loadModule:支持 .js/.mjs/.ts 与 index 入口 */
323
- declare function defaultLoadModule(spec: string, fromFile: string): string | undefined;
324
-
325
45
  /**
326
46
  * Host 侧多文件解析(非代数层)。
327
47
  *
@@ -351,219 +71,102 @@ declare function analyzeExportsFromSource(filePath: string, source: string): Mod
351
71
  declare function collectStaticImports(entryFile: string, maxDepth?: number): Map<string, ModuleExports>;
352
72
 
353
73
  /**
354
- * Host:从 npm 包 / @types 收集 .d.ts → harvestDts。
355
- * 代数不碰 fs;这里只做「找到 dts 路径」这一层宿主职责。
356
- */
357
-
358
- /** 在 node_modules 中解析包根(含 @types/*) */
359
- declare function resolvePackageRoot(pkg: string, fromDir?: string): string | undefined;
360
- type PackageHarvest = {
361
- pkg: string;
362
- root: string;
363
- dtsFiles: string[];
364
- env: HarvestedEnv;
365
- };
366
- /**
367
- * 从入口 .d.ts 沿 reference path / 相对 import 做 BFS 收集。
368
- * 适合 @types 包(三斜线引用图);比整树 walk 更贴声明入口。
369
- */
370
- declare function collectDtsFromEntry(entry: string, maxFiles?: number): string[];
371
- /** harvest 一个 npm 包(或 @types 包) */
372
- declare function harvestPackage(pkg: string, fromDir?: string, maxFiles?: number): PackageHarvest | {
373
- error: string;
74
+ * Entry-variant (browser / node) observation signal.
75
+ *
76
+ * (Module named entry-variants to avoid "dual engine" confusion; the
77
+ * product diagnostic code remains `nudo:dual-entry`.)
78
+ *
79
+ * Call-site records are file-scoped: when a package ships separate browser and
80
+ * node entrypoints, records collected against one variant do **not** inject
81
+ * into analysis of the other (design limitation, not a bug). This module makes
82
+ * that ceiling visible: when analysis runs on one entry variant of a dual-entry
83
+ * package, emit `nudo:dual-entry` once so the user is not left thinking both
84
+ * entries were covered.
85
+ *
86
+ * Zero-FP discipline: fires only when package.json really declares two faces
87
+ * (browser + node/default) that resolve to **different** files, and the file
88
+ * being analyzed is one of those entry targets. Single-entry packages never
89
+ * fire.
90
+ */
91
+ type EntryVariantInfo = {
92
+ pkgPath: string;
93
+ pkgDir: string;
94
+ pkgName?: string;
95
+ kind: "exports-conditions" | "browser-field";
96
+ /** resolved absolute paths of the browser face */
97
+ browserPaths: string[];
98
+ /** resolved absolute paths of the node/default face */
99
+ nodePaths: string[];
100
+ /** which face the analyzed file belongs to */
101
+ role: "browser" | "node";
102
+ /** display targets (as declared, relative) for the message */
103
+ browserTargets: string[];
104
+ nodeTargets: string[];
105
+ };
106
+ type EntryVariantFaces = {
107
+ kind: "exports-conditions" | "browser-field";
108
+ browser: string[];
109
+ node: string[];
110
+ };
111
+ /**
112
+ * Detect browser/node dual faces in a parsed package.json.
113
+ * Returns null unless both faces exist and differ (zero-FP on single-entry).
114
+ */
115
+ declare function detectEntryVariantsFromPackageJson(pkg: unknown): EntryVariantFaces | null;
116
+ /** Nearest package.json walking up from the file's directory. */
117
+ declare function findOwningPackage(fromFile: string): {
118
+ path: string;
119
+ dir: string;
120
+ pkg: Record<string, unknown>;
121
+ } | null;
122
+ /**
123
+ * Dual-entry info for an analyzed file: the owning package must declare two
124
+ * differing faces **and** this file must be one of the entry targets.
125
+ * Returns null otherwise (single-entry packages, shared helpers, …).
126
+ */
127
+ declare function entryVariantForFile(filePath: string): EntryVariantInfo | null;
128
+ /** Host-facing info issue (CLI check / JSON) for one analyzed entry variant. */
129
+ type EntryVariantIssue = {
130
+ severity: "info";
131
+ code: "nudo:dual-entry";
132
+ message: string;
133
+ suggestion: string;
134
+ line: number;
135
+ column: number;
374
136
  };
375
- /** harvest 结果 → 人类可读导出表 */
376
- declare function formatHarvestSummary(h: PackageHarvest): string;
377
- /** 取某个导出的展示串(formatShape) */
378
- declare function lookupHarvested(h: PackageHarvest, moduleName: string, exportName: string): string | undefined;
137
+ declare function entryVariantIssueForFile(filePath: string): EntryVariantIssue | null;
379
138
 
380
139
  /**
381
- * harvest 自动化:源码裸 import → @types/package → env modules。
382
- * 手动 `nudo harvest` 仍保留;这里是分析路径上的按需注入。
140
+ * `@nudo:skip [returnsExpr]` 采集(host 侧)。
141
+ *
142
+ * core 的 `checkSource` 不依赖 parser,所以 skip 指令由 host(CLI / LSP /
143
+ * vite-plugin)解析后经 `CheckOptions.skips` 下传——保证 check 面与 test 面
144
+ * 对 skip 的口径一致:不评估 body、退出 L1/L2 门禁。
383
145
  */
384
146
 
385
- /** 裸说明符 → 包名(含 scope);相对/绝对/node: 内建返回 undefined */
386
- declare function barePackageName(spec: string): string | undefined;
387
- declare function collectBarePackages(source: string): string[];
388
- declare function harvestPackageCached(pkg: string, fromDir: string): PackageHarvest | null;
389
- declare function clearHarvestCache(): void;
390
147
  /**
391
- * 自动 harvest 源码中全部裸包(有 @types 或包内 dts 时)。
392
- * 返回可注入 setEnvModules 的 modules 表;无包可 harvest 时为空对象。
148
+ * 每个带 `@nudo:skip` 的顶层函数 → 声明的返回 Abs;`null` = 未声明返回类型。
149
+ * 解析失败(语法错误等)→ 空表(check 退回默认路径,不静默吞函数)。
393
150
  */
394
- declare function autoHarvestModules(source: string, fromDir: string): Record<string, Record<string, Abs>>;
151
+ declare function collectSkipReturns(source: string): Map<string, Abs | null>;
395
152
 
396
153
  /**
397
- * Host:import 图(相对 + 裸包 harvest)→ Abs 导出表 → 注入入口。
398
- * 读 fs / 解析路径 / harvest 在这里;core 只收 modules 表。
154
+ * check/iface 磁盘缓存键的依赖内容采集。
155
+ * 走 core `loadModuleDepsFingerprint`:覆盖 ESM from / require / dynamic import /
156
+ * `@nudo:import` / ambient 侧车闭包——不只 `@nudo:import` 注释。
157
+ *
158
+ * 内容必须优先取 loadModule 解析结果(fingerprint.contents),不得回读磁盘:
159
+ * LSP buffer-aware loadModule 与自定义 loader 的内容可能与磁盘不一致,
160
+ * 回读会让缓存键分叉(buffer 编辑后仍命中磁盘旧内容)。
399
161
  */
400
-
401
- type AbsLoadModule = (spec: string, fromFile: string) => string | undefined;
402
- /** 相对说明符 → 源码 */
403
- declare function defaultAbsLoadModule(spec: string, fromFile: string): string | undefined;
404
- /** 模块加载守卫:与 TypeValue loadModuleEnv 口径对齐,供 analyzer 映射诊断 */
405
- type AbsModuleLoadIssue = {
406
- kind: "cycle" | "depth" | "missing";
407
- /** 诊断定位用标签(文件 basename 或 require/import 说明符) */
408
- label: string;
409
- reason: string;
410
- };
411
- type AbsModuleGraphResult = {
412
- /** 入口 import 说明符 → 依赖导出表 */
413
- modules: Record<string, AbsModuleExports>;
414
- /** 绝对路径 → 导出表(含依赖;循环时占位为空) */
415
- byPath: Map<string, AbsModuleExports>;
416
- /** cycle / depth / missing(B 路径权威,避免 TypeValue 叠报) */
417
- issues: AbsModuleLoadIssue[];
418
- };
419
- type AbsGraphOptions = {
420
- loadModule?: AbsLoadModule;
421
- seedVars?: Record<string, Abs>;
422
- seedFns?: Record<string, {
423
- params: string[];
424
- body: Node;
425
- async?: boolean;
426
- }>;
427
- maxDepth?: number;
428
- };
429
- /** 会话级依赖模块缓存条目:stat 指纹 + 导出 + 子树装载 issue。 */
430
- type AbsModuleCacheEntry = {
431
- mtimeMs: number;
432
- size: number;
433
- exports: AbsModuleExports;
434
- /** 该模块子树首次求值时记录的 cycle/depth/missing;命中时重放。 */
435
- issues: AbsModuleLoadIssue[];
162
+ type DepContent = {
163
+ path: string;
164
+ content: string | null;
436
165
  };
437
- declare function clearAbsModuleCache(): void;
438
- declare function evictAbsModuleCacheFiles(paths: string[]): void;
439
- /**
440
- * 递归求值相对依赖 + 裸包 harvest,产出入口可用的 modules 表。
441
- * 循环依赖:先放空表再回填(与 TypeValue 路径 partial 口径一致),
442
- * 并记录 cycle/depth/missing 供诊断。
443
- */
444
- declare function evalAbsModuleGraph(entrySource: string, entryFile: string, opts?: AbsGraphOptions): AbsModuleGraphResult;
445
- /** 便捷:入口求值 + 依赖 Abs 注入 */
446
- declare function evalProgramAbsWithModules(source: string, entryFile: string, opts?: AbsGraphOptions & {
447
- file?: unknown;
448
- }): {
449
- env: AstEnv;
450
- last: Abs;
451
- phi: Phi;
166
+ declare function collectLoadDepContents(filePath: string, source: string, loadModule: (spec: string, fromFile: string) => string | undefined): {
167
+ depContents: DepContent[];
168
+ truncated: boolean;
452
169
  };
453
- /**
454
- * 收集顶层绑定名 → Abs(含相对 import / 裸包 harvest 注入)。
455
- * 供 bindings / hover 从 Abs 投影,不必走 TypeValue evaluator。
456
- */
457
- declare function collectAbsBindingsFromGraph(source: string, filePath: string, opts?: AbsGraphOptions): Map<string, Abs>;
458
-
459
- /**
460
- * Harvest Abs 导出 → AbsModuleExports(供 Abs 模块图注入)。
461
- * harvest 产物已是 Abs;fn 槽 apply 直接返回声明返回类型(conf=mock)。
462
- */
463
-
464
- /** 单个 Abs 导出 → 可调用 mock(fn 槽 apply 返回声明返回类型) */
465
- declare function harvestedValueToAbs(a: Abs): Abs;
466
- /**
467
- * 把 harvest 的 modules/globals 合成 AbsModuleExports。
468
- * 键同时登记:原始模块路径、包名、basename(path / @types/path)。
469
- */
470
- declare function harvestToAbsModules(pkg: string, fromDir: string): Record<string, AbsModuleExports>;
471
- declare function packageHarvestToAbsModules(pkg: string, h: PackageHarvest): Record<string, AbsModuleExports>;
472
- /** 裸说明符 → Abs 导出表(走 harvest 缓存) */
473
- declare function bareSpecToAbsModules(spec: string, fromFile: string): AbsModuleExports | undefined;
474
-
475
- /** @nudo:env → Abs 全局表(env 模块 Abs 原生) */
476
- declare function collectEnvGlobals(envNames: string[]): Record<string, Abs>;
477
- /** @nudo:env modules(path / node:path / fs…)→ AbsModuleExports */
478
- declare function collectEnvModules(envNames: string[]): Record<string, AbsModuleExports>;
479
- /** 收集 @nudo:replace + @nudo:as → transpile 注入表 */
480
- declare function collectBPathReplacements(source: string): {
481
- targets: Array<{
482
- target: string;
483
- varName: string;
484
- stmtStart?: number;
485
- stmtEnd?: number;
486
- }>;
487
- values: Record<string, Abs>;
488
- asTargets: Array<{
489
- varName: string;
490
- stmtStart: number;
491
- stmtEnd: number;
492
- }>;
493
- asValues: Record<string, Abs>;
494
- };
495
- /** 可走 transpile+exec:env 经 loadEnvs(内置 + 已 preload 的路径型) */
496
- declare function isBPathCapable(source: string, envNames?: string[]): boolean;
497
- type BPathRunResult = {
498
- exports: Record<string, unknown>;
499
- modules: Record<string, AbsModuleExports>;
500
- /** 顶层执行期 method-missing */
501
- memberDiags?: BMemberDiag[];
502
- /** 模块图 cycle/depth/missing(B 权威) */
503
- moduleIssues?: AbsModuleLoadIssue[];
504
- /** Abs 求值递归截断的函数标签 */
505
- truncatedFns?: string[];
506
- /** 顶层 $callNamed 调用点(call@ 合成;不经 TypeValue collector) */
507
- calls?: BCallRecord[];
508
- };
509
- declare function clearBPathCache(): void;
510
- /** 依赖文件变更后:逐出以这些文件为入口的 B-path 缓存 */
511
- declare function evictBPathCacheForFiles(files: string[]): number;
512
- /** 模块图 + runTranspiled(默认 analyze 模式) */
513
- declare function tryRunBPath(source: string, filePath: string, opts?: {
514
- maxLoopIters?: number;
515
- mode?: "exec" | "analyze";
516
- envNames?: string[];
517
- /** @nudo:mock → Abs,注入为全局绑定(防止顶层调用真 fetch 等) */
518
- mocks?: Record<string, Abs>;
519
- }): BPathRunResult | undefined;
520
- /**
521
- * B 路径求值具名导出(结果 + throws);opts.collectCalls 时附带调用点记录。
522
- *
523
- * `calls` 只含**本次具名调用期间**(callTranspiledExportFull 内)发生的
524
- * 调用点——不含模块级顶层调用(run.calls)。模块级记录由主分析流程
525
- * 另行收集(analyzer 的 bTopCallRecords / absCallRecords);在此重复返回
526
- * 会把 B 路径结果(常为 unknown)当第二组记录推给 analyzer,dedupe 因
527
- * 结果形态不同而保留,污染被调函数的 case 列表(多余 call@L 重复 +
528
- * call@symbolic 聚合 case,见 analyzer directive-case 分支)。
529
- */
530
- declare function tryBPathCallFull(source: string, filePath: string, fnName: string, args: Abs[], opts?: {
531
- collectCalls?: boolean;
532
- collectMemberDiags?: boolean;
533
- envNames?: string[];
534
- mocks?: Record<string, Abs>;
535
- }): (TranspiledCallResult & {
536
- calls?: BCallRecord[];
537
- memberDiags?: BMemberDiag[];
538
- moduleIssues?: AbsModuleLoadIssue[];
539
- truncatedFns?: string[];
540
- }) | undefined;
541
- /** B 路径求值具名导出(仅成功结果) */
542
- declare function tryBPathCall(source: string, filePath: string, fnName: string, args: Abs[], opts?: {
543
- envNames?: string[];
544
- mocks?: Record<string, Abs>;
545
- }): Abs | undefined;
546
-
547
- declare function clearAnalysisFileCache(): void;
548
- declare function getAnalysisFileCacheSize(): number;
549
- /** 依赖变更后:按入口文件逐出 */
550
- declare function evictAnalysisFileCacheForFiles(files: string[]): number;
551
-
552
- /**
553
- * 依赖内容变更后:按入口文件定向逐出 service 层缓存。
554
- * 调用方应传「以这些文件为入口」的路径(脏集里的 dependents),
555
- * 而不是变更的 dep 文件本身——dep 自己 source 变了会自然 miss。
556
- */
557
- declare function evictAnalysisCachesForFiles(files: string[]): void;
558
- /**
559
- * 清空全部会话级分析缓存(service + core)。
560
- * 适用于:CLI watch 增量批前、vite buildStart / watchChange、测试隔离。
561
- * 比定向逐出重,但保证无陈旧命中;单次 analyze 内部的 per-fn / generalize
562
- * memo 不受影响(它们在同一轮里先写后读)。
563
- */
564
- declare function clearAnalysisSessionCaches(): void;
565
- /** 比 clearAnalysisSessionCaches 更彻底:再丢 AST LRU(测试 / 进程复用场景) */
566
- declare function resetAllAnalysisCaches(): void;
567
170
 
568
171
  /**
569
172
  * B 路径静态诊断(AST,不执行):
@@ -599,129 +202,9 @@ type BPathDiagnostics = {
599
202
  declare function collectBPathDiagnostics(source: string, extraKnown?: Iterable<string>): BPathDiagnostics;
600
203
 
601
204
  /**
602
- * 预置 Node API env:从 @types/node 的 .d.ts harvest。
603
- * 与 packages/env 的手写 env 并行;此路径自动、可刷新。
604
- */
605
-
606
- type NodeEnvResult = {
607
- ok: true;
608
- env: HarvestedEnv;
609
- root: string;
610
- files: number;
611
- } | {
612
- ok: false;
613
- error: string;
614
- };
615
- /** harvest @types/node(限制文件数 + 时间预算,避免拖垮启动) */
616
- declare function harvestNodeTypes(fromDir?: string, maxFiles?: number, maxMs?: number): NodeEnvResult;
617
- /** 把 harvest 结果压成「模块名 → 导出名列表」摘要,便于日志/测试 */
618
- declare function summarizeNodeEnv(env: HarvestedEnv): {
619
- modules: string[];
620
- globals: string[];
621
- symbolCount: number;
622
- };
623
-
624
- /**
625
- * Semantic tokens 图例(tokenTypes 下标即 LSP 编码里的 tokenType 值)。
626
- * 与 LSP server capabilities 里声明的 legend 必须逐字对齐——server.ts 直接
627
- * 导入本常量注册,保证「提取端索引」与「客户端图例」单一来源。
628
- * 顺序沿用 lsp 包原 legend(function/variable/parameter/property 在前),
629
- * 末尾追加 method(对象字面量方法键),只追加不重排,客户端索引稳定。
630
- */
631
- declare const SEMANTIC_TOKEN_TYPES: readonly ["function", "variable", "parameter", "property", "type", "keyword", "string", "number", "comment", "decorator", "method"];
632
- declare const SEMANTIC_TOKEN_MODIFIERS: readonly ["declaration", "readonly", "deprecated", "unreachable"];
633
- type SemanticToken = {
634
- line: number;
635
- char: number;
636
- length: number;
637
- typeIndex: number;
638
- modifierBitmask: number;
639
- };
640
- /** LSP 标准相对五元组编码:deltaLine/deltaStartChar/length/tokenType/tokenModifiers。 */
641
- declare function encodeSemanticTokens(tokens: SemanticToken[]): number[];
642
- /**
643
- * 从源码提取 semantic tokens 并按 LSP 相对编码返回扁平 number[]。
644
- *
645
- * 上色范围(声明位优先,未解析的 token 一律不上色):
646
- * - 顶层 const/let/var 声明的绑定名:推断为函数绑定 → function,否则 variable
647
- * (函数体内部的声明不做 env 反查——外层同名绑定会串味,统一 variable);
648
- * - 函数声明/函数表达式的名字 → function;所有函数的参数 → parameter;
649
- * - 对象字面量的键:值为函数 → method,否则 property。
650
- *
651
- * 推断优先 Abs 模块图绑定(TypeValue 退出主路径);失败时复用
652
- * evaluateProgram。解析失败返回 []。
653
- */
654
- declare function buildSemanticTokens(filePath: string, source: string): number[];
655
-
656
- /** Abs → TS 类型串。有损:pred / 非 lit term 落到 shape 基类型。 */
657
- declare function absToTSType(a: Abs): string;
658
- /**
659
- * 为单个函数生成 .d.ts 声明行(JSDoc + 单一 widen 主签名)。
660
- * service 的 generateDts 与 CLI `--dts`(infer/watch)共用本函数,
661
- * 两条路径输出保持一致。
662
- */
663
- declare function generateFunctionDtsLines(fn: FunctionAnalysis): string[];
664
- declare function generateDts(result: AnalysisResult): string;
665
-
666
- /** Abs → zod schema 源码。有损:pred / 非 lit term 落到 shape 基类型。 */
667
- declare function absToZodSchema(a: Abs): string;
668
-
669
- /** Abs 指称守卫(设计 §2.7):保留 pred */
670
- declare function generateGuardFunctionFromAbs(name: string, abs: Abs): string;
671
- /** 兼容别名:Abs 路径唯一 */
672
- declare function generateGuardFunction(name: string, abs: Abs): string;
673
-
674
- /** 单个 Abs → parseCaseArgExpr 可解析回去的表达式文本;不可表达返回 null */
675
- declare function serializeCaseArg(a: Abs): string | null;
676
- /**
677
- * 组装单行 ` * @nudo:case "name" (a, b)` 指令文本(无尾换行)。
678
- * 任一实参不可序列化、或名字含双引号/换行(名字正则 `"([^"]+)"` 承载不了)→ 整体 null。
679
- */
680
- declare function buildCaseDirective(name: string, argsAbs: Abs[]): string | null;
681
- /**
682
- * 从源码剥离所有本模块生成的 @nudo:case 指令(名字以 call@ 开头,整行删除)。
683
- * 若所属 JSDoc 块因此只剩空 ` *` 行(无其他 @nudo:* 指令、无文字内容),
684
- * 连块首 `/**` 行与块尾行整块删除。绝不碰非 case 指令与普通注释。
685
- * 注意:手写但以 call@ 命名的 case 同样会被删——call@ 前缀保留为生成物标记。
686
- * removed 返回被删指令名列表(按出现顺序)。
687
- */
688
- declare function stripGeneratedCaseDirectives(source: string): {
689
- source: string;
690
- removed: string[];
691
- };
692
- type EmitSkipReason = "hand-written" | "already-generated" | "entry-only" | "no-serializable-cases" | "no-declaration" | "skipped";
693
- type EmitResult = {
694
- source: string;
695
- changed: boolean;
696
- written: Array<{
697
- fn: string;
698
- cases: string[];
699
- }>;
700
- skipped: Array<{
701
- fn: string;
702
- reason: EmitSkipReason;
703
- detail?: string;
704
- }>;
705
- };
706
- /**
707
- * 把 analysis 中的合成 case(source === "callsite")固化为源码指令:
708
- *
709
- * 1. 源码已有任何非 call@ 命名的 case → skip "hand-written";
710
- * 已有 call@ case → skip "already-generated"。
711
- * 2. fn.skipped / fn.noDeclaration / fn.entryOnly → 对应 skip。
712
- * 3. 逐 case 序列化;个别不可序列化的丢弃并在 skipped 记
713
- * no-serializable-cases(函数整体仍写可序列化子集,全不可序列化才整函数跳过)。
714
- * 4. 写入位置:函数声明行正上方——已有 JSDoc 块则插到 `/**` 行后,
715
- * 无块则新建三行块。缩进取声明行的 loc.start.column(babel 0 基列)。
716
- * 多函数编辑按行号从下往上应用,避免行号漂移。
717
- */
718
- declare function insertGeneratedCaseDirectives(source: string, analysis: AnalysisResult): EmitResult;
719
- /** 行级 unified diff:`--- a/path` 头 + `@@` hunk + 上下文 3 行;相同返回 "" */
720
- declare function unifiedDiff(a: string, b: string, path: string): string;
721
-
722
- /**
723
- * @nudo:mock / sinon 指令 → Abs seed(供 evalProgramAbs)。
724
- * host 层:依赖 parser 指令形态;core 只吃 seedVars/seedFns。
205
+ * @nudo:mock / sinon 指令 → Abs seed(供 B 路径注入:runTranspiled
206
+ * envGlobals / mockSeedsToAbsMocks)。
207
+ * host 层:依赖 parser 指令形态;core 只吃 Abs 绑定。
725
208
  */
726
209
 
727
210
  type AbsMockSeeds = {
@@ -732,242 +215,271 @@ type AbsMockSeeds = {
732
215
  async?: boolean;
733
216
  fingerprint?: string;
734
217
  }>;
218
+ /** `@nudo:mock name from "path"` 解析失败(缺文件 / 缺绑定 / 求值失败)——fail-closed 诊断用 */
219
+ fromErrors?: FromMockError[];
220
+ };
221
+ type FromMockError = {
222
+ name: string;
223
+ fromPath: string;
224
+ message: string;
735
225
  };
226
+ /**
227
+ * B 路径注入用:seedVars + seedFns 统一为 Abs 函数绑定。
228
+ * arrowFn mock 落在 seedFns(AST body,供 ast-eval),B 路径的
229
+ * envGlobals 注入只吃 Abs——不合并会把 mock 丢掉,函数体内的调用
230
+ * 会落到真实原生函数(如 fetch 拿 Abs 当 URL,直接崩)。
231
+ */
232
+ declare function mockSeedsToAbsMocks(seeds: AbsMockSeeds): Record<string, Abs>;
736
233
  /** 从函数上的 @nudo:mock 指令收集 Abs seed */
737
234
  declare function mockDirectivesToAbsSeeds(functions: Array<{
738
235
  directives: FunctionWithDirectives["directives"];
739
- }>): AbsMockSeeds;
236
+ }>, opts?: {
237
+ /** `@nudo:mock name from "path"` 相对解析基准(被分析文件) */
238
+ fromFile?: string;
239
+ /** 自定义装载器(LSP buffer-aware);缺省 defaultLoadModule */
240
+ loadModule?: LoadModule;
241
+ }): AbsMockSeeds;
242
+ /** 便捷入口:源码 → @nudo:mock 的 B 注入 Abs 绑定(checkSource 注入管线用) */
243
+ declare function mockSeedsForSource(source: string, opts?: {
244
+ fromFile?: string;
245
+ loadModule?: LoadModule;
246
+ }): Record<string, Abs>;
740
247
 
741
248
  /**
742
- * `nudo interface` 的打印数据源(design-refine-derivation §11 第 0 步):
743
- * 逐顶层函数展示有效契约分层——effectiveInterface 命中(手写契约 / 侧车
744
- * 生成段)时 params/returns 用 formatConstraint 组合式显示;未命中走
745
- * implicit:优先 CaseResult.argAbs / FunctionAnalysis.combinedAbs(无损
746
- * Abs 源),展示用 formatShape(外延口径,不强求约束式、不带 conf)。
249
+ * `@nudo:mock-module "spec" from "./mock.js"` — file-level module replacement.
250
+ * Full replace swaps the specifier's exports table; partial `{ a, b }` only
251
+ * overlays those named exports and lets the rest fall through.
747
252
  *
748
- * autoBind 沿 package.json#nudo.interface(findProjectConfig → interfaceConfig)
749
- * 下传,可用 opts 覆盖(测试 / CLI 显式开关);读盘用 defaultLoadModule
750
- * (与 check 的 refine 解析同一扩展名表)。
253
+ * Fail-closed: missing mock file / eval failure / empty binding → error, not
254
+ * a silent drop and not invented types.
751
255
  */
752
256
 
753
- type InterfaceSurfaceEntry = {
754
- fn: string;
755
- /** 本文件 named export(自动绑定边界口径:localNamedExports) */
756
- kind: "export" | "local";
757
- source: "handwritten" | "generated" | "implicit";
758
- params: Array<{
759
- name: string;
760
- display: string;
761
- }>;
762
- returns?: string;
763
- };
764
- type InterfaceSurfaceOpts = {
765
- /** 覆盖项目配置的 autoBind(默认 findProjectConfig → interfaceConfig) */
766
- autoBind?: boolean;
767
- /** 模块源码装载器(测试注入);默认 defaultLoadModule 真实读盘 */
768
- loadModule?: LoadModule;
769
- /** 跨文件调用记录(--callsites 采集):implicit 展示的实参域原料 */
770
- records?: CallRecord[];
257
+ type MockModuleApplyResult = {
258
+ modules: Record<string, AbsModuleExports>;
259
+ errors: FromMockError[];
260
+ /** true when at least one mock-module directive was applied */
261
+ applied: boolean;
771
262
  };
772
- /** 单条 interface 打印行(CLI runInterface 与 LSP agent 面共用) */
773
- declare function formatInterfaceSurfaceLine(e: InterfaceSurfaceEntry): string;
774
263
  /**
775
- * 单文件 interface 表面:analyzer 推断结果给出函数清单与 implicit 展示,
776
- * effectiveInterface 给出契约命中(手写 > 生成段)。诊断 side-channel
777
- * 在收尾时取走丢弃——打印命令不执法,interface-load 等错误留给 check 路径。
264
+ * Overlay `@nudo:mock-module` directives onto a modules map.
265
+ * `base` is not mutated; a new map is returned.
778
266
  */
779
- declare function interfaceSurface(filePath: string, opts?: InterfaceSurfaceOpts): Promise<InterfaceSurfaceEntry[]>;
267
+ declare function applyMockModuleDirectives(base: Record<string, AbsModuleExports>, fileDirectives: FileDirective[], opts: {
268
+ fromFile: string;
269
+ loadModule?: LoadModule;
270
+ }): MockModuleApplyResult;
271
+ /** Source string → apply mock-module (CLI / one-shot hosts). */
272
+ declare function applyMockModuleDirectivesFromSource(source: string, base: Record<string, AbsModuleExports>, opts: {
273
+ fromFile: string;
274
+ loadModule?: LoadModule;
275
+ }): MockModuleApplyResult;
780
276
 
781
277
  /**
782
- * `nudo interface --emit` 的写盘器(design-refine-derivation §5.4 / §7.3 / §11):
783
- * 把分析产出的调用点域投影(joinThenProject,先 Abs join 再投影)固化为侧车
784
- * `*.nudo.js` / `*.nudo.ts` 的 `@generated` 段——`export const <fn> = fn({…}, …)`。
278
+ * B5:workspace 级 AnalysisSession——LSP 与 CLI(同进程)共享的分析 memo 面。
785
279
  *
786
- * - 生成段 = 三行:`@generated` 头注释 + `// source: <相对file>:<fn>` + export 行。
787
- * DSL 由 formatConstraint 产出,**写入前 round-trip 自检**(生成文本经
788
- * execNudoModule 求值、导出须 isNudoConstraint 且 fn 槽存在):展示兜底形态
789
- * (`x?:` 可选字段、`.eq()` 伪链、`{谓词原文}`)不是合法 DSL,自检拦下 →
790
- * not-projectable 跳过,不写垃圾。
791
- * - 手写导出永不覆盖:目标名已是侧车手写绑定 → 跳过写入并报
792
- * `nudo:interface-name-clash`(error,手写优先)。
793
- * - mode=update:剥离全部生成段再重排(幂等;非目标的既有生成段原样保留,
794
- * 不随 --fn 丢失);mode=add:仅追加缺失段。
795
- * - 目标过滤(§7.3):--fn 白名单 > --all 全量 > 默认只刷新已有生成段
796
- * (「无根只处理已存在生成段」;Phase 1 无 root 闭包下行推导)。
797
- * - autoBind=false 不影响 emit(显式动作,非 ambient 加载)。
798
- */
799
-
800
- type EmitInterfaceSkipReason = "name-clash" | "not-projectable" | "not-an-export" | "no-change"
801
- /** package.json#nudo.interface.emit 白名单拒绝 */
802
- | "emit-denied"
803
- /** 手工合并的多声明符 @generated 段:按段原子保留,不拆不重写 */
804
- | "multi-declarator";
805
- type EmitInterfaceOpts = {
806
- /** 目标导出名白名单(Phase 1:只过滤目标文件自身的导出;跨文件 root 闭包 emit 是 Phase 2 下行推导能力) */
807
- fnNames?: string[];
808
- /** update=剥离全部生成段再重排(幂等);add=仅追加缺失段 */
809
- mode: "add" | "update";
810
- /** 全部顶层导出(显式 opt-in,CLI 侧文档警告勿默认) */
811
- all?: boolean;
812
- /** 不写盘,返回 unifiedDiff */
813
- dryRun?: boolean;
814
- /**
815
- * 跨文件调用记录(--callsites 采集):域根导出(本文件无调用点、仅有
816
- * 外部使用现场记录)的投影原料;缺省时仅用本文件调用点证据。
817
- */
818
- records?: CallRecord[];
819
- };
820
- type EmitInterfaceResult = {
821
- written: string[];
822
- skipped: Array<{
823
- fn: string;
824
- reason: EmitInterfaceSkipReason;
825
- }>;
826
- changed: boolean;
827
- diff?: string;
828
- issues: Array<{
829
- code: string;
830
- severity: "error" | "warning";
831
- message: string;
832
- }>;
833
- /** 侧车绝对路径(新建或已有) */
834
- sidecarPath: string;
280
+ * core/service 的 analyzeFile / B-path / generalize / checkSource 都是
281
+ * 进程级模块缓存;本模块把「清空 / 定向逐出 / 依赖变更」收成一个显式
282
+ * session 对象,避免宿主各接一套失效逻辑,也便于测试隔离。
283
+ *
284
+ * 宿主契约:
285
+ * - 依赖内容变更 → `session.evictForDependents(files)`
286
+ * - 全量重置(watch 批前 / vite buildStart)→ `session.clear()`
287
+ * - LSP validate 与 agent check/hover/interface 在同一进程共用默认 session
288
+ */
289
+
290
+ type AnalysisSession = {
291
+ /** 依赖变更:按「以这些文件为入口」的路径定向逐出 */
292
+ evictForDependents(files: string[]): void;
293
+ /** 清空 service+core 会话 memo(不含 AST LRU) */
294
+ clear(): void;
295
+ /** 彻底重置(含 AST LRU) */
296
+ reset(): void;
835
297
  /**
836
- * 默认过滤(无 --fn/--all)且侧车无既有 @generated 段可刷 —— 调用方
837
- * 用它把「no interface changes」解释成首次 emit 的用法提示,而非漂移。
298
+ * 与 analyzeFile 同源,但强制走本 session 的 memo(进程内默认即共享)。
299
+ * LSP / CLI / agent 工具都应调用这里,而不是旁路第二套缓存。
838
300
  */
839
- emptyDefaultTargets?: boolean;
301
+ analyze(filePath: string, source: string, activeCases?: Map<string, number>, externalCallRecords?: unknown): AnalysisResult;
840
302
  };
303
+ /** 进程内默认 AnalysisSession(LSP server / CLI watch / agent tools 共用) */
304
+ declare function getAnalysisSession(): AnalysisSession;
305
+ /** 测试:替换默认 session(返回旧值以便恢复) */
306
+ declare function setAnalysisSession(session: AnalysisSession | undefined): AnalysisSession | undefined;
307
+
308
+ declare function clearAnalysisFileCache(): void;
309
+ declare function getAnalysisFileCacheSize(): number;
310
+ /** 立刻压到当前 maxFiles(调低上限时收内存) */
311
+ declare function trimAnalysisFileCache(): void;
312
+ /** 依赖变更后:按入口文件逐出 */
313
+ declare function evictAnalysisFileCacheForFiles(files: string[]): number;
314
+
315
+ /**
316
+ * 会话级内存 LRU 上限(进程内,非磁盘 cache)。
317
+ * 多项目开 LSP 时用 env 封顶内存;单大仓可调高换 warm 命中。
318
+ *
319
+ * 优先级:setSessionCacheLimits(显式)> env > package.json#nudo.sessionCache > 默认
320
+ *
321
+ * 覆盖面:analysis-file-cache(maxFiles)/ fn-analysis-cache(maxFns)/
322
+ * bpath-run(maxBRuns)。其余驻留结构(harvest-auto / harvest-node /
323
+ * abs-modules-graph / env-loader path-env / env-path-deps)用各自的硬上限常量,
324
+ * 见各文件与 lru-map.ts。所有上限加起来给出大仓分析后 retained 内存的上界。
325
+ */
326
+ type SessionCacheLimits = {
327
+ /** 整文件 AnalysisResult LRU;0 = 关闭 */
328
+ maxFiles: number;
329
+ /** per-fn FunctionAnalysis LRU;0 = 关闭 */
330
+ maxFns: number;
331
+ /** B-path run LRU;0 = 关闭 */
332
+ maxBRuns: number;
333
+ };
334
+ /** 保守默认:多项目共存时不悄悄吃内存(大仓请显式调高) */
335
+ declare const DEFAULT_SESSION_CACHE_LIMITS: SessionCacheLimits;
336
+ type PartialLimits = Partial<SessionCacheLimits>;
337
+ declare function getSessionCacheLimits(env?: NodeJS.ProcessEnv): SessionCacheLimits;
338
+ /** 显式覆盖(宿主 / 测试)。传 null 清除显式层 */
339
+ declare function setSessionCacheLimits(partial: PartialLimits | null): SessionCacheLimits;
340
+ /** package.json#nudo.sessionCache 层(findProjectConfig / 宿主接线) */
341
+ declare function setSessionCacheFromProject(partial: PartialLimits | null | undefined): void;
342
+ /** 测试:丢弃 env 惰性缓存,重新读 process.env */
343
+ declare function resetSessionCacheLimitState(): void;
344
+
841
345
  /**
842
- * 单文件 emit:分析 → 逐目标投影/自检 → 组装侧车内容 →(非 dryRun)写盘。
843
- * 诊断 side-channel(round-trip 自检触发的 refine/interface diags)收尾取走丢弃。
346
+ * 依赖内容变更后:按入口文件定向逐出 service 层缓存。
347
+ * 调用方应传「以这些文件为入口」的路径(脏集里的 dependents),
348
+ * 而不是变更的 dep 文件本身——dep 自己 source 变了会自然 miss。
349
+ * 残余缺口:absModuleCache 按 dep 路径 + mtime/size 键控;「同 size + 同 mtime」
350
+ * 编辑需再 evictAbsModuleCacheFiles([depPath]) 或 clearAnalysisSessionCaches。
844
351
  */
845
- declare function emitInterface(filePath: string, opts: EmitInterfaceOpts): Promise<EmitInterfaceResult>;
352
+ declare function evictAnalysisCachesForFiles(files: string[]): void;
846
353
  /**
847
- * emit 摘要行(CLI runInterfaceEmit 与 LSP agent 面共用;路径由调用方按
848
- * 展示口径传入——CLI 传 cwd 相对、agent 传绝对路径)。
354
+ * 清空全部会话级分析缓存(service + core)。
355
+ * 适用于:CLI watch 增量批前、vite buildStart / watchChange、测试隔离。
356
+ * 比定向逐出重,但保证无陈旧命中;单次 analyze 内部的 per-fn / generalize
357
+ * memo 不受影响(它们在同一轮里先写后读)。
849
358
  */
850
- declare function formatEmitSummary(sourcePath: string, sidecarRel: string, result: EmitInterfaceResult): string[];
851
-
359
+ declare function clearAnalysisSessionCaches(): void;
852
360
  /**
853
- * Root 驱动的契约下行(design-refine-derivation §4.2 / §11 Phase 2)。
854
- *
855
- * 对含手写契约根的文件(lib.nudo.js 绑定 add4):
856
- * 1. 从侧车 AST 抽出参数约束的源表达式(`positive` ← `./std.nudo.js`);
857
- * 2. constraintToEntryAbs + tagDerivationRoot;
858
- * 3. analyzeFn 求值 body(模块图注入下游),收集调用记录 + 推导打点;
859
- * 4. 闭包内下游导出投影为组合式 DSL,禁止事后从 Abs 反编译链。
860
- *
861
- * check 分轨:每条 root 链独立;join 只用于工件聚合(多调用者)。
361
+ * 接线 package.json#nudo.sessionCache(进程内 LRU 上限)并立刻 trim。
362
+ * env `NUDO_CACHE_MAX_FILES|FNS|BRUNS` 仍优先(多项目内存封顶)。
862
363
  */
364
+ declare function applySessionCacheConfig(config: NudoConfig | null | undefined): SessionCacheLimits;
365
+ /** 比 clearAnalysisSessionCaches 更彻底:再丢 AST LRU(测试 / 进程复用场景) */
366
+ declare function resetAllAnalysisCaches(): void;
863
367
 
864
- type ConstraintSourceExpr = {
865
- expr: string;
866
- importFrom?: string;
867
- importName?: string;
868
- };
869
- type DerivedParam = {
870
- name: string;
871
- constraint: NudoConstraint;
872
- dsl: string;
873
- prelude: string[];
874
- imports: Array<{
875
- name: string;
876
- from: string;
368
+ /**
369
+ * 磁盘内容寻址缓存(B3,design-persistent-cache.md L1 骨架)。
370
+ * - 键:sha256(analysisAbi + relative paths + content hashes + import deps)
371
+ * - fail-open:读写失败/版本不符 → miss,绝不 throw
372
+ * - 不存 Abs;只存可 JSON 再执行投影(如 CheckJson)
373
+ * - 缓存根解析见 `evaluator/config.ts` 的 `diskCacheRoot`(唯一入口)
374
+ *
375
+ * 内存上界:本层不持有进程内 map——每次 get/set 直读/直写磁盘,retained
376
+ * heap O(1)。磁盘容量不在本层封顶(由宿主/CI 清理 `diskCacheRoot`)。
377
+ * 进程内 LRU 上界见 session-cache-limits / lru-map.ts(analysis/fn/bpath/
378
+ * harvest/abs-module/path-env)。
379
+ */
380
+ /**
381
+ * 带包版本:升级 @nudojs/* 后旧 CheckJson 不得继续命中。
382
+ * 语义大改仍可手工再抬 major(`nudo-check-cache-v3`)。
383
+ */
384
+ declare const ANALYSIS_ABI: string;
385
+ type DiskCacheOptions = {
386
+ /** 缓存根目录;undefined = 禁用 */
387
+ root?: string | undefined;
388
+ /** 命名空间子目录(check / interface …) */
389
+ namespace: string;
390
+ };
391
+ declare function sha256Hex(data: string | Buffer): string;
392
+ /** 相对化路径,避免绝对路径进磁盘键;树外路径用稳定内容 hash */
393
+ declare function relativizePath(p: string, root?: string): string;
394
+ declare class DiskCache {
395
+ private readonly root;
396
+ private readonly ns;
397
+ enabled: boolean;
398
+ constructor(opts: DiskCacheOptions);
399
+ private pathFor;
400
+ get<T>(key: string): T | undefined;
401
+ set(key: string, value: unknown): void;
402
+ clearNamespace(): void;
403
+ }
404
+ /**
405
+ * check 报告键:abi + 相对路径 + 源码 sha + autoBind + **侧车 sha** +
406
+ * **@nudo:import / 传递契约依赖内容 sha**(依赖变更必须 miss)。
407
+ * dep 路径同样相对化(`relativizePath`):绝对路径进键会让同内容在不同
408
+ * 机器/checkout 上键不同,缓存无法跨环境复用。
409
+ */
410
+ declare function checkCacheKey(filePath: string, source: string, opts: {
411
+ autoBind: boolean;
412
+ projectDir?: string;
413
+ sidecarContent?: string | null;
414
+ depContents?: Array<{
415
+ path: string;
416
+ content: string | null;
877
417
  }>;
878
- /** 单链组合式投影时的推导图 root 节点 id(返回位相对锚定用) */
879
- rootNodeId?: number;
880
- /** 该参数位自 root 起消耗的 shift 步数(与 prelude 行数无关,读图) */
881
- shiftCount?: number;
882
- };
883
- type DerivedExport = {
884
- file: string;
885
- fn: string;
886
- paramNames: string[];
887
- params: DerivedParam[];
888
- returns?: {
889
- constraint: NudoConstraint;
890
- dsl: string;
891
- prelude: string[];
892
- imports: Array<{
893
- name: string;
894
- from: string;
895
- }>;
418
+ /** package.json#nudo.env 等项目维(named env 不在 path-dep 指纹里) */
419
+ projectEnvNames?: string[];
420
+ /** analysis knobs that can change check surface */
421
+ analysisCfg?: {
422
+ mode?: string;
423
+ evalMissingSlot?: string;
424
+ callSiteBudget?: number;
425
+ entryThrows?: string;
426
+ ignoreThrows?: string;
896
427
  };
897
- /** `lib.js:add4` */
898
- derivedFrom: string;
899
- compositional: boolean;
900
- underivable?: boolean;
901
- };
902
- type RootDeriveOpts = {
903
- loadModule?: LoadModule;
904
- autoBind?: boolean;
905
- fnNames?: string[];
906
- /**
907
- * true:只刷新目标侧车里**已存在**的 @generated 段(CLI 无 --fn/--all 时
908
- * 的默认行为——不发明新下游契约)。false/省略:闭包内全部可推导导出。
909
- */
910
- refreshExistingOnly?: boolean;
911
- };
912
- type RootDeriveResult = {
913
- roots: string[];
914
- derived: DerivedExport[];
915
- hasRoot: boolean;
916
- };
917
- /** 从侧车源码抽出 `export const f = fn({ x: positive }, ret)` 的约束源表达式 */
918
- declare function extractFnConstraintSources(sidecarSrc: string, fnName: string): {
919
- params: Record<string, ConstraintSourceExpr>;
920
- returns?: ConstraintSourceExpr;
921
- };
922
- /**
923
- * 入口:对 filePath 做 root 驱动下行推导。
924
- */
925
- declare function deriveFromRoot(filePath: string, opts?: RootDeriveOpts): RootDeriveResult;
428
+ }): string;
429
+ /**
430
+ * effectiveInterface 表键(L1 Phase B,design-persistent-cache)。
431
+ * 维度:相对路径 + 源码 sha256 + autoBind + 侧车内容 sha256 + import 依赖
432
+ * (dep 路径相对化,与 checkCacheKey 同口径)。
433
+ * **不含** emit allowlist(白名单不影响契约读取)。
434
+ */
435
+ declare function ifaceCacheKey(filePath: string, source: string, opts: {
436
+ autoBind: boolean;
437
+ projectDir?: string;
438
+ /** 侧车源码(已读入);undefined = 无侧车或 autoBind 关 */
439
+ sidecarSource?: string | undefined;
440
+ depContents?: Array<{
441
+ path: string;
442
+ content: string | null;
443
+ }>;
444
+ projectEnvNames?: string[];
445
+ }): string;
446
+ /** 从源码提取 `@nudo:import` / `@nudo:import * as` 的 specifier */
447
+ declare function extractNudoImportSpecs(source: string): string[];
448
+
926
449
  /**
927
- * 组装生成段(组合式 + import + prelude)。
928
- * importFrom 相对 root 侧车解析,再相对 target 侧车写出。
450
+ * nudo 推断目标文件判定(纯扩展名规则,路径无需存在)。
451
+ *
452
+ * 规则:.js / .mjs / .ts 可作为推断目标;其余扩展(.cjs/.tsx/.jsx/.mts/.d.ts…)
453
+ * 一律 false。显式排除:
454
+ * - .d.ts —— 类型声明文件(harvester 的输入),不是可求值的实现源码;
455
+ * - .tsx / .jsx —— JSX 构造的求值超出 nudo 推断器范围;
456
+ * - *.nudo.js / *.nudo.mjs / *.nudo.ts —— 侧车契约模块(interface 绑定源),
457
+ * 不是源码推断目标;目录级 check/infer/doctor 展开不得把它们当实现分析;
458
+ * - *.nudo.draft.js / *.nudo.draft.mjs / *.nudo.draft.ts —— draft 产物,
459
+ * 明确不被 ambient 绑定,也不得当实现源码分析。
929
460
  *
930
- * `takenNames`:侧车顶层已占用标识符(手写 / 既有生成段 / 本批先前段)。
931
- * 同文件多导出时对 import local 与 prelude local 做避让改写,
932
- * 保证拼出的侧车在模块作用域内无重复声明。
461
+ * 消费方:CLI 的 collectNudoFiles/watch 过滤/doctor 目录展开(.ts 放开后统一
462
+ * 走本函数,避免各处手写 endsWith 漂移),以及 LSP 的 isNudoFile(接线由
463
+ * LSP 侧负责)。
933
464
  */
934
- declare function formatDerivedSection(row: DerivedExport, opts: {
935
- rootSidecarDir: string;
936
- targetSidecarDir: string;
937
- takenNames?: Iterable<string>;
938
- }): {
939
- text: string;
940
- usedNames: string[];
941
- } | undefined;
942
- type EmitDerivedResult = {
943
- /** 被写/将写的下游侧车(绝对路径) */
944
- sidecars: Array<{
945
- file: string;
946
- sidecarPath: string;
947
- fn: string;
948
- written: boolean;
949
- changed: boolean;
950
- skipped?: "name-clash" | "not-projectable" | "underivable" | "no-change";
951
- diff?: string;
952
- issues: Array<{
953
- code: string;
954
- severity: "error" | "warning" | "info";
955
- message: string;
956
- }>;
957
- }>;
958
- hasRoot: boolean;
959
- roots: string[];
960
- /** 根在别处 / 无契约根且无已存在生成段 → info */
961
- entryOnly?: boolean;
962
- };
963
- declare function emitDerivedFromRoot(rootFile: string, opts: {
964
- fnNames?: string[];
965
- mode: "add" | "update";
966
- dryRun?: boolean;
967
- loadModule?: LoadModule;
968
- autoBind?: boolean;
969
- /** 只刷新目标侧车里已存在的 @generated 段(不发明新下游契约) */
970
- refreshExistingOnly?: boolean;
971
- }): EmitDerivedResult;
465
+ declare function isNudoTargetPath(path: string): boolean;
972
466
 
973
- export { type AbsGraphOptions, type AbsMockSeeds, type AbsModuleCacheEntry, type AbsModuleGraphResult, type AbsModuleLoadIssue, type AnalysisResult, type BPathBuiltinUnknown, type BPathDiagnostics, type BPathRunResult, type BPathUnreachable, type BindingInfo, CallRecord, type CaseHint, type CaseInfo, type CaseResult, type CompletionItem, type ConstraintSourceExpr, type DerivedExport, type DerivedParam, type Diagnostic, type DiagnosticSeverity, type DiagnosticTag, type EmitDerivedResult, type EmitInterfaceOpts, type EmitInterfaceResult, type EmitInterfaceSkipReason, type EmitResult, type EmitSkipReason, type FunctionAnalysis, type HoverInfo, type InferJson, type InferJsonCase, type InferJsonFunction, type InterfaceSurfaceEntry, type InterfaceSurfaceOpts, type LoadModule, type ModuleExports, type ModuleGraphCache, type NodeEnvResult, type PackageHarvest, type ReferenceInfo, type RootDeriveOpts, type RootDeriveResult, SEMANTIC_TOKEN_MODIFIERS, SEMANTIC_TOKEN_TYPES, type SemanticToken, type SourceLocation, type SymbolInfo, type SymbolTable, absToTSType, absToZodSchema, analyzeExportsFromSource, analyzeFile, analyzeFileAsync, autoHarvestModules, barePackageName, bareSpecToAbsModules, buildCaseDirective, buildModuleGraph, buildSemanticTokens, clearAbsModuleCache, clearAnalysisFileCache, clearAnalysisSessionCaches, clearBPathCache, clearFnAnalysisCache, clearHarvestCache, collectAbsBindingsFromGraph, collectBPathDiagnostics, collectBPathReplacements, collectBarePackages, collectCallRecords, collectDependencySpecs, collectDtsFromEntry, collectEnvGlobals, collectEnvModules, collectStaticImports, computeDirtySet, defaultAbsLoadModule, defaultLoadModule, deriveFromRoot, emitDerivedFromRoot, emitInterface, encodeSemanticTokens, evalAbsModuleGraph, evalProgramAbsWithModules, evictAbsModuleCacheFiles, evictAnalysisCachesForFiles, evictAnalysisFileCacheForFiles, evictBPathCacheForFiles, evictFnAnalysisCacheForFiles, extractFnConstraintSources, formatDerivedSection, formatEmitSummary, formatHarvestSummary, formatInterfaceSurfaceLine, generateDts, generateFunctionDtsLines, generateGuardFunction, generateGuardFunctionFromAbs, getAbsAtPosition, getAbsAtPositionAsync, getAnalysisFileCacheSize, getCasesForFile, getCompletionsAtPosition, getHoverAtPosition, getTypeAtPosition, getTypeAtPositionAsync, harvestNodeTypes, harvestPackage, harvestPackageCached, harvestToAbsModules, harvestedValueToAbs, insertGeneratedCaseDirectives, interfaceSurface, isBPathCapable, isNudoTargetPath, lookupHarvested, mockDirectivesToAbsSeeds, packageHarvestToAbsModules, resetAllAnalysisCaches, resolvePackageRoot, serializeCaseArg, serializeInferJson, stripGeneratedCaseDirectives, summarizeNodeEnv, topoSortDirty, tryBPathCall, tryBPathCallFull, tryRunBPath, unifiedDiff };
467
+ /** Formal sidecar contracts only — drafts never ambient-bind and need not reanalyze */
468
+ declare function isSidecarPath(path: string): boolean;
469
+ declare function isProjectConfigPath(path: string): boolean;
470
+ /** Watch accept gate: analysis targets + sidecar/config/env-template invalidators */
471
+ declare function isWatchRelevantPath(path: string): boolean;
472
+ /** `lib.nudo.js|ts` → candidate ambient sources next to it */
473
+ declare function ambientSourcesOfSidecar(sidecarPath: string): string[];
474
+
475
+ /** 测试/诊断:反向依赖驻留规模 */
476
+ declare function getEnvPathDepsSize(): number;
477
+ /** 源码里的 path-based load specs 解析为绝对路径后登记反向边 */
478
+ declare function noteEnvPathDeps(sourcePath: string, source: string): void;
479
+ /** 依赖该 env 模板的源文件列表 */
480
+ declare function envPathDependents(envPath: string): string[];
481
+ declare function clearEnvPathDeps(): void;
482
+ /** watch 门禁:env 模板变更必须可被接收(即便扩展名不进 isNudoTargetPath) */
483
+ declare function isEnvTemplatePath(path: string): boolean;
484
+
485
+ export { ANALYSIS_ABI, type AbsMockSeeds, AnalysisResult, type AnalysisSession, type BPathBuiltinUnknown, type BPathDiagnostics, type BPathUnreachable, CallRecord, DEFAULT_SESSION_CACHE_LIMITS, type DepContent, DirectiveCaseMode, DiskCache, type DiskCacheOptions, type EntryVariantInfo, type EntryVariantIssue, LoadModule, type MockModuleApplyResult, type ModuleExports, NudoConfig, type SessionCacheLimits, ambientSourcesOfSidecar, analysisFileCacheKey, analyzeExportsFromSource, applyMockModuleDirectives, applyMockModuleDirectivesFromSource, applySessionCacheConfig, checkCacheKey, clearAnalysisFileCache, clearAnalysisSessionCaches, clearEnvPathDeps, clearFnAnalysisCache, collectBPathDiagnostics, collectDependencySpecs, collectLoadDepContents, collectSkipReturns, collectStaticImports, detectEntryVariantsFromPackageJson, entryVariantForFile, entryVariantIssueForFile, envPathDependents, evictAnalysisCachesForFiles, evictAnalysisFileCacheForFiles, evictFnAnalysisCacheForFiles, extractNudoImportSpecs, findOwningPackage, getAnalysisFileCacheSize, getAnalysisSession, getEnvPathDepsSize, getFnAnalysisCacheSize, getSessionCacheLimits, ifaceCacheKey, isEnvTemplatePath, isNudoTargetPath, isProjectConfigPath, isSidecarPath, isWatchRelevantPath, mockDirectivesToAbsSeeds, mockSeedsForSource, mockSeedsToAbsMocks, noteEnvPathDeps, relativizePath, resetAllAnalysisCaches, resetSessionCacheLimitState, setAnalysisSession, setSessionCacheFromProject, setSessionCacheLimits, sha256Hex, trimAnalysisFileCache, trimFnAnalysisCache };