@nudojs/core 0.3.1 → 1.0.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.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Node, File } from '@babel/types';
2
- import { P as Phi, A as AstEnv, a as Abs, C as Confidence, b as Pred, S as Shape, c as PrimName, T as Term, R as RelSource, H as HofSite, L as LeakBudget } from './index-CVYjXnwU.js';
3
- export { $ as $add, d as $arr, e as $async, f as $asyncReturn, g as $await, h as $call, i as $callNamed, j as $catchVal, k as $class, l as $concat, m as $div, n as $elems, o as $eq, p as $fnVal, q as $for, r as $forIter, s as $forOf, t as $fork, u as $ge, v as $gen, w as $get, x as $gt, y as $idx, z as $idxSet, B as $invoke, D as $invokeSuper, E as $join, F as $le, G as $len, I as $lit, J as $lt, K as $mod, M as $mul, N as $ne, O as $neg, Q as $new, U as $not, V as $obj, W as $optionalGet, X as $optionalInvoke, Y as $orDefault, Z as $set, _ as $setKey, a0 as $spread, a1 as $staticInvoke, a2 as $sub, a3 as $super, a4 as $switch, a5 as $thisGet, a6 as $thisSet, a7 as $throw, a8 as $typeof, a9 as $while, aa as $whileSeq, ab as $yield, ac as AbsAssignRecord, ad as AbsCallRecord, ae as AbsModuleExports, af as BCallRecord, ag as BClassSpec, ah as BMemberDiag, ai as DEFAULT_MAX_LOOP_ITERS, aj as EvalOptions, ak as EvalResult, al as HofCollectCtx, am as MAX_CALL_DEPTH, an as MAX_TOTAL_CALLS, ao as NudoThrow, ap as RunTranspiledOptions, aq as TranspileOptions, ar as TranspiledCallResult, as as abs, at as absToString, au as alphaOf, av as analyzeFn, aw as and, ax as anyVar, ay as app, az as applyAbsFn, aA as applyCallbackAbs, aB as asAbs, aC as asAbsVal, aD as betaOf, aE as bindImports, aF as bool, aG as boolLit, aH as callFunction, aI as callTranspiledExport, aJ as callTranspiledExportFull, aK as clearBClasses, aL as collectAbsExports, aM as collectAbsNodeTypes, aN as confJoin, aO as createHofCollectCtx, aP as currentExecPhi, aQ as defaultLeakBudget, aR as emptyEnv, aS as emptyPhi, aT as eq, aU as evalMethodBody, aV as evalNode, aW as evalProgramAbs, aX as evalSource, aY as exceedsBudget, aZ as findAbsAtPosition, a_ as ge, a$ as geNum, b0 as getAbsOrigin, b1 as getBCallCollector, b2 as getBClass, b3 as gt, b4 as gtNum, b5 as implies, b6 as instantiateReturn, b7 as isDefinitelyFalse, b8 as isDefinitelyTrue, b9 as isExactLit, ba as isNudoThrow, bb as isNumPrim, bc as isRelFn, bd as isStrPrim, be as le, bf as leNum, bg as leakIfNeeded, bh as lit, bi as litValue, bj as lt, bk as ltNum, bl as mapElementFallback, bm as maybeLeak, bn as ne, bo as never, bp as not, bq as noteMemberDispatchMiss, br as notePrimMemberMissing, bs as noteUnknownMemberMissing, bt as num, bu as numLit, bv as numVar, bw as obj, bx as or, by as pFalse, bz as pTrue, bA as phiAnd, bB as predEquals, bC as predToString, bD as predVars, bE as projectFlatMapResult, bF as promoteParamShape, bG as ptypeof, bH as recordMemberDiag, bI as registerBClass, bJ as resetAbsCallBudget, bK as resetLeakCounter, bL as runTranspiled, bM as setAbsAssignCollector, bN as setAbsCallCollector, bO as setAbsNodeCollector, bP as setAbsTruncationCollector, bQ as setApplyCallbackHost, bR as setBCallCollector, bS as setMemberDiagCollector, bT as shapeOfTerm, bU as shapeToString, bV as simplifyTerm, bW as snapshotAbs, bX as str, bY as strLit, bZ as substAbs, b_ as substPred, b$ as substPredAbs, c0 as tagAbsOrigin, c1 as termDepth, c2 as termEquals, c3 as termNodes, c4 as termToString, c5 as transpile, c6 as transpileExpression, c7 as transpileFile, c8 as transpileSource, c9 as tryPromoteDirectCall, ca as tryPromoteForOfIteratee, cb as tryPromoteHofCallback, cc as tryPromoteReceiverAsArr, cd as undefAbs, ce as unknown, cf as v, cg as withExecPhi, ch as withVar } from './index-CVYjXnwU.js';
2
+ import { P as Phi, A as AstEnv, a as Abs, C as Confidence, b as Pred, S as Shape, T as Term, c as AbsModuleExports, d as PrimName, R as RelSource, H as HofSite } from './index-OfNo5qlN.js';
3
+ export { $ as $add, e as $arr, f as $async, g as $asyncReturn, h as $await, i as $call, j as $callNamed, k as $catchVal, l as $class, m as $concat, n as $div, o as $elems, p as $eq, q as $fnVal, r as $for, s as $forIter, t as $forOf, u as $fork, v as $ge, w as $gen, x as $get, y as $gt, z as $idx, B as $idxSet, D as $invoke, E as $invokeSuper, F as $join, G as $le, I as $len, J as $lit, K as $lt, L as $mod, M as $mul, N as $ne, O as $neg, Q as $new, U as $not, V as $obj, W as $optionalGet, X as $optionalInvoke, Y as $orDefault, Z as $regex, _ as $set, a0 as $setKey, a1 as $spread, a2 as $staticInvoke, a3 as $sub, a4 as $super, a5 as $switch, a6 as $thisGet, a7 as $thisSet, a8 as $throw, a9 as $typeof, aa as $while, ab as $whileSeq, ac as $yield, ad as BCallRecord, ae as BClassSpec, af as BMemberDiag, ag as DEFAULT_MAX_LOOP_ITERS, ah as HofCollectCtx, ai as NudoThrow, aj as RunTranspiledOptions, ak as TranspileOptions, al as TranspiledCallResult, am as abs, an as absToString, ao as alphaOf, ap as and, aq as anyVar, ar as app, as as applyCallbackAbs, at as asAbs, au as asAbsVal, av as betaOf, aw as bindImports, ax as bool, ay as boolLit, az as callTranspiledExport, aA as callTranspiledExportFull, aB as clearBClasses, aC as collectAbsExports, aD as confJoin, aE as createHofCollectCtx, aF as currentExecPhi, aG as emptyPhi, aH as eq, aI as ge, aJ as geNum, aK as getAbsOrigin, aL as getBCallCollector, aM as getBClass, aN as gt, aO as gtNum, aP as implies, aQ as instantiateReturn, aR as isDefinitelyFalse, aS as isDefinitelyTrue, aT as isExactLit, aU as isNudoThrow, aV as isNumPrim, aW as isRelFn, aX as isStrPrim, aY as le, aZ as leNum, a_ as lit, a$ as litTruth, b0 as litValue, b1 as lt, b2 as ltNum, b3 as mapElementFallback, b4 as namespaceNameOf, b5 as ne, b6 as never, b7 as not, b8 as noteMemberDispatchMiss, b9 as notePrimMemberMissing, ba as noteUnknownMemberMissing, bb as num, bc as numLit, bd as numVar, be as obj, bf as or, bg as pFalse, bh as pTrue, bi as phiAnd, bj as predEquals, bk as predToString, bl as predVars, bm as projectFlatMapResult, bn as promoteParamShape, bo as ptypeof, bp as recordMemberDiag, bq as registerBClass, br as runTranspiled, bs as setApplyCallbackHost, bt as setBCallCollector, bu as setMemberDiagCollector, bv as shapeOfTerm, bw as shapeToString, bx as simplifyTerm, by as snapshotAbs, bz as str, bA as strLit, bB as substAbs, bC as substPred, bD as substPredAbs, bE as tagAbsOrigin, bF as termEquals, bG as termToString, bH as transpile, bI as transpileExpression, bJ as transpileFile, bK as transpileSource, bL as tryPromoteDirectCall, bM as tryPromoteForOfIteratee, bN as tryPromoteHofCallback, bO as tryPromoteReceiverAsArr, bP as undefAbs, bQ as unknown, bR as v, bS as withExecPhi } from './index-OfNo5qlN.js';
4
4
 
5
5
  type Environment = {
6
6
  lookup(name: string): TypeValue;
@@ -153,8 +153,6 @@ declare function dispatchProperty(receiver: TypeValue, name: string): TypeValue
153
153
  */
154
154
  declare function isTemplate(tv: TypeValue): boolean;
155
155
 
156
- declare function getKnownPrefix(parts: TypeValue[]): string;
157
- declare function getKnownSuffix(parts: TypeValue[]): string;
158
156
  declare function createTemplate(parts: TypeValue[]): TypeValue;
159
157
 
160
158
  declare function getTemplateParts(tv: TypeValue): TypeValue[] | undefined;
@@ -163,6 +161,10 @@ declare function concatTemplates(left: TypeValue, right: TypeValue): TypeValue;
163
161
  type RangeMeta = {
164
162
  min?: number;
165
163
  max?: number;
164
+ /** 下界开区间:value > min(JS 实数,不能写成 >= min+1) */
165
+ minExclusive?: boolean;
166
+ /** 上界开区间:value < max */
167
+ maxExclusive?: boolean;
166
168
  integer?: boolean;
167
169
  };
168
170
  declare function createRange(meta: RangeMeta): TypeValue;
@@ -231,6 +233,7 @@ declare function resetParseSourceCache(): void;
231
233
  declare function getParseSourceCacheSize(): number;
232
234
  declare function parseSource(source: string, opts?: {
233
235
  errorRecovery?: boolean;
236
+ keepTs?: boolean;
234
237
  }): File;
235
238
 
236
239
  /**
@@ -321,21 +324,6 @@ declare function shapeOnlyFn(paramTypes: Abs[], returnType: Abs, opts?: {
321
324
  * 无契约的 score(x){return x+1}:score("x") 合法,不得钉成 number。
322
325
  */
323
326
  declare function add(a: Abs, b: Abs, phi?: Phi): Abs;
324
- type NumBounds = {
325
- lo?: {
326
- value: number;
327
- strict: boolean;
328
- };
329
- hi?: {
330
- value: number;
331
- strict: boolean;
332
- };
333
- };
334
- /**
335
- * 提取 Abs 上相对 term 的数值界。
336
- * 优先用自身 pred;否则查 Φ(针对 var id)。
337
- */
338
- declare function numericBounds(a: Abs, phi?: Phi): NumBounds | undefined;
339
327
  /** 减法:a - b = a + (-b),数值上做单调性 */
340
328
  declare function sub(a: Abs, b: Abs, phi?: Phi): Abs;
341
329
  /** 乘法:字面量直接求值;×正数同向缩放;×负数翻转不等式;×0 归零 */
@@ -354,6 +342,21 @@ declare function mod(a: Abs, b: Abs, phi?: Phi): Abs;
354
342
  declare function cmp(op: "lt" | "le" | "gt" | "ge" | "eq" | "ne", a: Abs, b: Abs, phi?: Phi): Abs;
355
343
  /** 从比较结果 Abs 提取「若为真」的额外约束(供 if 使用) */
356
344
  declare function trueConstraint(c: Abs): Pred | undefined;
345
+ /**
346
+ * 关系比较为真时收窄操作数 shape。
347
+ * `x > k` 对 any:JS 只允许 number(n>k)或数字字符串(ToNumber(s)>k)。
348
+ * 粗化展示为 `number>… | string`;string 臂不挂 ToNumber pred(Pred 无该构造)。
349
+ */
350
+ declare function refineAbsForRelTrue(a: Abs, op: "gt" | "ge" | "lt" | "le", k: number): Abs;
351
+ /**
352
+ * 从 Identifier 在比较中的位置解析「对哪个变量、用哪个关系」。
353
+ * 支持 `x > 3` 与 `3 < x`(后者关系翻转)。
354
+ */
355
+ declare function matchRelIdentLit(test: unknown): {
356
+ name: string;
357
+ op: "gt" | "ge" | "lt" | "le";
358
+ k: number;
359
+ } | undefined;
357
360
  declare function falseConstraint(c: Abs): Pred | undefined;
358
361
 
359
362
  /**
@@ -414,6 +417,7 @@ declare function evalBuiltinInstanceMethod(brandName: string, method: string, re
414
417
  * Abs 方法表:模板字符串 / 结构值上的方法与属性。
415
418
  * 类型即计算——方法结果仍是 Abs,可继续参与约束推理。
416
419
  * 宿主 TypeValue 的 dispatchMethod 只服务 IR 兜底,不是真理源。
420
+ * 模板语义(前缀/后缀/固定文本/长度/谓词判定)统一在 template.ts。
417
421
  */
418
422
 
419
423
  /**
@@ -423,6 +427,29 @@ declare function callAbsMethod(recv: Abs, name: string, args: Abs[]): Abs | unde
423
427
  /** 属性读取:template/string.length 等 */
424
428
  declare function getAbsProperty(recv: Abs, name: string): Abs | undefined;
425
429
 
430
+ /**
431
+ * 项(Term)防爆炸:深度/宽度阈值 → leak 为新鲜 var + 等式约束。
432
+ */
433
+
434
+ type LeakBudget = {
435
+ maxDepth: number;
436
+ maxNodes: number;
437
+ };
438
+ declare const defaultLeakBudget: LeakBudget;
439
+ declare function termDepth(t: Term): number;
440
+ declare function termNodes(t: Term): number;
441
+ declare function exceedsBudget(t: Term, budget?: LeakBudget): boolean;
442
+ declare function resetLeakCounter(): void;
443
+ /**
444
+ * 若项超预算,替换为新鲜变量,并返回附加等式 pred:fresh = originalTerm。
445
+ * 未超预算则原样返回。
446
+ */
447
+ declare function maybeLeak(a: Abs, budget?: LeakBudget, label?: string): Abs;
448
+ /**
449
+ * 批量:在算术结果上应用 leak。
450
+ */
451
+ declare function leakIfNeeded(a: Abs, budget?: LeakBudget, label?: string): Abs;
452
+
426
453
  /**
427
454
  * 结构层:对象槽位、spread、函数重载并。
428
455
  * 纪律:积之和默认;optional 塌缩是显式损失;函数并保输入→输出相关性。
@@ -452,6 +479,15 @@ declare function objOf(slots: Record<string, Slot>, opts?: {
452
479
  declare function isObj(a: Abs): a is Abs & {
453
480
  shape: ObjShape;
454
481
  };
482
+ /**
483
+ * 自有槽位读取。slots 是普通对象,直接 `slots[key]` 会让 `__proto__` /
484
+ * `toString` / `valueOf` 等键命中 Object.prototype 原型链,得到既非 slot
485
+ * 又 truthy 的原生值(历史 bug 模式,已两次复发)。所有跨来源 key 的槽位
486
+ * 读取必须走这里。
487
+ */
488
+ declare function getSlot<S extends {
489
+ value: Abs;
490
+ }>(slots: Record<string, S>, key: string): S | undefined;
455
491
  /**
456
492
  * spread:base ⊕ over(右侧覆盖,不是 join)
457
493
  * 未出现在 over 的 key 保留 base;over 的 key 覆盖。
@@ -465,11 +501,6 @@ declare function joinObjects(a: Abs, b: Abs): Abs;
465
501
  /** 值级 join:字面量保留为… Phase A 对 prim 做 term 保留策略 */
466
502
  declare function joinValues(a: Abs, b: Abs): Abs;
467
503
  declare function makeSum(a: Abs, b: Abs): Abs;
468
- /**
469
- * 显式损失:sum-of-products → optional 槽(仅 emit/阈值)。
470
- * 强制 #widened。
471
- */
472
- declare function collapseToOptional(sum: Abs): Abs;
473
504
  type FnAbs = Abs & {
474
505
  shape: {
475
506
  k: "fn";
@@ -514,6 +545,143 @@ declare function leqAbs(src: Abs, tgt: Abs, opts?: {
514
545
  env?: AstEnv;
515
546
  }): LeqResult;
516
547
 
548
+ /**
549
+ * Babel AST 抽象求值:把「类型即计算」接到真实 JS 源码。
550
+ * 支持表达式、函数声明/箭头、return、if、const/let、块作用域、类、循环。
551
+ */
552
+
553
+ declare function emptyEnv(): AstEnv;
554
+ declare function withVar(env: AstEnv, name: string, value: Abs): AstEnv;
555
+ type EvalOptions = {
556
+ phi?: Phi;
557
+ budget?: LeakBudget;
558
+ /** 预解析 AST(check 等批量场景避免重复 parse) */
559
+ file?: File;
560
+ /** host 已求值的相对依赖导出表 */
561
+ modules?: Record<string, AbsModuleExports>;
562
+ };
563
+ declare const MAX_CALL_DEPTH = 64;
564
+ declare const MAX_TOTAL_CALLS = 200000;
565
+ /** 宿主入口(evalProgramAbs / analyzeFn / check)前重置 */
566
+ declare function resetAbsCallBudget(): void;
567
+ /** 记录被截断的递归(service 可映射为 nudo:recursion-truncated) */
568
+ declare function setAbsTruncationCollector(collector: ((fnLabel: string) => void) | null): void;
569
+ /** Abs 域调用记录(自包含程序可不经 TypeValue evaluator) */
570
+ type AbsCallRecord = {
571
+ fnName: string;
572
+ args: Abs[];
573
+ result: Abs;
574
+ callLoc?: {
575
+ line: number;
576
+ column: number;
577
+ };
578
+ threw?: boolean;
579
+ };
580
+ declare function setAbsCallCollector(collector: ((r: AbsCallRecord) => void) | null): void;
581
+ declare function setAbsNodeCollector(collector: ((node: Node, value: Abs) => void) | null): void;
582
+ /** 赋值记录:结构可赋值检查用 */
583
+ type AbsAssignRecord = {
584
+ name: string;
585
+ prev?: Abs;
586
+ next: Abs;
587
+ line?: number;
588
+ column?: number;
589
+ /** 分支/循环体内发生:可变绑定在路径上取并集是合法 JS,不参与结构检查 */
590
+ conditional?: boolean;
591
+ };
592
+ declare function setAbsAssignCollector(collector: ((r: AbsAssignRecord) => void) | null): void;
593
+ type EvalResult = {
594
+ value: Abs;
595
+ phi: Phi;
596
+ env: AstEnv;
597
+ /** 函数已通过 return 跳出,块内后续语句不可达 */
598
+ returned?: boolean;
599
+ /** break 跳出最近循环 */
600
+ brk?: boolean;
601
+ /** continue 进入下一轮 */
602
+ cont?: boolean;
603
+ /** throw 了 value(未捕获时向上传播) */
604
+ threw?: boolean;
605
+ /**
606
+ * if 无 else 且 consequent 已 return/throw:真分支已产出 value,
607
+ * 假分支 fall-through 仍可能走后续语句。evalBlock 需与后续结果 join。
608
+ */
609
+ partialReturn?: boolean;
610
+ };
611
+ /**
612
+ * 分析一段 JS 源码。
613
+ * 若含多个顶层函数声明,先注册全部,再对 `main` 或最后一个有调用的函数求值。
614
+ * 更简单:提供 `analyzeFunction(source, fnName, args)`。
615
+ */
616
+ declare function evalSource(source: string, entry: {
617
+ fn: string;
618
+ args: Abs[];
619
+ }, opts?: EvalOptions): EvalResult;
620
+ declare function callFunction(env: AstEnv, name: string, args: Abs[], phi?: Phi, budget?: LeakBudget): Abs;
621
+ /**
622
+ * 在 this=receiver 下求值方法体。
623
+ * constructor 无显式 return 时返回更新后的 this(字段写入已并入 env)。
624
+ */
625
+ declare function evalMethodBody(method: {
626
+ params: string[];
627
+ body: Node;
628
+ async?: boolean;
629
+ kind?: string;
630
+ }, args: Abs[], thisVal: Abs, env: AstEnv, phi?: Phi, budget?: LeakBudget,
631
+ /** 方法定义所在类名(用于 super 派发) */
632
+ ownerClass?: string): Abs;
633
+ /** 对外入口:求值并记入节点表(Map<Node, Abs> 由 collector 消费) */
634
+ declare function evalNode(node: Node, env: AstEnv, phi: Phi, budget: LeakBudget): EvalResult;
635
+ /**
636
+ * 应用 Abs 一等函数。统一顺序:apply → body → relation → isRelFn。
637
+ * 调用门须扩为 `getFnImpl || isRelFn`,否则 E 路径永远进不来。
638
+ */
639
+ declare function applyAbsFn(fnVal: Abs, args: Abs[], env: AstEnv, phi: Phi, budget: LeakBudget): Abs;
640
+ /**
641
+ * 从源码分析指定函数在给定实参下的抽象结果。
642
+ *
643
+ * @example
644
+ * analyzeFn(`
645
+ * const add = (a, b) => a + b;
646
+ * function scale(x) { return add(x, 1); }
647
+ * `, "scale", [numVar("x", gtNum(v("x"), 0))], gtNum(v("x"), 0))
648
+ */
649
+ declare function analyzeFn(source: string, fnName: string, args: Abs[], phi?: Phi, budget?: LeakBudget, file?: File, modules?: Record<string, AbsModuleExports>): Abs;
650
+ /**
651
+ * 程序级 Abs 求值:注册全部顶层函数/class,再顺序执行语句。
652
+ * 返回最终 env(vars 含导出绑定)。TypeValue 仅在调用方 bridge 时出现。
653
+ *
654
+ * seedVars / seedFns:host 注入(@nudo:mock 等)在求值前绑定。
655
+ * modules:host 已求值的依赖导出表(specifier → AbsModuleExports)。
656
+ */
657
+ declare function evalProgramAbs(source: string, opts?: EvalOptions & {
658
+ seedVars?: Record<string, Abs>;
659
+ seedFns?: Record<string, {
660
+ params: string[];
661
+ body: Node;
662
+ async?: boolean;
663
+ }>;
664
+ modules?: Record<string, AbsModuleExports>;
665
+ }): {
666
+ env: AstEnv;
667
+ last: Abs;
668
+ phi: Phi;
669
+ };
670
+ /**
671
+ * 收集整文件的节点 → Abs 表(LSP 无损信息源)。
672
+ * 自包含源码上一次 evalProgramAbs 即可;失败返回空表。
673
+ */
674
+ declare function collectAbsNodeTypes(source: string, opts?: EvalOptions & {
675
+ seedVars?: Record<string, Abs>;
676
+ seedFns?: Record<string, {
677
+ params: string[];
678
+ body: Node;
679
+ async?: boolean;
680
+ }>;
681
+ }): Map<Node, Abs>;
682
+ /** 按 loc 找最紧的节点 Abs(hover 用) */
683
+ declare function findAbsAtPosition(nodeTypes: Map<Node, Abs>, line: number, column: number): Abs | undefined;
684
+
517
685
  /**
518
686
  * 格式化:把 Abs 渲染成人类可读 / CLI 友好的字符串。
519
687
  */
@@ -532,6 +700,26 @@ declare function formatShape(a: Abs): string;
532
700
  /** 多行展示,CLI 用 */
533
701
  declare function formatAbsMultiline(a: Abs, label?: string): string;
534
702
 
703
+ /**
704
+ * 侧车/依赖路径纯函数(leaf 模块:零依赖,供 load-deps-fp / interface /
705
+ * refine / LSP 共享单一定义——历史上三份内联拷贝已各自漂移过)。
706
+ */
707
+ declare function normPath(p: string): string;
708
+ /** core 不引 path:相对 spec 纯字符串拼接(与 LSP resolve 对齐时双方 norm) */
709
+ declare function resolveDepPath(fromFile: string, spec: string): string;
710
+ /**
711
+ * 是否落在 node_modules 下(相对/绝对/盘符形态统一)。
712
+ * autoBind 永不 ambient 加载 node_modules 侧车(§2.2)——必须在 normPath
713
+ * 之后判定,否则 `node_modules/pkg/x.js`(无前导 `/`)会绕过守卫。
714
+ */
715
+ declare function isNodeModulesPath(p: string): boolean;
716
+ /**
717
+ * 源文件的旁路侧车路径:.js/.mjs → 同名 .nudo.js;.ts/.mts → 同名 .nudo.ts。
718
+ * 其他扩展名(.cjs/.jsx/无扩展名…)不做替换,直接追加 .nudo.js——侧车约定
719
+ * 只覆盖四类入口;host loadModule 对不存在的路径返回 miss,自然无侧车来源。
720
+ */
721
+ declare function sidecarPathOf(file: string): string;
722
+
535
723
  /**
536
724
  * 约束模板构建器(参数无关)。
537
725
  *
@@ -540,10 +728,16 @@ declare function formatAbsMultiline(a: Abs, label?: string): string;
540
728
  * string().min(1) → 非空串(长度)
541
729
  * array(number().gt(0)) → 元素约束
542
730
  * shape({ id: number().gt(0) }) → object 形状约束
731
+ * lit(42) → 字面量(prim + eq(self, 42))
732
+ * union(number().gt(0), lit(0)) → 成员析取(or / joinAbs)
733
+ * fn({ x: number().gt(0) }, number()) → 一等函数约束
734
+ * number().gt(0).shift(1) → 界平移(x>0 ⇒ x+n>1)
543
735
  * instantiate("ms") → Pred ms > 0 / u.id > 0 ∧ …
544
736
  *
545
737
  * 在 *.nudo.js 里执行;不是 zod 绑定,是我们自己的运行时 API。
546
738
  * 不需要 interface/type 语法——契约用 JS 表达式声明。
739
+ * 注意:本文件的 lit/and 构建器与 term/pred 同名导出在桶导出处冲突,
740
+ * 消费方从 "./constraint.ts" 直接路径导入。
547
741
  */
548
742
 
549
743
  /** 模板占位项;instantiate 时换成真实参数名 */
@@ -568,6 +762,16 @@ type NudoConstraint = {
568
762
  readonly int?: boolean;
569
763
  /** 该约束整体可选(shape 字段用;不用 optional 以免与链式方法撞名) */
570
764
  readonly isOptional?: boolean;
765
+ /** union 成员(析取):instantiate 为 or(...),entry Abs 为成员 join */
766
+ readonly members?: NudoConstraint[];
767
+ /** 一等函数约束(fn() 构建器产出) */
768
+ readonly fn?: NudoFnConstraint;
769
+ };
770
+ /** fn(params, returns?, { throws? }) 的一等函数约束形态 */
771
+ type NudoFnConstraint = {
772
+ params: Record<string, NudoConstraint>;
773
+ returns?: NudoConstraint;
774
+ throws?: NudoConstraint;
571
775
  };
572
776
  declare function isNudoConstraint(x: unknown): x is NudoConstraint;
573
777
  /** 链式约束:不可变,每次 .gt() 返回新对象 */
@@ -584,9 +788,19 @@ type ConstraintBuilder = NudoConstraint & {
584
788
  max(n: number): ConstraintBuilder;
585
789
  /** string:精确长度 */
586
790
  length(n: number): ConstraintBuilder;
791
+ /**
792
+ * 界平移:term 平移 n 后重写常数界(x>0 ⇒ x+n>n)。
793
+ * 仅数值标量界链合法;length 界 / shape / array / union / fn → throw。
794
+ */
795
+ shift(n: number): ConstraintBuilder;
587
796
  /** 字段可选(仅在 shape 内有意义) */
588
797
  optional(): ConstraintBuilder;
589
798
  };
799
+ /**
800
+ * builder 与纯数据形态统一的 int 标志读取:纯数据看 `int === true`,
801
+ * builder(int 是链式方法)查 WeakSet。toPlainConstraint 归一化后只剩前者。
802
+ */
803
+ declare function isIntFlag(c: NudoConstraint): boolean;
590
804
  /** number() —— 约束 number 原语 + 后续链式界 */
591
805
  declare function number(): ConstraintBuilder;
592
806
  declare function string(): ConstraintBuilder;
@@ -599,13 +813,38 @@ declare function array(item: NudoConstraint | ConstraintBuilder): ConstraintBuil
599
813
  * shape({ id: number().gt(0), name: string() })
600
814
  */
601
815
  declare function shape(fields: Record<string, NudoConstraint | ConstraintBuilder>): ConstraintBuilder;
816
+ /** union(...cs):成员析取;instantiate 为 or(...),entry Abs 为成员 joinAbs。空参 throw */
817
+ declare function union(...cs: (NudoConstraint | ConstraintBuilder)[]): ConstraintBuilder;
818
+ /**
819
+ * fn(params, returns?, { throws? }):一等函数约束。
820
+ * Phase 1 只展示不执法:参数位 instantiate 恒真(pTrue),
821
+ * 逐参约束经 fnConstraintToEntryReqs 消费。
822
+ */
823
+ declare function fn(params: Record<string, NudoConstraint | ConstraintBuilder>, returns?: NudoConstraint | ConstraintBuilder, opts?: {
824
+ throws?: NudoConstraint | ConstraintBuilder;
825
+ }): ConstraintBuilder;
826
+ /** partial(c):shape 全字段变可选;非 shape throw */
827
+ declare function partial(c: NudoConstraint | ConstraintBuilder): ConstraintBuilder;
828
+ /** pick(c, keys):shape 子形状(不存在的 key 忽略);非 shape throw */
829
+ declare function pick(c: NudoConstraint | ConstraintBuilder, keys: string[]): ConstraintBuilder;
830
+ /** omit(c, keys):shape 去字段;非 shape throw */
831
+ declare function omit(c: NudoConstraint | ConstraintBuilder, keys: string[]): ConstraintBuilder;
602
832
  /** 把模板绑定到参数名:self → paramName;shape 展开为字段访问 Pred */
603
833
  declare function instantiateConstraint(c: NudoConstraint, paramName: string): Pred;
604
834
  /**
605
835
  * 契约 → 函数入口 param Abs(infer/hover 用)。
606
- * 标量:prim + pred;shape:obj slots 递归。
836
+ * 标量:prim + pred;shape:obj slots 递归;union:成员 joinAbs;
837
+ * fn 形态:退化 unknown(不是参数位标量值),逐参约束由 fnConstraintToEntryReqs 消费。
607
838
  */
608
839
  declare function constraintToEntryAbs(c: NudoConstraint, paramName: string): Abs;
840
+ /**
841
+ * fn 约束 → 逐参约束表(interface 推导 / 入口签名消费)。
842
+ * 非 fn() 形态 throw——调用方应先判 c.fn。
843
+ */
844
+ declare function fnConstraintToEntryReqs(c: NudoConstraint): Array<{
845
+ param: string;
846
+ constraint: NudoConstraint;
847
+ }>;
609
848
 
610
849
  /**
611
850
  * 精化契约解析:唯一形态
@@ -621,6 +860,11 @@ declare function constraintToEntryAbs(c: NudoConstraint, paramName: string): Abs
621
860
  * 由 /// @nudo:import { delay } from "./delay.nudo.js" 引入。
622
861
  * 不支持写 `x > 0`(绑死参数名)。
623
862
  * 不用 JSDoc @param/@return:那是类型注解语法。
863
+ *
864
+ * `@nudo:interface` 是 `@nudo:refine` 的等价别名(渐进迁移,§design-refine-derivation)。
865
+ * 侧车加载:Babel 语句级改写(多行 import / 注释与字符串里的同形文本不误伤)、
866
+ * 相对 .nudo.js/.nudo.ts 经 loadModule 递归求值、环检测、执行失败改诊断
867
+ * (nudo:interface-load / nudo:interface-cycle,不再静默吞错)。
624
868
  */
625
869
 
626
870
  /** `/// @nudo:import { delay, percent } from "./delay.nudo.js"` */
@@ -629,13 +873,34 @@ type NamedImport = {
629
873
  spec: string;
630
874
  };
631
875
  declare function extractNudoImports(source: string): NamedImport[];
876
+ /** refine 侧车加载诊断(severity 由消费方按 code 定档,形状对齐 Issue 子集) */
877
+ type RefineDiag = {
878
+ code: string;
879
+ message: string;
880
+ file?: string;
881
+ };
882
+ /** 设置诊断观察者(null 清除);缓冲照常累积,takeRefineDiags 取走 */
883
+ declare function setRefineDiagCollector(fn: ((d: RefineDiag) => void) | null): void;
884
+ /** 当前诊断累计序号(since 锚) */
885
+ declare function refineDiagCount(): number;
886
+ /** 取走已收集的诊断(收集即清空) */
887
+ declare function takeRefineDiags(): RefineDiag[];
888
+ /** 只取走 seq > since 的增量(工具面防窃取在途诊断;全量 take 的 since 版) */
889
+ declare function takeRefineDiagsSince(since: number): RefineDiag[];
890
+ /** 侧车模块错误:code ∈ nudo:interface-cycle | nudo:interface-load */
891
+ declare class NudoSidecarError extends Error {
892
+ readonly code: string;
893
+ constructor(code: string, message: string);
894
+ }
632
895
  /**
633
- * 执行 *.nudo.js(真实 JS + 我们的构建器)。
634
- * 把 export const 改写成 const,末尾 return { names }。
896
+ * 执行 *.nudo.js(真实 JS + 我们的构建器)。import/export 由 Babel 语句级
897
+ * 改写:多行 named import、注释/字符串里的同形文本不误伤;相对 .nudo 递归
898
+ * 求值;环 → throw NudoSidecarError。结果进 exec 缓存(依赖闭包内容指纹键)。
635
899
  */
636
- declare function execNudoModule(src: string): Record<string, unknown>;
900
+ declare function execNudoModule(src: string, opts?: RefineResolveOpts): Record<string, unknown>;
637
901
  type RefineResolveOpts = {
638
902
  loadModule?: (spec: string, fromFile: string) => string | undefined;
903
+ /** 侧车自身的路径(相对 spec 解析基准 + 环检测链起点) */
639
904
  fromFile?: string;
640
905
  };
641
906
  declare function resetNudoModuleExecCache(): void;
@@ -661,24 +926,139 @@ declare function extractRefineReturnFromSource(source: string, fnName: string, o
661
926
  constraint: NudoConstraint;
662
927
  } | undefined;
663
928
 
929
+ /**
930
+ * Interface 分层推导(design-refine-derivation §2.1/§2.2/§11 第 0 步):
931
+ *
932
+ * effectiveInterface(source, fnName) —— 手写 ∪ 侧车同名绑定 ∪ 生成段的
933
+ * 唯一读取口,来源标注(handwritten / generated / implicit)随值返回。
934
+ *
935
+ * 来源三层(合并序 handwritten > generated > implicit,§4/§11):
936
+ * - handwritten:源码 `@nudo:refine`/`@nudo:interface` 行(复用 refine.ts 的
937
+ * extractRefinesFromSource / extractRefineReturnFromSource)∪ 侧车同名**手写**
938
+ * fn() 绑定。同名同参取合取 and()(§2.1:侧车 x>0 + 源码 x>1 → 有效契约
939
+ * 取合取);常数界交叉矛盾(x>0 ∧ x<0)→ conflict 标记,由调用方报
940
+ * nudo:interface-conflict——本函数不 throw。
941
+ * - generated:侧车同名导出且声明上方注释块含 @generated 标记(emit 产物)。
942
+ * 与手写并存时整体降级忽略(手写为准;混排由 nudo:interface-name-clash /
943
+ * drift 在 emit/check 侧处理)。
944
+ * - implicit:无任何契约 → 返回 undefined(隐式推断是调用方的事)。
945
+ *
946
+ * 自动绑定边界(§2.2):只绑源文件**本地 named export**(re-export /
947
+ * export default / 私有名不绑);opts.autoBind === false 或侧车路径含
948
+ * /node_modules/ → 不 ambient 加载(只看源码 refine)。「项目根内」检查属
949
+ * 宿主层(core 无 projectDir 概念),Phase 1 不在此实现。
950
+ *
951
+ * 侧车绑定 Phase 1 只承诺 fn() 形态:非 fn 的标量/shape 绑定不消费,收集
952
+ * nudo:interface-load 诊断(后续 Phase 再放开单参形态)。
953
+ *
954
+ * 诊断走本文件独立 side-channel(先例 refine.ts 的 setRefineDiagCollector):
955
+ * 侧车加载/执行失败 → nudo:interface-cycle / nudo:interface-load。
956
+ */
957
+
958
+ /** interface 推导诊断(severity 由消费方按 code 定档,形状对齐 Issue 子集) */
959
+ type InterfaceDiag = {
960
+ code: string;
961
+ message: string;
962
+ file?: string;
963
+ };
964
+ /** 设置诊断观察者(null 清除);缓冲照常累积,takeInterfaceDiags 取走 */
965
+ declare function setInterfaceDiagCollector(fn: ((d: InterfaceDiag) => void) | null): void;
966
+ /** 当前诊断累计序号(since 锚:工具面只排干自身探测产生的增量) */
967
+ declare function interfaceDiagCount(): number;
968
+ /** 取走已收集的诊断(收集即清空) */
969
+ declare function takeInterfaceDiags(): InterfaceDiag[];
970
+ /**
971
+ * 只取走 seq > since 的诊断(清空仅限增量)——LSP 长驻进程里 lens/打印/
972
+ * emit 工具用它排干**自身探测**产生的诊断,不窃取在途 validateText 待消费
973
+ * 的接口诊断(全量 take 曾在 await 窗口偷走 checkSource 的待收诊断)。
974
+ */
975
+ declare function takeInterfaceDiagsSince(since: number): InterfaceDiag[];
976
+ /** 有效契约来源:手写(源码 refine ∪ 侧车手写绑定)> 生成段 > 隐式 */
977
+ type InterfaceSource = "handwritten" | "generated" | "implicit";
978
+ /**
979
+ * 源文件本地 named export 表:收集本文件声明并导出的名字——
980
+ * `export function/const/let/var/class` 声明形式,以及本地列表
981
+ * `export { x }` / `export { local as exported }`(按**导出名**绑定,
982
+ * 与侧车同名自动绑定口径一致)。
983
+ * 排除 re-export(`export {x} from` / `export *`)与 `export default`。
984
+ */
985
+ declare function localNamedExports(source: string): Set<string>;
986
+ /**
987
+ * 侧车源码的生成段导出名:导出名所在声明的**前置注释块**含 `@generated`
988
+ * 标记(emit 产物 canonical 注释为 `@generated by nudo`)→ 该名为 generated。
989
+ * Phase 1 简化:只看紧邻声明上方的注释块(与 extractRefineLines 同款反向
990
+ * 行扫描,空行可跨);隔了代码行 / 无标记 / re-export 列表均不算。
991
+ */
992
+ declare function generatedExportNames(sidecarSrc: string): Set<string>;
993
+ type EffectiveInterfaceOpts = RefineResolveOpts & {
994
+ /** false(或谓词返回 false)→ 不 ambient 加载侧车;默认 true */
995
+ autoBind?: boolean | ((sidecarPath: string) => boolean);
996
+ };
997
+ type EffectiveInterface = {
998
+ fnName: string;
999
+ params: Array<{
1000
+ param: string;
1001
+ constraint: NudoConstraint;
1002
+ }>;
1003
+ returns?: {
1004
+ constraint: NudoConstraint;
1005
+ };
1006
+ source: InterfaceSource;
1007
+ /**
1008
+ * 合取不可满足标记:params = 常数界交叉矛盾(或 prim 矛盾等 and() 不可
1009
+ * 合取形态)的参数名;returns = 返回位同样不可满足。调用方报
1010
+ * nudo:interface-conflict 并跳过对应位执法。
1011
+ */
1012
+ conflict?: {
1013
+ params: string[];
1014
+ returns?: boolean;
1015
+ };
1016
+ };
1017
+ /**
1018
+ * 单点读取口:手写 ∪ 侧车同名 ∪ 生成段 → 有效契约(含来源标注)。
1019
+ * 无任何契约 → undefined(implicit 由调用方处理)。
1020
+ */
1021
+ declare function effectiveInterface(source: string, fnName: string, opts?: EffectiveInterfaceOpts): EffectiveInterface | undefined;
1022
+ /**
1023
+ * 侧车及递归 .nudo 依赖闭包的内容指纹:`${hashSource(侧车)}|路径=hash,…`。
1024
+ * 无 loadModule / autoBind 关闭 / node_modules / loadModule miss → undefined
1025
+ * (无侧车影响即无需指纹)。闭包截断 → `trunc:` 前缀,键不可信,调用方
1026
+ * fail-open(参照 loadModuleDepsFingerprint 的 truncated 契约)。
1027
+ */
1028
+ declare function sidecarClosureFingerprint(fromFile: string, opts: EffectiveInterfaceOpts): string | undefined;
1029
+ /** 组合式显示:重建构建器调用形态(number().gt(0) / union(…) / fn(…)) */
1030
+ declare function formatConstraint(c: NudoConstraint): string;
1031
+
664
1032
  type LoadDepsFingerprint = {
665
1033
  fp: string;
666
1034
  paths: string[];
667
1035
  /** BFS 撞到节点上限:剩余 dep 未进指纹,键不可信 */
668
1036
  truncated: boolean;
669
1037
  };
670
- declare function normPath(p: string): string;
671
- /** core 不引 path:相对 spec 纯字符串拼接(与 LSP resolve 对齐时双方 norm) */
672
- declare function resolveDepPath(fromFile: string, spec: string): string;
673
1038
  /**
674
1039
  * All string module specs that analysis may resolve through loadModule.
675
1040
  * Regex over-approximates (may hit comments) — extra dep fingerprint is safe
676
1041
  * (more misses, never a stale hit).
677
1042
  */
678
1043
  declare function extractAllLoadSpecs(source: string): string[];
1044
+ /**
1045
+ * 源里指向其他侧车的相对 spec(`.nudo.js`/`.nudo.ts`)。regex 过近似安全:
1046
+ * 多算的 dep 只带来额外 miss,绝不产生陈旧命中。LSP 隐式依赖登记共用。
1047
+ */
1048
+ declare function sidecarSpecsOf(source: string): string[];
679
1049
  /**
680
1050
  * Fingerprint every loadModule-reachable dep (not only `*.nudo.js`), including
681
- * one hop of transitive specs from each dep source.
1051
+ * one hop of transitive specs from each dep source — plus the autoBind 侧车
1052
+ * 闭包(`sidecar:` 前缀条目)。
1053
+ *
1054
+ * 侧车吸收范围 = fromFile 自身 **与每一个成功加载的依赖文件**的旁路侧车及其
1055
+ * 递归 .nudo 依赖:跨文件被调(scan.ts checkExternalCall)会按定义文件路径
1056
+ * ambient 绑定其侧车,依赖侧车内容影响调用方报告——不进指纹则编辑后 memo
1057
+ * 陈旧命中(错诊断)。侧车 loadModule miss(无侧车文件)→ 不加任何条目。
1058
+ *
1059
+ * 注意:本扩展对 autoBind=false 与 /node_modules/ 均**不** gate(刻意过近似,
1060
+ * 只过度失效、绝不陈旧命中——安全方向);ambient 生效边界由
1061
+ * interface.ts 的 sidecarClosureFingerprint 负责,两者职责不同。
682
1062
  */
683
1063
  declare function loadModuleDepsFingerprint(source: string, loadModule: (spec: string, fromFile: string) => string | undefined, fromFile: string): LoadDepsFingerprint;
684
1064
 
@@ -732,11 +1112,13 @@ declare function generalizeFromAst(fnName: string, source: string, opts?: {
732
1112
  budget?: LeakBudget;
733
1113
  label?: string;
734
1114
  /** 传入则把 @nudo:refine 挂到入口 param Abs */
735
- refine?: RefineResolveOpts;
1115
+ refine?: EffectiveInterfaceOpts;
736
1116
  /** 预解析 AST,避免 check 批量场景重复 parse */
737
1117
  file?: ReturnType<typeof parseSource>;
738
1118
  /** 预计算 load-deps 指纹(checkSource 整文件一次,避免 per-fn 重读) */
739
1119
  depsFp?: LoadDepsFingerprint;
1120
+ /** 预计算 ambient 侧车闭包指纹(checkSource 整文件一次) */
1121
+ sidecarFp?: string;
740
1122
  }): PolyFn | undefined;
741
1123
  declare function generalizeAll(source: string, opts?: {
742
1124
  budget?: LeakBudget;
@@ -777,11 +1159,50 @@ declare function formatDiagnostics(diags: Diagnostic[]): string;
777
1159
  * Template string 拼接(代数侧)。
778
1160
  * 表示:prim(string) + refinement.meta.templateParts = Abs[]
779
1161
  * 与 core 的 createTemplate 对齐,使 `"x" + string + "!"` 得到 template refined。
1162
+ *
1163
+ * 本模块是模板语义的唯一真理源:前缀/后缀/固定文本/长度/匹配/名称渲染/
1164
+ * 相邻合并/谓词判定等纯计算以「中性 part 视图」(TemplatePartView)暴露;
1165
+ * TypeValue 侧(refinements/template.ts)与 Abs 方法表(methods.ts)只做薄适配。
780
1166
  */
781
1167
 
782
1168
  type TemplateMeta = {
783
1169
  templateParts: Abs[];
784
1170
  };
1171
+ /** 单个 part 的分类:固定文本,或抽象 part(携带展示文本) */
1172
+ type TemplatePartDesc = {
1173
+ fixed: string;
1174
+ } | {
1175
+ render: string;
1176
+ };
1177
+ /** 带原始 part 回引的视图:既喂语义计算,也用于重建合并结果 */
1178
+ type TemplatePartView<P = unknown> = {
1179
+ /** 固定文本;undefined = 抽象 part */
1180
+ fixed: string | undefined;
1181
+ /** 抽象 part 的展示文本(渲染 `${...}` 名时使用) */
1182
+ render: string;
1183
+ part: P;
1184
+ };
1185
+ declare function viewTemplateParts<P>(parts: P[], describe: (p: P) => TemplatePartDesc): TemplatePartView<P>[];
1186
+ /** 前导固定文本(遇到首个抽象 part 停止) */
1187
+ declare function knownPrefixOfViews(views: TemplatePartView[]): string;
1188
+ /** 尾部固定文本(从末尾遇到首个抽象 part 停止) */
1189
+ declare function knownSuffixOfViews(views: TemplatePartView[]): string;
1190
+ /** 全部固定文本按序拼接(跨抽象 part) */
1191
+ declare function allFixedTextOfViews(views: TemplatePartView[]): string;
1192
+ /** 全部 part 均为固定文本时的精确总长;含抽象 part 则 undefined */
1193
+ declare function fixedLengthOfViews(views: TemplatePartView[]): number | undefined;
1194
+ /** 渲染 `` `lit${render}` `` 形态的模板名 */
1195
+ declare function formatTemplateNameViews(views: TemplatePartView[]): string;
1196
+ /** 相邻固定文本合并;rebuildFixed 以合并文本重建视图(含原始 part) */
1197
+ declare function mergeAdjacentFixedViews<P>(views: TemplatePartView<P>[], rebuildFixed: (text: string) => TemplatePartView<P>): TemplatePartView<P>[];
1198
+ /** 具体字符串是否匹配模板(Refinement.check 的判定语义) */
1199
+ declare function templateMatchesValue(value: string, views: TemplatePartView[]): boolean;
1200
+ /** 三值判定;两侧分别把 "unknown" 适配为 boolPrim(Abs)或 undefined(TypeValue) */
1201
+ type TemplatePredicateDecision = boolean | "unknown";
1202
+ declare function decideStartsWith(prefix: string, search: string): TemplatePredicateDecision;
1203
+ declare function decideEndsWith(suffix: string, search: string): TemplatePredicateDecision;
1204
+ declare function decideIncludes(fixedText: string, search: string): TemplatePredicateDecision;
1205
+ declare function absTemplateViews(parts: Abs[]): TemplatePartView<Abs>[];
785
1206
  /** 从 Abs 提取 template parts(已是 template 则展开,否则 [self]) */
786
1207
  declare function templatePartsOf(a: Abs): Abs[];
787
1208
  /**
@@ -993,7 +1414,6 @@ declare function formatCheckReport(r: CheckReport, opts?: {
993
1414
  */
994
1415
 
995
1416
  declare function resetCheckSourceMemo(): void;
996
- declare function getCheckSourceMemoSize(): number;
997
1417
  /** `*.nudo.js` 变更后定向逐出依赖它的整文件 check 缓存 */
998
1418
  declare function evictCheckSourceMemoForPaths(paths: string[]): number;
999
1419
  /**
@@ -1004,6 +1424,12 @@ type CheckOptions = {
1004
1424
  loadModule?: (spec: string, fromFile: string) => string | undefined;
1005
1425
  /** 当前文件路径(供 loadModule 解析相对 spec) */
1006
1426
  fromFile?: string;
1427
+ /**
1428
+ * 侧车 ambient 绑定开关(host 从 package.json#nudo.interface.autoBind
1429
+ * 解析后下传;默认 true)。false = check/LSP 执法路径不自动加载侧车
1430
+ * (§2.2「整体关闭」承诺覆盖 CI 门禁,不只是打印路径)。
1431
+ */
1432
+ autoBind?: boolean;
1007
1433
  };
1008
1434
  /**
1009
1435
  * 检查一个文件:
@@ -1015,9 +1441,32 @@ type CheckOptions = {
1015
1441
  */
1016
1442
  declare function checkSource(filePath: string, source: string, phi?: Phi, opts?: CheckOptions): CheckReport;
1017
1443
 
1444
+ /**
1445
+ * 字面量域隶属判定(Phase 1)。
1446
+ *
1447
+ * 手写契约(*.nudo.js)与调用点域证据对账用:判断字面量值是否落在
1448
+ * NudoConstraint 表达的域内。只覆盖可判定的标量子集:
1449
+ *
1450
+ * - prim 门(prim 缺失或不匹配字面量类型 → false)
1451
+ * - eq(self, lit v) 字面量等值(number/string/boolean/null)
1452
+ * - gt/ge/lt/le 数值常数界(self op n)
1453
+ * - 字符串长度界(length(self) op n,即 min/max/length 链)
1454
+ * - int(整数性)
1455
+ * - members(union):任一成员满足即满足
1456
+ *
1457
+ * 对象 / 数组 / 函数域与不可判定的 pred 形态一律 false——保守不满足,
1458
+ * 对账侧宁可多报 domain-exceeds 也不放过。
1459
+ */
1460
+
1461
+ /** 字面量 lv 是否落在约束 c 表达的域内(保守:判不了 → false)。 */
1462
+ declare function literalMeetsConstraint(lv: number | string | boolean | null, c: NudoConstraint): boolean;
1463
+
1018
1464
  /**
1019
1465
  * Abs inlay hint:把无损约束内联到源码位置。
1020
1466
  * 不是 TS 风格 type annotation 复读,而是 term/pred/conf 的计算结果。
1467
+ *
1468
+ * 参数侧只展示显式 `@nudo:refine` 契约(entryReqs)——
1469
+ * 不从函数体 `if` 反推前置条件(那是控制流,不是对外契约)。
1021
1470
  */
1022
1471
  type AbsInlay = {
1023
1472
  /** 1-based 行号 */
@@ -1029,8 +1478,8 @@ type AbsInlay = {
1029
1478
  };
1030
1479
  /**
1031
1480
  * 收集源码中函数签名的 Abs inlay:
1032
- * - 参数后:前置约束(声明 refine 优先;否则从 if 推)
1033
- * - `)` 后:返回 shape + term(类型即计算)
1481
+ * - 参数后:仅 `@nudo:refine` 声明的前置契约
1482
+ * - `{` 前:返回计算形(`x | x * 2`),无 term 时退回 shape
1034
1483
  */
1035
1484
  declare function collectAbsInlays(source: string, refineOpts?: {
1036
1485
  loadModule?: (spec: string, fromFile: string) => string | undefined;
@@ -1068,13 +1517,102 @@ declare function absToTypeValue(a: Abs): TypeValue;
1068
1517
  * 置信度:优先读 abs→tv 时挂上的 conf 旁路,避免 #widened 回升 #exact。
1069
1518
  */
1070
1519
  declare function typeValueToAbs(tv: TypeValue): Abs;
1520
+
1521
+ /**
1522
+ * Abs → NudoConstraint 投影(Phase 1,interface 分层推导的生成侧半边)。
1523
+ *
1524
+ * 只投影可表达子集,其余一律 undefined——诚实缺口,不产垃圾约束
1525
+ * (调用方据此标 partial/skip,见设计文档 §4.2):
1526
+ *
1527
+ * numLit(42) / strLit("a") / boolLit(true) → lit(v)
1528
+ * prim number + 常数界(gt/ge/lt/le 于 self 项)→ number().gt(…) 链
1529
+ * prim string + 长度界(length(self) 与常数比较)→ string().min/max
1530
+ * prim + eq(self, lit v) → lit(v)
1531
+ * sum 形态 / or-pred 字面量集 → union(lit…)(全员字面量才投影)
1532
+ * obj slots → shape({ 字段递归 })(任一字段
1533
+ * 不可投影 → 整体 undefined;空对象 → shape({}))
1534
+ * arr → array(item)(元素可投影);
1535
+ * 元素不可投影但 prim 均匀无 preds → array(number()) 之类退化
1536
+ *
1537
+ * conf ∈ {exact, path} 才投影;widened/partial/opaque/mock → undefined。
1538
+ * preds 中含不可表达形态(length 于 number、ne、未锚定 self 的项、
1539
+ * 嵌套 or/not)→ undefined。bigint/symbol、tuple、fn、eff、brand、
1540
+ * any(无 or-pred)、never、unknown → undefined。
1541
+ *
1542
+ * 注意:本模块从 "./constraint.ts" 直接路径 import(桶导出消歧为
1543
+ * term.ts 的 lit / pred.ts 的 and,见 constraint.ts 头注释)。
1544
+ */
1545
+
1546
+ /** Abs → 契约;不可表达 → undefined */
1547
+ declare function absToConstraint(a: Abs): NudoConstraint | undefined;
1548
+ /**
1549
+ * 工件聚合投影(设计 §4.2:先 Abs join 折叠再投影)。
1550
+ * 空列表 → undefined(无证据不产约束)。
1551
+ *
1552
+ * 全员可投影字面量时走**字面量快路径**(直接 union 去重):joinValues 对
1553
+ * 两个同 prim 字面量的相遇会急切塌缩为裸 prim(term/pred 丢失),reduce
1554
+ * 左折叠因此对证据**顺序敏感**——{42,"a",7} 一序产出 union 三字面量、
1555
+ * 另一序 not-projectable。快路径绕过 join,聚合结果顺序无关。
1556
+ */
1557
+ declare function joinThenProject(absList: Abs[]): NudoConstraint | undefined;
1558
+
1559
+ /**
1560
+ * 源码级调用图侦察:从 check 门禁拆出的 AST 扫描层。
1561
+ *
1562
+ * 职责:不做代数求值结论,只回答「谁在调用谁、实参长什么样」——
1563
+ * - listTopFunctions:顶层函数清单
1564
+ * - collectCallResolvers / resolveCalleeFn / collectForwarders:别名 / 对象属性 /
1565
+ * require / 动态 import / 无条件转发 的调用解析
1566
+ * - scanLiteralCalls:字面量调用点实参 vs 前置约束的违例收集
1567
+ */
1568
+
1071
1569
  /**
1072
- * 有损检查:Abs 转 TypeValue 后是否丢了 term/pred。
1073
- * 用于金标与调试。
1570
+ * 注入记录的最小结构面(service CallRecord 的成员子集——core 不反向依赖
1571
+ * service 的 CallRecord 声明,按结构兼容接收)。
1074
1572
  */
1075
- declare function bridgeIsLossy(a: Abs): {
1076
- lossy: boolean;
1077
- reasons: string[];
1573
+ type InjectedDomainRecord = {
1574
+ argTypes: TypeValue[];
1575
+ resultType: TypeValue;
1576
+ throws: TypeValue;
1577
+ };
1578
+ type InjectedDomainEvidenceOpts = {
1579
+ /** 被调函数形参名(位置序);契约按参数名对齐证据位 */
1580
+ paramNames: string[];
1581
+ loadModule?: (spec: string, fromFile: string) => string | undefined;
1582
+ fromFile?: string;
1583
+ /** 侧车 ambient 绑定开关(host 配置下传;默认 true) */
1584
+ autoBind?: boolean;
1585
+ /** 报告定位:被调函数声明处。注入证据的 loc 在使用现场文件,不属于本文件 */
1586
+ loc?: {
1587
+ line: number;
1588
+ column: number;
1589
+ };
1078
1590
  };
1591
+ /**
1592
+ * 跨文件注入的调用点域证据 vs 手写契约(设计稿 §3.3/§6 对账矩阵第一行)。
1593
+ *
1594
+ * 来源分流铁律:写在被分析文件里的调用点违例(含 scanLiteralCalls 的
1595
+ * checkExternalCall 跨文件被调路径)维持 `nudo:constraint-violated` 原码
1596
+ * 原语义——本函数**只**消费经 externalCallRecords 注入的跨文件记录(analyzer
1597
+ * 消费区已做归属守卫),该路径此前不查契约,是纯增量。
1598
+ *
1599
+ * 证据门槛(§6):
1600
+ * - 只有 plain literal 实参构成证据:union/unknown/primitive/refined 形态
1601
+ * 无法归因到确定值,不参与(widened/partial conf 经 absToTypeValue 投影
1602
+ * 为非 literal 形态,天然被此条排除;getTvConfidence 再兜一道底);
1603
+ * - null 证据预过滤(T4 caveat:lit(null) 编码 prim undefined + eq(self,
1604
+ * null),对任何约束恒不满足,不过滤必 FP);undefined/bigint/symbol
1605
+ * 不在字面量证据域内,一并跳过;
1606
+ * - resultType=never ∧ throws=never 是求值中断泄漏(analyzer 注入消费区
1607
+ * 同款过滤)。CallRecord 上没有截断字段(查证于 evaluator.ts CallRecord
1608
+ * 声明:fnName/argTypes/resultType/throws/callLoc/targetModule/
1609
+ * targetExport/targetAliases/fnModule 十项,无截断标记)——递归截断走
1610
+ * nudo:recursion-truncated 诊断通道且只 widen 结果,不产生新字面量证据;
1611
+ * - fn/shape/array 参数位 Phase 1 不执法(§3.3 HOF 豁免:
1612
+ * literalMeetsConstraint 对这些形态恒 false,直接查必 FP)。
1613
+ *
1614
+ * 每函数每参数位最多一条 issue(多证据并列在 actual 里,去重)。
1615
+ */
1616
+ declare function checkInjectedDomainEvidence(fnName: string, source: string, records: InjectedDomainRecord[], opts: InjectedDomainEvidenceOpts): CheckIssue[];
1079
1617
 
1080
- export { Abs, type AbsFnImpl, type AbsInlay, AstEnv, type CheckIssue, type CheckJson, type CheckOptions, type CheckReport, type ClassDef, Confidence, type ConstraintBuilder, type Diagnostic, type Environment, type FnAbs, type FnFp, type FormatOptions, type FunctionSignature, HofSite, LeakBudget, type LeqResult, type LiteralValue, type LoadDepsFingerprint, type MethodDef, type MockHelper, type NamedImport, type NudoConstraint, type NudoField, type NudoSig, type ObjShape, Ops, Phi, type PolyFn, Pred, PrimName, type RangeMeta, type RefineEntry, type RefineResolveOpts, type Refinement, RelSource, SELF, Shape, type SigImpl, type Slot, T, type TemplateMeta, Term, type TypeParam, type TypeValue, absFunction, absToTypeValue, add, applyBinaryOp, array, attachFnImpl, awaitAbs, boolean, bridgeIsLossy, buildArgsFromAssume, callAbsMethod, canSkipLiteralCallScan, checkArg, checkCall, checkSource, classFromMethods, cmp, coerceAsyncReturn, collapseLiteralUnion, collapseToOptional, collectAbsInlays, concatString, concatTemplates, constraintToEntryAbs, createEnvironment, createRange, createTemplate, createTemplateAbs, currentPhi, deepCloneTypeValue, defineClass, definitelyNotNullishShape, denoteGuard, describePhi, dispatchBinaryOp, dispatchMethod, dispatchProperty, div, evalArrayStatic, evalBuiltinInstanceMethod, evalBuiltinNew, evalDateCtor, evalDateMethod, evalDateStatic, evalGlobalFn, evalJsonMethod, evalMathMethod, evalNamespaceCall, evalNumberStatic, evalObjectMethod, evalPromiseCtor, evalPromiseStatic, evalRegExpCtor, evalRegExpMethod, evictCheckSourceMemoForPaths, evictGeneralizeMemoForPaths, execNudoModule, extractAllLoadSpecs, extractFn, extractNudoImports, extractRefineReturnFromSource, extractRefinesFromSource, falseConstraint, fnFingerprints, fnOf, formatAbs, formatAbsMultiline, formatCheckReport, formatDiagnostics, formatShape, formatShapeSlot, generalizeAll, generalizeFromAst, generalizeSourceKeyPart, getAbsProperty, getCheckSourceMemoSize, getClass, getClassChain, getFnImpl, getFnNameAndBodies, getFnSig, getGeneralizeMemoSize, getKnownPrefix, getKnownSuffix, getParseSourceCacheSize, getPrimitiveTypeOf, getRangeMeta, getRefinedBase, getTemplateParts, getTerm, getTvConfidence, hashSource, instanceOf, instantiateClass, instantiateConstraint, isFnSig, isNudoConstraint, isNullishLitAbs, isObj, isRange, isSubtypeOf, isTemplate, isTemplateLike, joinAbs, joinFunctions, joinObjects, joinValues, lenTerm, leqAbs, listFunctionNames, loadModuleDepsFingerprint, lookupMethod, lookupMethodWithOwner, lookupSuperMethod, makeSum, mergeObjectProperties, mock, mockHelperToTypeValue, mod, mul, narrowType, negAbs, normPath, notAbs, number, numericBounds, objOf, parseSource, popPhi, projectBrand, pushPhi, refineToIndexedFull, relationFingerprint, relationFn, resetCheckSourceMemo, resetFnFpCache, resetGeneralizeMemo, resetHashSourceCache, resetNudoModuleExecCache, resetParseSourceCache, resetPhi, resolveDepPath, serializeCheckJson, setTvConfidence, shape, shapeOnlyFn, simplifyUnion, spread, spy, stableAnalyzeKeySource, strictEqAbs, string, stripTypes, stub, sub, subtractType, superNameOf, templatePartsOf, trueConstraint, typeValueEquals, typeValueToAbs, typeValueToString, typeofAbs, widenLiteral, withPhiConstraint, wrapPromise };
1618
+ export { Abs, type AbsAssignRecord, type AbsCallRecord, type AbsFnImpl, type AbsInlay, AbsModuleExports, AstEnv, type CheckIssue, type CheckJson, type CheckOptions, type CheckReport, type ClassDef, Confidence, type ConstraintBuilder, type Diagnostic, type EffectiveInterface, type EffectiveInterfaceOpts, type Environment, type EvalOptions, type EvalResult, type FnAbs, type FnFp, type FormatOptions, type FunctionSignature, HofSite, type InjectedDomainRecord, type InterfaceDiag, type InterfaceSource, type LeakBudget, type LeqResult, type LiteralValue, type LoadDepsFingerprint, MAX_CALL_DEPTH, MAX_TOTAL_CALLS, type MethodDef, type MockHelper, type NamedImport, type NudoConstraint, type NudoField, type NudoFnConstraint, NudoSidecarError, type NudoSig, type ObjShape, Ops, Phi, type PolyFn, Pred, PrimName, type RangeMeta, type RefineDiag, type RefineEntry, type RefineResolveOpts, type Refinement, RelSource, SELF, Shape, type SigImpl, type Slot, T, type TemplateMeta, type TemplatePartDesc, type TemplatePartView, type TemplatePredicateDecision, Term, type TypeParam, type TypeValue, absFunction, absTemplateViews, absToConstraint, absToTypeValue, add, allFixedTextOfViews, analyzeFn, applyAbsFn, applyBinaryOp, array, attachFnImpl, awaitAbs, boolean, buildArgsFromAssume, callAbsMethod, callFunction, canSkipLiteralCallScan, checkArg, checkCall, checkInjectedDomainEvidence, checkSource, classFromMethods, cmp, coerceAsyncReturn, collapseLiteralUnion, collectAbsInlays, collectAbsNodeTypes, concatString, concatTemplates, constraintToEntryAbs, createEnvironment, createRange, createTemplate, createTemplateAbs, currentPhi, decideEndsWith, decideIncludes, decideStartsWith, deepCloneTypeValue, defaultLeakBudget, defineClass, definitelyNotNullishShape, denoteGuard, describePhi, dispatchBinaryOp, dispatchMethod, dispatchProperty, div, effectiveInterface, emptyEnv, evalArrayStatic, evalBuiltinInstanceMethod, evalBuiltinNew, evalDateCtor, evalDateMethod, evalDateStatic, evalGlobalFn, evalJsonMethod, evalMathMethod, evalMethodBody, evalNamespaceCall, evalNode, evalNumberStatic, evalObjectMethod, evalProgramAbs, evalPromiseCtor, evalPromiseStatic, evalRegExpCtor, evalRegExpMethod, evalSource, evictCheckSourceMemoForPaths, evictGeneralizeMemoForPaths, exceedsBudget, execNudoModule, extractAllLoadSpecs, extractFn, extractNudoImports, extractRefineReturnFromSource, extractRefinesFromSource, falseConstraint, findAbsAtPosition, fixedLengthOfViews, fn, fnConstraintToEntryReqs, fnFingerprints, fnOf, formatAbs, formatAbsMultiline, formatCheckReport, formatConstraint, formatDiagnostics, formatShape, formatShapeSlot, formatTemplateNameViews, generalizeAll, generalizeFromAst, generalizeSourceKeyPart, generatedExportNames, getAbsProperty, getClass, getClassChain, getFnImpl, getFnNameAndBodies, getFnSig, getGeneralizeMemoSize, getParseSourceCacheSize, getPrimitiveTypeOf, getRangeMeta, getRefinedBase, getSlot, getTemplateParts, getTerm, getTvConfidence, hashSource, instanceOf, instantiateClass, instantiateConstraint, interfaceDiagCount, isFnSig, isIntFlag, isNodeModulesPath, isNudoConstraint, isNullishLitAbs, isObj, isRange, isSubtypeOf, isTemplate, isTemplateLike, joinAbs, joinFunctions, joinObjects, joinThenProject, joinValues, knownPrefixOfViews, knownSuffixOfViews, leakIfNeeded, lenTerm, leqAbs, listFunctionNames, literalMeetsConstraint, loadModuleDepsFingerprint, localNamedExports, lookupMethod, lookupMethodWithOwner, lookupSuperMethod, makeSum, matchRelIdentLit, maybeLeak, mergeAdjacentFixedViews, mergeObjectProperties, mock, mockHelperToTypeValue, mod, mul, narrowType, negAbs, normPath, notAbs, number, objOf, omit, parseSource, partial, pick, popPhi, projectBrand, pushPhi, refineAbsForRelTrue, refineDiagCount, refineToIndexedFull, relationFingerprint, relationFn, resetAbsCallBudget, resetCheckSourceMemo, resetFnFpCache, resetGeneralizeMemo, resetHashSourceCache, resetLeakCounter, resetNudoModuleExecCache, resetParseSourceCache, resetPhi, resolveDepPath, serializeCheckJson, setAbsAssignCollector, setAbsCallCollector, setAbsNodeCollector, setAbsTruncationCollector, setInterfaceDiagCollector, setRefineDiagCollector, setTvConfidence, shape, shapeOnlyFn, sidecarClosureFingerprint, sidecarPathOf, sidecarSpecsOf, simplifyUnion, spread, spy, stableAnalyzeKeySource, strictEqAbs, string, stripTypes, stub, sub, subtractType, superNameOf, takeInterfaceDiags, takeInterfaceDiagsSince, takeRefineDiags, takeRefineDiagsSince, templateMatchesValue, templatePartsOf, termDepth, termNodes, trueConstraint, typeValueEquals, typeValueToAbs, typeValueToString, typeofAbs, union, viewTemplateParts, widenLiteral, withPhiConstraint, withVar, wrapPromise };