@nudojs/core 1.3.0 → 1.5.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.js CHANGED
@@ -1,5 +1,8 @@
1
1
  import "./chunk-US532PZA.js";
2
2
  import {
3
+ CONSTRAINT_BUILDERS,
4
+ CONSTRAINT_BUILDER_NAMES,
5
+ CONSTRAINT_EXPR_RE,
3
6
  NudoSidecarError,
4
7
  SELF,
5
8
  andC,
@@ -14,14 +17,20 @@ import {
14
17
  effectiveInterface,
15
18
  evictGeneralizeMemoForPaths,
16
19
  execNudoModule,
20
+ extractBalancedParens,
17
21
  extractDeclaredThrows,
22
+ extractFileEnvNames,
18
23
  extractFn,
19
24
  extractFnBudget,
25
+ extractMockModuleRecords,
26
+ extractNudoImportRecords,
20
27
  extractNudoImports,
21
28
  extractRefineReturnFromSource,
22
29
  extractRefinesFromSource,
30
+ findFnDirectiveScope,
23
31
  fn,
24
32
  fnConstraintToEntryReqs,
33
+ fnDirectiveCommentLines,
25
34
  formatConstraint,
26
35
  formatEffectiveInterfaceDisplay,
27
36
  formatInterfaceTierLine,
@@ -40,6 +49,7 @@ import {
40
49
  isNodeModulesPath,
41
50
  isNudoConstraint,
42
51
  lenTerm,
52
+ listFnDirectiveScopes,
43
53
  listFunctionNames,
44
54
  listTopFunctions,
45
55
  litC,
@@ -50,6 +60,9 @@ import {
50
60
  nullable,
51
61
  number,
52
62
  omit,
63
+ parseEnvPayload,
64
+ parseMockModulePayload,
65
+ parseNudoImportPayload,
53
66
  partial,
54
67
  pick,
55
68
  refineDiagCount,
@@ -58,13 +71,19 @@ import {
58
71
  resetHashSourceCache,
59
72
  resetNudoModuleExecCache,
60
73
  resetSidecarLoadFailureCache,
74
+ scanBudgetDecl,
75
+ scanCaseArgSpans,
76
+ scanCaseTags,
77
+ scanContractSegments,
61
78
  scanLiteralCalls,
79
+ scanThrowsDecl,
62
80
  setInterfaceDiagCollector,
63
81
  setRefineDiagCollector,
64
82
  shape,
65
83
  sidecarClosureFingerprint,
66
84
  sidecarPathOf,
67
85
  stableAnalyzeKeySource,
86
+ stablePathKey,
68
87
  string,
69
88
  takeInterfaceDiags,
70
89
  takeInterfaceDiagsSince,
@@ -72,7 +91,7 @@ import {
72
91
  takeRefineDiagsSince,
73
92
  throwConstraintToKinds,
74
93
  union
75
- } from "./chunk-5YNR4Q7E.js";
94
+ } from "./chunk-YO4GKCNE.js";
76
95
  import {
77
96
  $add,
78
97
  $arguments,
@@ -200,6 +219,7 @@ import {
200
219
  TYPEOF_NAMES,
201
220
  abs,
202
221
  absFunction,
222
+ absOnly,
203
223
  absShapeKey,
204
224
  absToString,
205
225
  add,
@@ -231,6 +251,7 @@ import {
231
251
  callAbsMethod,
232
252
  callAtFunctionBoundary,
233
253
  callTranspiledExport,
254
+ callTranspiledExportApply,
234
255
  callTranspiledExportFull,
235
256
  canonicalArrayIndex,
236
257
  clearBClasses,
@@ -309,6 +330,7 @@ import {
309
330
  identBoundaryRegex,
310
331
  implies,
311
332
  instantiateReturn,
333
+ isAbsApplyResult,
312
334
  isArrMutator,
313
335
  isBigPrim,
314
336
  isDefinitelyFalse,
@@ -345,6 +367,7 @@ import {
345
367
  looseEqAbs,
346
368
  lt,
347
369
  ltNum,
370
+ makeAbsApplyResult,
348
371
  makeArrayCtorAbs,
349
372
  makeMapAbs,
350
373
  makeSetAbs,
@@ -484,7 +507,7 @@ import {
484
507
  v,
485
508
  withExecPhi,
486
509
  withVar
487
- } from "./chunk-CKH6GQAI.js";
510
+ } from "./chunk-W2MP6REI.js";
488
511
 
489
512
  // src/environment.ts
490
513
  function createEnvironment(parent, bindings = /* @__PURE__ */ new Map()) {
@@ -613,15 +636,15 @@ function checkArg(arg, expect, phi = pTrue) {
613
636
  }
614
637
  const combined = arg.pred && arg.pred.op !== "true" ? phi.op === "true" ? arg.pred : { op: "and", args: [phi, arg.pred] } : phi;
615
638
  if (implies(combined, expect)) return void 0;
616
- const lv = litValue(arg);
617
- if (lv !== void 0 && (expect.op === "gt" || expect.op === "ge" || expect.op === "lt" || expect.op === "le")) {
618
- const ok = decideLitCmp(lv, expect);
639
+ const lvR = litValue(arg);
640
+ if (lvR.ok && (expect.op === "gt" || expect.op === "ge" || expect.op === "lt" || expect.op === "le")) {
641
+ const ok = decideLitCmp(lvR.value, expect);
619
642
  if (ok === true) return void 0;
620
643
  if (ok === false) {
621
644
  return {
622
645
  severity: "error",
623
646
  code: "nudo:constraint-violated",
624
- message: `argument ${JSON.stringify(lv)} does not satisfy ${predToString(expect)}`,
647
+ message: `argument ${JSON.stringify(lvR.value)} does not satisfy ${predToString(expect)}`,
625
648
  suggestion: `use a value satisfying the constraint, or relax the function precondition`
626
649
  };
627
650
  }
@@ -745,60 +768,92 @@ function isBoundedEvidenceMissing(ret, constraint) {
745
768
  if (ret.pred && ret.pred.op !== "true") return false;
746
769
  return true;
747
770
  }
771
+ function flattenSumArms(ret) {
772
+ if (ret.shape.k !== "sum") return [ret];
773
+ const out = [];
774
+ for (const m of ret.shape.members) {
775
+ if (m.shape.k === "sum") out.push(...flattenSumArms(m));
776
+ else out.push(m);
777
+ }
778
+ return out;
779
+ }
780
+ function isWidenedSumArm(m, parent) {
781
+ return parent.conf === "partial" && m.shape.k === "prim" && !m.term && (!m.pred || m.pred.op === "true");
782
+ }
748
783
  function assertImplies(ret, constraint, opts) {
749
784
  const phi = opts?.phi ?? pTrue;
750
785
  if (ret.shape.k === "never") return proved();
751
786
  if (isAnyConstraint(constraint)) return proved();
752
- const nullishOk = constraintAdmitsNullish(constraint);
753
- if (isNullishLitAbs(ret)) {
754
- return nullishOk ? proved() : disproved(`nullish return \u22AD ${formatConstraint(constraint)}`);
755
- }
756
- let sumMembers;
757
- if (ret.shape.k === "sum") {
758
- const members = ret.shape.members;
759
- const nullishMembers = members.filter((m) => isNullishLitAbs(m));
760
- if (nullishMembers.length > 0 && !nullishOk) {
761
- return disproved(
762
- `nullish return arm \u22AD ${formatConstraint(constraint)} (contract does not admit nullish)`
763
- );
764
- }
765
- sumMembers = members.filter((m) => !isNullishLitAbs(m));
766
- }
767
787
  if (isValueSetUnknown(ret)) {
768
788
  return unprovable(
769
789
  ret.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
770
790
  );
771
791
  }
792
+ const arms = flattenSumArms(ret);
793
+ if (arms.length > 1) {
794
+ return assertSumArms(arms, ret, constraint, opts, phi);
795
+ }
796
+ return assertImpliesSingle(arms[0], constraint, opts, phi);
797
+ }
798
+ function assertSumArms(arms, parent, constraint, opts, phi) {
799
+ const hasWidenedArm = arms.some(
800
+ (a) => isValueSetUnknown(a) || isWidenedSumArm(a, parent)
801
+ );
802
+ let sawUnprovable = false;
803
+ for (const arm of arms) {
804
+ if (isNullishLitAbs(arm)) {
805
+ if (!constraintAdmitsNullish(constraint)) {
806
+ return disproved(
807
+ `nullish return arm \u22AD ${formatConstraint(constraint)} (contract does not admit nullish)`
808
+ );
809
+ }
810
+ continue;
811
+ }
812
+ if (isValueSetUnknown(arm) || isWidenedSumArm(arm, parent)) {
813
+ sawUnprovable = true;
814
+ continue;
815
+ }
816
+ const r = assertImpliesSingle(arm, constraint, opts, phi);
817
+ if (r.status === "disproved") {
818
+ if (hasWidenedArm) {
819
+ sawUnprovable = true;
820
+ continue;
821
+ }
822
+ return r;
823
+ }
824
+ if (r.status === "unprovable") sawUnprovable = true;
825
+ }
826
+ return sawUnprovable ? unprovable("sum: some arms unprovable") : proved();
827
+ }
828
+ function assertImpliesSingle(arm, constraint, opts, phi) {
829
+ if (isNullishLitAbs(arm)) {
830
+ return constraintAdmitsNullish(constraint) ? proved() : disproved(`nullish return \u22AD ${formatConstraint(constraint)}`);
831
+ }
832
+ if (isValueSetUnknown(arm)) {
833
+ return unprovable(
834
+ arm.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
835
+ );
836
+ }
772
837
  if (constraint.members && constraint.members.length > 0) {
773
838
  let sawUnprovable = false;
774
839
  for (const m of constraint.members) {
775
- const r = assertImplies(ret, m, opts);
840
+ const r = assertImplies(arm, m, opts);
776
841
  if (r.status === "proved") return proved();
777
842
  if (r.status === "unprovable") sawUnprovable = true;
778
843
  }
779
844
  return sawUnprovable ? unprovable("union: no member proved the return contract") : disproved(`return \u22AD union(${constraint.members.map((m) => formatConstraint(m)).join(", ")})`);
780
845
  }
781
- if (sumMembers && constraint.fields) {
782
- let sawUnprovable = false;
783
- for (const m of sumMembers) {
784
- if (isValueSetUnknown(m)) continue;
785
- const r = assertImplies(m, constraint, opts);
786
- if (r.status === "disproved") return r;
787
- if (r.status === "unprovable") sawUnprovable = true;
788
- }
789
- return sawUnprovable ? unprovable("sum: some arms unprovable") : proved();
790
- }
791
846
  if (constraint.fields) {
792
- return assertShapeFields(ret, constraint, opts);
847
+ return assertShapeFields(arm, constraint, opts);
793
848
  }
794
849
  if (constraint.element) {
795
- if (ret.shape.k !== "arr" && ret.shape.k !== "tuple") {
796
- return disproved(`return shape ${ret.shape.k} \u22AD array(...)`);
850
+ if (arm.shape.k !== "arr" && arm.shape.k !== "tuple") {
851
+ return disproved(`return shape ${arm.shape.k} \u22AD array(...)`);
797
852
  }
798
853
  return proved();
799
854
  }
800
855
  if (constraint.fn) return proved();
801
- return assertScalar(ret, constraint, phi);
856
+ return assertScalar(arm, constraint, phi);
802
857
  }
803
858
  function isAnyConstraint(c) {
804
859
  return !c.prim && c.preds.length === 0 && !c.fields && !c.element && !c.members && !c.fn && !isIntFlag(c);
@@ -838,13 +893,18 @@ function assertScalar(ret, constraint, phi) {
838
893
  if (retPrim && retPrim !== constraint.prim) {
839
894
  return disproved(`typeof return = "${retPrim}" \u22AD "${constraint.prim}"`);
840
895
  }
841
- if (!retPrim && ret.shape.k !== "sum" && ret.shape.k !== "never") {
896
+ if (!retPrim) {
897
+ const k = ret.shape.k;
898
+ if (k === "obj" || k === "arr" || k === "tuple" || k === "fn" || k === "brand" || k === "eff") {
899
+ return disproved(`return shape ${k} \u22AD prim "${constraint.prim}"`);
900
+ }
842
901
  }
843
902
  }
844
903
  if (isIntFlag(constraint) && constraint.prim === "number") {
845
- const lv2 = litValue(ret);
846
- if (typeof lv2 === "number" && !Number.isInteger(lv2)) {
847
- return disproved(`return ${lv2} \u22AD int`);
904
+ const lvR = litValue(ret);
905
+ const lv = lvR.ok ? lvR.value : void 0;
906
+ if (typeof lv === "number" && !Number.isInteger(lv)) {
907
+ return disproved(`return ${lv} \u22AD int`);
848
908
  }
849
909
  }
850
910
  const t = retAnchorTerm(ret);
@@ -867,18 +927,17 @@ function assertScalar(ret, constraint, phi) {
867
927
  );
868
928
  }
869
929
  }
870
- const lv = litValue(ret);
871
- if (lv !== void 0 && (typeof lv === "number" || typeof lv === "string" || typeof lv === "boolean" || lv === null)) {
872
- if (literalMeetsConstraint(lv, constraint)) {
873
- return proved();
930
+ if (ret.term?.op === "lit") {
931
+ const lv = ret.term.value;
932
+ if (typeof lv === "number" || typeof lv === "string" || typeof lv === "boolean" || lv === null || lv === void 0) {
933
+ if (literalMeetsConstraint(lv, constraint)) {
934
+ return proved();
935
+ }
936
+ const boundDesc = describeBoundViolation(lv, constraint);
937
+ return disproved(
938
+ boundDesc ?? `return ${JSON.stringify(lv)} \u22AD ${formatConstraint(constraint)}`
939
+ );
874
940
  }
875
- const boundDesc = describeBoundViolation(lv, constraint);
876
- return disproved(
877
- boundDesc ?? `return ${JSON.stringify(lv)} \u22AD ${formatConstraint(constraint)}`
878
- );
879
- }
880
- if (ret.term?.op === "lit" && ret.term.value === void 0) {
881
- return proved();
882
941
  }
883
942
  if (constraintPred.op !== "true" || constraint.preds.length > 0) {
884
943
  if (isBoundedEvidenceMissing(ret, constraint)) {
@@ -924,7 +983,8 @@ function litLE(a, b) {
924
983
  }
925
984
  function primOfAbs(a) {
926
985
  if (a.shape.k === "prim") return a.shape.type;
927
- const lv = litValue(a);
986
+ const lvR = litValue(a);
987
+ const lv = lvR.ok ? lvR.value : void 0;
928
988
  if (typeof lv === "number") return "number";
929
989
  if (typeof lv === "string") return "string";
930
990
  if (typeof lv === "boolean") return "boolean";
@@ -1513,7 +1573,7 @@ function unindexCheckKey(key) {
1513
1573
  function evictCheckSourceMemoForPaths(paths) {
1514
1574
  let n = 0;
1515
1575
  for (const raw of paths) {
1516
- const p = normPath(raw);
1576
+ const p = stablePathKey(raw);
1517
1577
  const keys = checkDepIndex.get(p);
1518
1578
  if (!keys) continue;
1519
1579
  for (const key of [...keys]) {
@@ -1589,8 +1649,9 @@ function checkMemoSet(key, value, depPaths) {
1589
1649
  }
1590
1650
  checkReportMemo.set(key, value);
1591
1651
  if (depPaths.length > 0) {
1592
- checkKeyDeps.set(key, depPaths);
1593
- for (const p of depPaths) {
1652
+ const normDeps = [...new Set(depPaths.map(stablePathKey))];
1653
+ checkKeyDeps.set(key, normDeps);
1654
+ for (const p of normDeps) {
1594
1655
  let set = checkDepIndex.get(p);
1595
1656
  if (!set) {
1596
1657
  set = /* @__PURE__ */ new Set();
@@ -1915,13 +1976,14 @@ function scanCaseInconsistency(source, knownFns, opts) {
1915
1976
  }
1916
1977
  arg = projected;
1917
1978
  }
1918
- const lv = litValue(arg);
1919
- if (lv === void 0 || typeof lv !== "number" && typeof lv !== "string" && typeof lv !== "boolean") {
1979
+ const argLit = arg.term?.op === "lit" ? arg.term.value : void 0;
1980
+ const argIsLit = arg.term?.op === "lit";
1981
+ if (!argIsLit || typeof argLit !== "number" && typeof argLit !== "string" && typeof argLit !== "boolean" && argLit !== null && argLit !== void 0) {
1920
1982
  continue;
1921
1983
  }
1922
1984
  const hasEqOr = (entry.constraint.members?.length ?? 0) > 0 || entry.constraint.preds.some((p) => p.op === "eq");
1923
1985
  if (hasEqOr) {
1924
- if (!literalMeetsConstraint(lv, entry.constraint)) {
1986
+ if (!literalMeetsConstraint(argLit, entry.constraint)) {
1925
1987
  const paramName = entry.param || paramNames[idx] || `arg${idx}`;
1926
1988
  out.push({
1927
1989
  severity: "error",
@@ -1936,16 +1998,16 @@ function scanCaseInconsistency(source, knownFns, opts) {
1936
1998
  }
1937
1999
  continue;
1938
2000
  }
1939
- if (typeof lv !== "number") continue;
2001
+ if (typeof argLit !== "number") continue;
1940
2002
  const flatten = (p) => p.op === "and" ? p.args.flatMap(flatten) : p.op === "true" ? [] : [p];
1941
2003
  for (const p of flatten(entry.pred)) {
1942
2004
  if ((p.op === "gt" || p.op === "ge" || p.op === "lt" || p.op === "le") && p.b.op === "lit" && typeof p.b.value === "number") {
1943
2005
  const n = p.b.value;
1944
2006
  let ok = true;
1945
- if (p.op === "gt") ok = lv > n;
1946
- if (p.op === "ge") ok = lv >= n;
1947
- if (p.op === "lt") ok = lv < n;
1948
- if (p.op === "le") ok = lv <= n;
2007
+ if (p.op === "gt") ok = argLit > n;
2008
+ if (p.op === "ge") ok = argLit >= n;
2009
+ if (p.op === "lt") ok = argLit < n;
2010
+ if (p.op === "le") ok = argLit <= n;
1949
2011
  if (!ok) {
1950
2012
  const paramName = entry.param || paramNames[idx] || `arg${idx}`;
1951
2013
  out.push({
@@ -1963,36 +2025,18 @@ function scanCaseInconsistency(source, knownFns, opts) {
1963
2025
  }
1964
2026
  }
1965
2027
  };
1966
- const visit = (n) => {
1967
- if (!n || typeof n !== "object") return;
1968
- const obj2 = n;
1969
- let decl = obj2;
1970
- if (obj2.type === "ExportNamedDeclaration" || obj2.type === "ExportDefaultDeclaration") {
1971
- decl = obj2.declaration;
1972
- }
1973
- if (decl && (decl.type === "FunctionDeclaration" || decl.type === "VariableDeclaration" && (decl.declarations ?? [])[0]?.init && ["ArrowFunctionExpression", "FunctionExpression"].includes(
1974
- String(
1975
- decl.declarations[0].init.type
1976
- )
1977
- ))) {
1978
- const id = decl.type === "FunctionDeclaration" ? decl.id?.name : decl.declarations[0]?.id?.name;
1979
- if (id && knownFns.includes(id)) {
1980
- for (const c of obj2.leadingComments ?? []) {
1981
- const caseArgs = parseCaseArgs(c.value);
1982
- if (!caseArgs) continue;
1983
- const caseName = /@nudo:case\s+"([^"]+)"/.exec(c.value)?.[1] ?? "?";
1984
- checkCaseAgainstReqs(id, caseName, caseArgs, c.loc?.start.line);
1985
- }
2028
+ for (const scope of listFnDirectiveScopes(file)) {
2029
+ if (!knownFns.includes(scope.name)) continue;
2030
+ for (let ci = 0; ci < scope.commentTexts.length; ci++) {
2031
+ const text = scope.commentTexts[ci];
2032
+ const startLine = scope.commentStartLines[ci] ?? 0;
2033
+ for (const tag of scanCaseTags(text)) {
2034
+ const caseArgs = parseCaseArgs(`@nudo:case "${tag.name}" (${tag.argsText})`);
2035
+ if (!caseArgs) continue;
2036
+ checkCaseAgainstReqs(scope.name, tag.name, caseArgs, startLine);
1986
2037
  }
1987
2038
  }
1988
- for (const key of Object.keys(obj2)) {
1989
- if (key === "loc" || key === "start" || key === "end" || key === "leadingComments") continue;
1990
- const val = obj2[key];
1991
- if (Array.isArray(val)) val.forEach(visit);
1992
- else if (val && typeof val === "object") visit(val);
1993
- }
1994
- };
1995
- visit(file);
2039
+ }
1996
2040
  return out;
1997
2041
  }
1998
2042
 
@@ -2085,7 +2129,8 @@ function sidecarDiagIssues(diags) {
2085
2129
  const k = `${d.code}\0${d.message}`;
2086
2130
  if (seen.has(k)) continue;
2087
2131
  seen.add(k);
2088
- out.push({ severity: "error", code: d.code, message: d.message });
2132
+ const severity = d.code === "nudo:contract-syntax" || d.code === "nudo:directive-syntax" ? "warning" : "error";
2133
+ out.push({ severity, code: d.code, message: d.message });
2089
2134
  }
2090
2135
  return out;
2091
2136
  }
@@ -2201,7 +2246,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2201
2246
  message: `${name} (export): may throw ${gateDisplay}`,
2202
2247
  actual: `${name}(\u2026) throws ${gateDisplay}`,
2203
2248
  expected: "entry total, or @nudo:throws / try-catch",
2204
- suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} / sidecar fn({ \u2026 }) contract / refine / guard / try-catch`}` : first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} / sidecar fn({ \u2026 }) contract / refine / guard / try-catch`,
2249
+ suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`}` : first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`,
2205
2250
  fn: name,
2206
2251
  ...loc.line !== void 0 ? { line: loc.line } : {},
2207
2252
  ...loc.column !== void 0 ? { column: loc.column } : {}
@@ -2246,7 +2291,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2246
2291
  message: `${name} (export): may throw ${gateDisplay}`,
2247
2292
  actual: `${formatEntrySigLine(name, g, gateDisplay)}`,
2248
2293
  expected: "entry total, or @nudo:throws / try-catch",
2249
- suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} / sidecar fn({ \u2026 }) contract / refine / guard / try-catch`}` : first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} / sidecar fn({ \u2026 }) contract / refine / guard / try-catch`,
2294
+ suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`}` : first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`,
2250
2295
  fn: name,
2251
2296
  ...loc.line !== void 0 ? { line: loc.line } : {},
2252
2297
  ...loc.column !== void 0 ? { column: loc.column } : {}
@@ -2614,6 +2659,19 @@ function actionsForIssue(i) {
2614
2659
  label: "migration switch: ignore this throw class on L2"
2615
2660
  }
2616
2661
  ];
2662
+ case "nudo:unproven-return":
2663
+ return [
2664
+ {
2665
+ kind: "relax",
2666
+ label: `relax the return contract${i.fn ? ` of ${i.fn}` : ""} to the inferred surface (review the diff \u2014 not a silent green)`,
2667
+ ...i.expected ? { hint: i.expected } : {}
2668
+ },
2669
+ draft,
2670
+ {
2671
+ kind: "info",
2672
+ label: "or narrow the return expression / add a precondition so the bound is implied"
2673
+ }
2674
+ ];
2617
2675
  case "nudo:unknown-inference":
2618
2676
  case "nudo:opaque-result":
2619
2677
  return [
@@ -2979,6 +3037,9 @@ export {
2979
3037
  $while,
2980
3038
  $whileSeq,
2981
3039
  $yield,
3040
+ CONSTRAINT_BUILDERS,
3041
+ CONSTRAINT_BUILDER_NAMES,
3042
+ CONSTRAINT_EXPR_RE,
2982
3043
  DEFAULT_MAX_LOOP_ITERS,
2983
3044
  MAX_EVAL_CALL_DEPTH,
2984
3045
  MAX_EVAL_TOTAL_CALLS,
@@ -2993,6 +3054,7 @@ export {
2993
3054
  TYPEOF_NAMES,
2994
3055
  abs,
2995
3056
  absFunction,
3057
+ absOnly,
2996
3058
  absShapeKey,
2997
3059
  absToConstraint,
2998
3060
  absToString,
@@ -3031,6 +3093,7 @@ export {
3031
3093
  callAbsMethod,
3032
3094
  callAtFunctionBoundary,
3033
3095
  callTranspiledExport,
3096
+ callTranspiledExportApply,
3034
3097
  callTranspiledExportFull,
3035
3098
  canonicalArrayIndex,
3036
3099
  checkArg,
@@ -3090,16 +3153,22 @@ export {
3090
3153
  evictGeneralizeMemoForPaths,
3091
3154
  execNudoModule,
3092
3155
  extStateOf,
3156
+ extractBalancedParens,
3093
3157
  extractDeclaredThrows,
3158
+ extractFileEnvNames,
3094
3159
  extractFn,
3095
3160
  extractFnBudget,
3161
+ extractMockModuleRecords,
3162
+ extractNudoImportRecords,
3096
3163
  extractNudoImports,
3097
3164
  extractRefineReturnFromSource,
3098
3165
  extractRefinesFromSource,
3099
3166
  falseConstraint,
3100
3167
  fillTuple,
3168
+ findFnDirectiveScope,
3101
3169
  fn,
3102
3170
  fnConstraintToEntryReqs,
3171
+ fnDirectiveCommentLines,
3103
3172
  fnOf,
3104
3173
  foldRequireSpecArg,
3105
3174
  foldStaticStringExpr,
@@ -3141,6 +3210,7 @@ export {
3141
3210
  interfaceDiagCount,
3142
3211
  interfaceSourceOf,
3143
3212
  interfaceTierOf,
3213
+ isAbsApplyResult,
3144
3214
  isArrMutator,
3145
3215
  isBigPrim,
3146
3216
  isDefinitelyFalse,
@@ -3174,6 +3244,7 @@ export {
3174
3244
  leavePromiseExecutorScope,
3175
3245
  lenTerm,
3176
3246
  leqAbs,
3247
+ listFnDirectiveScopes,
3177
3248
  listFunctionNames,
3178
3249
  lit,
3179
3250
  litC,
@@ -3186,6 +3257,7 @@ export {
3186
3257
  looseEqAbs,
3187
3258
  lt,
3188
3259
  ltNum,
3260
+ makeAbsApplyResult,
3189
3261
  makeArrayCtorAbs,
3190
3262
  makeMapAbs,
3191
3263
  makeSetAbs,
@@ -3235,6 +3307,9 @@ export {
3235
3307
  or,
3236
3308
  pFalse,
3237
3309
  pTrue,
3310
+ parseEnvPayload,
3311
+ parseMockModulePayload,
3312
+ parseNudoImportPayload,
3238
3313
  parseSource,
3239
3314
  partial,
3240
3315
  phiAnd,
@@ -3277,6 +3352,11 @@ export {
3277
3352
  runTranspiledOptionsMemoKey,
3278
3353
  runWithLoopExits,
3279
3354
  runtimeImportOf,
3355
+ scanBudgetDecl,
3356
+ scanCaseArgSpans,
3357
+ scanCaseTags,
3358
+ scanContractSegments,
3359
+ scanThrowsDecl,
3280
3360
  serializeCheckJson,
3281
3361
  serializeCheckJsonMulti,
3282
3362
  setAddEntry,
@@ -1,7 +1,7 @@
1
- import { I as InterfaceSource, a as InterfaceTierOpts, p as parseSource, C as CheckIssue } from './check-report-BWmfy810.js';
2
- export { L as LeakBudget, b as LoadDepsFingerprint, M as MAX_PROMISE_MICROS, d as defaultLeakBudget, e as exceedsBudget, c as extractAllLoadSpecs, g as getPromiseMicrosLength, l as leakIfNeeded, f as loadModuleDepsFingerprint, m as maybeLeak, n as normPath, r as resetLeakCounter, h as resolveDepPath, s as sidecarSpecsOf, t as termDepth, i as termNodes } from './check-report-BWmfy810.js';
3
- import { A as Abs, T as Term, c as AstEnv } from './run-Dk08Q5zl.js';
4
- export { $ as $tryDigestSoft, d as $tryMarkSoft, e as $tryReleaseSoft, E as ERROR_FAMILY, f as EvalFallbackStats, M as MayThrowEffect, g as enterEvalCallBudgetSession, h as errorTypeAbs, i as exitEvalCallBudgetSession, j as filterDeclaredThrows, k as filterGateThrows, l as filterIgnoredThrows, m as flushMayThrowEffects, n as formatThrowsAbs, o as getEvalCallBudgetState, p as getEvalFallbackStats, q as getMayThrowCollector, r as isThrowsIgnored, s as mayThrowEffectsToAbs, t as orphanMayThrowEffects, u as popMayThrowFrame, v as pushMayThrowFrame, w as recordMayThrow, x as resetEvalFallbackStats, y as runWithMayThrowSession, z as setMayThrowCollector, B as throwAbsToKinds, D as throwsKindCovered, F as withEvalBudgetOverride } from './run-Dk08Q5zl.js';
1
+ import { I as InterfaceSource, a as InterfaceTierOpts, p as parseSource, C as CheckIssue } from './check-report-Ci1dDysO.js';
2
+ export { L as LeakBudget, b as LoadDepsFingerprint, M as MAX_PROMISE_MICROS, d as defaultLeakBudget, e as exceedsBudget, c as extractAllLoadSpecs, g as getPromiseMicrosLength, l as leakIfNeeded, f as loadModuleDepsFingerprint, m as maybeLeak, n as normPath, r as resetLeakCounter, h as resolveDepPath, s as sidecarSpecsOf, i as stablePathKey, j as stablePathKeyGraph, t as termDepth, k as termNodes } from './check-report-Ci1dDysO.js';
3
+ import { A as Abs, T as Term, c as AstEnv } from './run-WJfj477N.js';
4
+ export { $ as $tryDigestSoft, d as $tryMarkSoft, e as $tryReleaseSoft, E as ERROR_FAMILY, f as EvalFallbackStats, M as MayThrowEffect, g as clearPureCallMemo, h as clearPureMemo, i as enterEvalCallBudgetSession, j as errorTypeAbs, k as exitEvalCallBudgetSession, l as filterDeclaredThrows, m as filterGateThrows, n as filterIgnoredThrows, o as flushMayThrowEffects, p as formatThrowsAbs, q as getEvalCallBudgetState, r as getEvalFallbackStats, s as getMayThrowCollector, t as isThrowsIgnored, u as mayThrowEffectsToAbs, v as orphanMayThrowEffects, w as popMayThrowFrame, x as pushMayThrowFrame, y as recordMayThrow, z as resetEvalFallbackStats, B as runWithMayThrowSession, D as setMayThrowCollector, F as throwAbsToKinds, G as throwsKindCovered, H as withEvalBudgetOverride } from './run-WJfj477N.js';
5
5
  import { File, Node } from '@babel/types';
6
6
 
7
7
  /**