nudojs 1.1.0 → 1.2.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.
Files changed (2) hide show
  1. package/dist/index.js +1422 -390
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -16209,6 +16209,10 @@ function joinValues(a, b) {
16209
16209
  }
16210
16210
  return makeSum(a, b);
16211
16211
  }
16212
+ const hasPred = (x) => !!x.pred && x.pred.op !== "true";
16213
+ if (hasPred(a) || hasPred(b)) {
16214
+ return makeSum(a, b);
16215
+ }
16212
16216
  return abs(a.shape, void 0, void 0, confJoin(confJoin(a.conf, b.conf), "path"));
16213
16217
  }
16214
16218
  return makeSum(a, b);
@@ -18268,6 +18272,335 @@ var init_invariants = __esm({
18268
18272
  }
18269
18273
  });
18270
18274
 
18275
+ // ../core/src/algebra/containers.ts
18276
+ function shouldWidenArrayLiteral(n) {
18277
+ return n > TUPLE_LITERAL_CAP;
18278
+ }
18279
+ function widenedArrayConf() {
18280
+ return "path";
18281
+ }
18282
+ var TUPLE_LITERAL_CAP, TUPLE_MATERIALIZE_CAP;
18283
+ var init_containers = __esm({
18284
+ "../core/src/algebra/containers.ts"() {
18285
+ "use strict";
18286
+ TUPLE_LITERAL_CAP = 8;
18287
+ TUPLE_MATERIALIZE_CAP = 4096;
18288
+ }
18289
+ });
18290
+
18291
+ // ../core/src/algebra/exec/runtime/state.ts
18292
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
18293
+ function writeInPlace(target, next) {
18294
+ target.shape = next.shape;
18295
+ target.conf = next.conf;
18296
+ target.term = void 0;
18297
+ target.pred = void 0;
18298
+ return target;
18299
+ }
18300
+ function clearStaleTermPred(v2) {
18301
+ v2.term = void 0;
18302
+ v2.pred = void 0;
18303
+ }
18304
+ function currentExecPhi() {
18305
+ return phi;
18306
+ }
18307
+ function withExecPhi(p, body) {
18308
+ const prev = phi;
18309
+ phi = p;
18310
+ try {
18311
+ return body();
18312
+ } finally {
18313
+ phi = prev;
18314
+ }
18315
+ }
18316
+ function asAbsVal(v2) {
18317
+ if (v2 && typeof v2 === "object" && "shape" in v2) return v2;
18318
+ if (typeof v2 === "function") {
18319
+ const n = Math.max(0, v2.length);
18320
+ const params = Array.from({ length: n }, (_, i) => `arg${i}`);
18321
+ return absFunction(params, {
18322
+ body: noBody,
18323
+ // 与 $fnVal / $callNamed 同边界:callee 的 NudoReturn 不得冒泡成 caller
18324
+ apply: (args) => callAtFunctionBoundary(() => v2(...args))
18325
+ });
18326
+ }
18327
+ return $lit(v2);
18328
+ }
18329
+ function callAtFunctionBoundary(body) {
18330
+ let forwarded = [];
18331
+ try {
18332
+ return runWithLoopExits(() => {
18333
+ try {
18334
+ const r = body();
18335
+ forwarded = takeThrowExits();
18336
+ return r;
18337
+ } catch (e) {
18338
+ forwarded = takeThrowExits();
18339
+ if (isNudoReturn(e)) return e.absValue;
18340
+ throw e;
18341
+ }
18342
+ });
18343
+ } finally {
18344
+ for (const x of forwarded) pushThrowExit(x);
18345
+ }
18346
+ }
18347
+ function $fnVal(params, impl, opts) {
18348
+ return absFunction(params, {
18349
+ body: noBody,
18350
+ // bindThis(对象方法):receiver 走首参注入,无宿主 this;
18351
+ // 非方法 fn:宿主 this 传递(call/apply/bind 的 thisArg 经 $rawThis 进入函数体)
18352
+ apply: opts?.bindThis ? (args) => callAtFunctionBoundary(() => impl(...args)) : (args, thisVal) => callAtFunctionBoundary(() => impl.apply(thisVal, args)),
18353
+ ...opts?.bindThis ? { bindThis: true } : {}
18354
+ });
18355
+ }
18356
+ function $rawThis(v2) {
18357
+ if (v2 === void 0 || v2 === globalThis) return $lit(void 0);
18358
+ if (v2 && typeof v2 === "object" && "shape" in v2) return v2;
18359
+ return $lit(v2);
18360
+ }
18361
+ function throwStrictWrite() {
18362
+ throw new NudoThrow(errorTypeAbs("TypeError"));
18363
+ }
18364
+ function $throwConstAssign() {
18365
+ throw new NudoThrow(errorTypeAbs("TypeError"));
18366
+ }
18367
+ function $litTruth(a) {
18368
+ return litTruth(a);
18369
+ }
18370
+ function $lit(v2) {
18371
+ if (v2 && typeof v2 === "object" && "shape" in v2 && "conf" in v2) {
18372
+ return v2;
18373
+ }
18374
+ return litAbsFromJs(v2);
18375
+ }
18376
+ function litAbsFromJs(v2, depth = 0) {
18377
+ if (v2 === null || v2 === void 0) {
18378
+ return abs({ k: "unknown" }, { op: "lit", value: v2 }, pTrue, "exact");
18379
+ }
18380
+ const t = typeof v2;
18381
+ if (t === "number" || t === "string" || t === "boolean" || t === "bigint") {
18382
+ return abs(
18383
+ { k: "prim", type: t },
18384
+ { op: "lit", value: v2 },
18385
+ pTrue,
18386
+ "exact"
18387
+ );
18388
+ }
18389
+ if (depth < 8) {
18390
+ if (Array.isArray(v2)) {
18391
+ const els = v2.map((x) => litAbsFromJs(x, depth + 1));
18392
+ if (shouldWidenArrayLiteral(els.length)) {
18393
+ return abs(
18394
+ { k: "arr", element: els.reduce((x, y) => joinAbs(x, y)) },
18395
+ void 0,
18396
+ void 0,
18397
+ widenedArrayConf()
18398
+ );
18399
+ }
18400
+ return abs({ k: "tuple", elements: els }, void 0, void 0, "exact");
18401
+ }
18402
+ if (t === "object") {
18403
+ const proto = Object.getPrototypeOf(v2);
18404
+ if (proto === Object.prototype || proto === null) {
18405
+ const slots = {};
18406
+ for (const [k, val] of Object.entries(v2)) {
18407
+ Object.defineProperty(slots, k, {
18408
+ value: { value: litAbsFromJs(val, depth + 1) },
18409
+ enumerable: true,
18410
+ writable: true,
18411
+ configurable: true
18412
+ });
18413
+ }
18414
+ return objOf(slots);
18415
+ }
18416
+ }
18417
+ }
18418
+ return unknown;
18419
+ }
18420
+ function litTruth(a) {
18421
+ if (a.term?.op === "lit") {
18422
+ return Boolean(a.term.value);
18423
+ }
18424
+ switch (a.shape.k) {
18425
+ case "obj":
18426
+ case "arr":
18427
+ case "tuple":
18428
+ case "fn":
18429
+ case "brand":
18430
+ case "eff":
18431
+ return true;
18432
+ case "prim":
18433
+ return a.shape.type === "symbol" ? true : void 0;
18434
+ case "never":
18435
+ return false;
18436
+ default:
18437
+ return void 0;
18438
+ }
18439
+ }
18440
+ function isDefinitelyTrue(a) {
18441
+ return litTruth(a) === true;
18442
+ }
18443
+ function isDefinitelyFalse(a) {
18444
+ const t = litTruth(a);
18445
+ if (t === false) return true;
18446
+ if (a.shape.k === "never") return true;
18447
+ return false;
18448
+ }
18449
+ function undef() {
18450
+ return abs({ k: "unknown" }, { op: "lit", value: void 0 }, pTrue, "exact");
18451
+ }
18452
+ function runWithLoopExits(body) {
18453
+ return loopExitsAls.run(
18454
+ [],
18455
+ () => throwExitsAls.run(
18456
+ [],
18457
+ () => tryMarksAls.run([], () => softFrameActiveAls.run([], body))
18458
+ )
18459
+ );
18460
+ }
18461
+ function takeLoopExits() {
18462
+ return loopExitsAls.getStore() ?? [];
18463
+ }
18464
+ function takeThrowExits() {
18465
+ return throwExitsAls.getStore() ?? [];
18466
+ }
18467
+ function pushLoopExit(v2) {
18468
+ loopExitsAls.getStore()?.push(v2);
18469
+ }
18470
+ function pushThrowExit(v2) {
18471
+ throwExitsAls.getStore()?.push(v2);
18472
+ }
18473
+ function $pushLoopExit(v2) {
18474
+ pushLoopExit(v2);
18475
+ }
18476
+ function $tryMark() {
18477
+ $tryMarkSoft();
18478
+ softFrameActiveAls.getStore()?.push(true);
18479
+ const store = throwExitsAls.getStore();
18480
+ const m = store?.length ?? 0;
18481
+ tryMarksAls.getStore()?.push(m);
18482
+ return m;
18483
+ }
18484
+ function $tryCurrentMark() {
18485
+ const stack = tryMarksAls.getStore();
18486
+ return stack && stack.length > 0 ? stack[stack.length - 1] : 0;
18487
+ }
18488
+ function $tryPopMark() {
18489
+ tryMarksAls.getStore()?.pop();
18490
+ const soft = softFrameActiveAls.getStore();
18491
+ if (soft && soft.length > 0) {
18492
+ if (soft[soft.length - 1]) $tryReleaseSoftOut();
18493
+ soft.pop();
18494
+ }
18495
+ }
18496
+ function $tryTakeSince(mark) {
18497
+ const store = throwExitsAls.getStore();
18498
+ if (!store) return [];
18499
+ return store.splice(Math.min(mark, store.length));
18500
+ }
18501
+ function peekThrowExitsSince(mark) {
18502
+ const store = throwExitsAls.getStore();
18503
+ if (!store) return [];
18504
+ return store.slice(Math.min(mark, store.length));
18505
+ }
18506
+ function throwExitsMark() {
18507
+ return throwExitsAls.getStore()?.length ?? 0;
18508
+ }
18509
+ function $tryDigestSoftCatch() {
18510
+ const soft = softFrameActiveAls.getStore();
18511
+ if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
18512
+ $tryDigestSoft();
18513
+ soft[soft.length - 1] = false;
18514
+ }
18515
+ function $tryReleaseSoftCatch() {
18516
+ const soft = softFrameActiveAls.getStore();
18517
+ if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
18518
+ $tryReleaseSoft();
18519
+ soft[soft.length - 1] = false;
18520
+ }
18521
+ function $tryDetachSoftCatch() {
18522
+ const soft = softFrameActiveAls.getStore();
18523
+ if (!soft || soft.length === 0 || !soft[soft.length - 1]) return [];
18524
+ const effects = popMayThrowFrame(false);
18525
+ soft[soft.length - 1] = false;
18526
+ return effects;
18527
+ }
18528
+ function $tryDiscardSoft(_effects) {
18529
+ }
18530
+ function $tryOrphanSoft(effects) {
18531
+ orphanMayThrowEffects(effects);
18532
+ }
18533
+ function $tryReleaseSoftOut() {
18534
+ const soft = softFrameActiveAls.getStore();
18535
+ if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
18536
+ $tryReleaseSoft();
18537
+ soft[soft.length - 1] = false;
18538
+ }
18539
+ function isNudoReturn(e) {
18540
+ return e instanceof NudoReturn;
18541
+ }
18542
+ function $loopReturn(v2) {
18543
+ throw new NudoReturn(v2);
18544
+ }
18545
+ function $loopBreak(label) {
18546
+ throw new NudoLoopSignal("break", label || void 0);
18547
+ }
18548
+ function $loopContinue(label) {
18549
+ throw new NudoLoopSignal("continue", label || void 0);
18550
+ }
18551
+ function loopSignalMatches(e, label) {
18552
+ return e.label === void 0 || e.label === label;
18553
+ }
18554
+ function isNudoBreak(e, label) {
18555
+ return e instanceof NudoLoopSignal && e.kind === "break" && loopSignalMatches(e, label);
18556
+ }
18557
+ function isNudoContinue(e, label) {
18558
+ return e instanceof NudoLoopSignal && e.kind === "continue" && loopSignalMatches(e, label);
18559
+ }
18560
+ function $isBreakTo(e, label) {
18561
+ return e instanceof NudoLoopSignal && e.kind === "break" && e.label === label;
18562
+ }
18563
+ function $rethrowIfNudoReturn(e) {
18564
+ if (isNudoReturn(e)) throw e;
18565
+ }
18566
+ var phi, noBody, loopExitsAls, throwExitsAls, tryMarksAls, softFrameActiveAls, NudoReturn, NudoLoopSignal;
18567
+ var init_state = __esm({
18568
+ "../core/src/algebra/exec/runtime/state.ts"() {
18569
+ "use strict";
18570
+ init_abs();
18571
+ init_pred();
18572
+ init_abs_fn();
18573
+ init_nudo_throw();
18574
+ init_may_throw();
18575
+ init_containers();
18576
+ init_objects();
18577
+ phi = pTrue;
18578
+ noBody = { type: "BlockStatement", body: [], directives: [] };
18579
+ loopExitsAls = new AsyncLocalStorage2();
18580
+ throwExitsAls = new AsyncLocalStorage2();
18581
+ tryMarksAls = new AsyncLocalStorage2();
18582
+ softFrameActiveAls = new AsyncLocalStorage2();
18583
+ NudoReturn = class extends Error {
18584
+ absValue;
18585
+ constructor(absValue) {
18586
+ super("nudo:return");
18587
+ this.name = "NudoReturn";
18588
+ this.absValue = absValue;
18589
+ }
18590
+ };
18591
+ NudoLoopSignal = class extends Error {
18592
+ kind;
18593
+ label;
18594
+ constructor(kind, label) {
18595
+ super("nudo:loop");
18596
+ this.name = "NudoLoopSignal";
18597
+ this.kind = kind;
18598
+ this.label = label;
18599
+ }
18600
+ };
18601
+ }
18602
+ });
18603
+
18271
18604
  // ../core/src/algebra/builtins/shared.ts
18272
18605
  function numPrim(conf = "path") {
18273
18606
  return abs({ k: "prim", type: "number" }, void 0, void 0, conf);
@@ -18291,12 +18624,12 @@ function isPrimLike(a) {
18291
18624
  }
18292
18625
  return false;
18293
18626
  }
18294
- var noBody;
18627
+ var noBody2;
18295
18628
  var init_shared = __esm({
18296
18629
  "../core/src/algebra/builtins/shared.ts"() {
18297
18630
  "use strict";
18298
18631
  init_abs();
18299
- noBody = { type: "BlockStatement", body: [], directives: [] };
18632
+ noBody2 = { type: "BlockStatement", body: [], directives: [] };
18300
18633
  }
18301
18634
  });
18302
18635
 
@@ -18316,8 +18649,194 @@ function mathMethod(name) {
18316
18649
  const impl = Math[name];
18317
18650
  return typeof impl === "function" ? impl : void 0;
18318
18651
  }
18652
+ function isNonNaN(a, phi2) {
18653
+ if (a.term?.op === "lit") {
18654
+ return typeof a.term.value === "number" && !Number.isNaN(a.term.value);
18655
+ }
18656
+ const hasNonNaNFact = (p) => {
18657
+ if (!p) return false;
18658
+ if (p.op === "and") return p.args.some(hasNonNaNFact);
18659
+ if (p.op === "assumeFinite") {
18660
+ return !!a.term && termEquals(p.t, a.term);
18661
+ }
18662
+ if (p.op === "ne") {
18663
+ if (p.b.op === "lit" && typeof p.b.value === "number" && Number.isNaN(p.b.value) && a.term && termEquals(p.a, a.term)) {
18664
+ return true;
18665
+ }
18666
+ }
18667
+ if (p.op === "gt" || p.op === "ge" || p.op === "lt" || p.op === "le") {
18668
+ if (a.term && (termEquals(p.a, a.term) || termEquals(p.b, a.term))) return true;
18669
+ }
18670
+ return false;
18671
+ };
18672
+ if (hasNonNaNFact(a.pred)) return true;
18673
+ if (a.term?.op === "var") {
18674
+ const id = a.term.id;
18675
+ const conjs = phi2.op === "and" ? phi2.args : [phi2];
18676
+ for (const p of conjs) {
18677
+ if (p.op === "assumeFinite" && p.t.op === "var" && p.t.id === id) {
18678
+ return true;
18679
+ }
18680
+ if (p.op === "ne") {
18681
+ const b = p.b;
18682
+ if (b.op === "lit" && typeof b.value === "number" && Number.isNaN(b.value) && p.a.op === "var" && p.a.id === id) {
18683
+ return true;
18684
+ }
18685
+ }
18686
+ if (p.op === "gt" || p.op === "ge" || p.op === "lt" || p.op === "le") {
18687
+ const sides = [p.a, p.b];
18688
+ if (sides.some((t) => t.op === "var" && t.id === id) && sides.some((t) => t.op === "lit" && typeof t.value === "number")) {
18689
+ return true;
18690
+ }
18691
+ }
18692
+ }
18693
+ }
18694
+ return false;
18695
+ }
18696
+ function ieeeBoundNum(n) {
18697
+ return Number.isFinite(n) || n === Infinity || n === -Infinity ? n : void 0;
18698
+ }
18699
+ function loMin(a, b) {
18700
+ if (a.lo === void 0 || b.lo === void 0) return void 0;
18701
+ if (b.lo.value < a.lo.value) return b.lo;
18702
+ if (b.lo.value === a.lo.value && b.lo.strict && !a.lo.strict) return b.lo;
18703
+ return a.lo;
18704
+ }
18705
+ function loMax(a, b) {
18706
+ if (a.lo === void 0) return b.lo;
18707
+ if (b.lo === void 0) return a.lo;
18708
+ if (b.lo.value > a.lo.value) return b.lo;
18709
+ if (b.lo.value === a.lo.value && b.lo.strict && !a.lo.strict) return b.lo;
18710
+ return a.lo;
18711
+ }
18712
+ function hiMin(a, b) {
18713
+ if (a.hi === void 0) return b.hi;
18714
+ if (b.hi === void 0) return a.hi;
18715
+ if (b.hi.value < a.hi.value) return b.hi;
18716
+ if (b.hi.value === a.hi.value && b.hi.strict && !a.hi.strict) return b.hi;
18717
+ return a.hi;
18718
+ }
18719
+ function hiMax(a, b) {
18720
+ if (a.hi === void 0 || b.hi === void 0) return void 0;
18721
+ if (b.hi.value > a.hi.value) return b.hi;
18722
+ if (b.hi.value === a.hi.value && b.hi.strict && !a.hi.strict) return b.hi;
18723
+ return a.hi;
18724
+ }
18725
+ function boundsToPred(t, b) {
18726
+ const facts = [];
18727
+ if (b.lo !== void 0) {
18728
+ const v2 = ieeeBoundNum(b.lo.value);
18729
+ if (v2 !== void 0) {
18730
+ facts.push(b.lo.strict ? { op: "gt", a: t, b: lit(v2) } : { op: "ge", a: t, b: lit(v2) });
18731
+ }
18732
+ }
18733
+ if (b.hi !== void 0) {
18734
+ const v2 = ieeeBoundNum(b.hi.value);
18735
+ if (v2 !== void 0) {
18736
+ facts.push(b.hi.strict ? { op: "lt", a: t, b: lit(v2) } : { op: "le", a: t, b: lit(v2) });
18737
+ }
18738
+ }
18739
+ if (facts.length === 0) return void 0;
18740
+ return facts.length === 1 ? facts[0] : and(...facts);
18741
+ }
18742
+ function minMaxAbs(name, args) {
18743
+ const phi2 = currentExecPhi();
18744
+ const empty = {};
18745
+ let acc = empty;
18746
+ const termArgs = args.map(
18747
+ (a, i) => a.term ?? app(`arg${i}`, [])
18748
+ );
18749
+ const term = simplifyTerm(app(`Math.${name}`, termArgs));
18750
+ let first = true;
18751
+ let mayNaN = false;
18752
+ for (const a of args) {
18753
+ if (!isNonNaN(a, phi2)) mayNaN = true;
18754
+ const b = numericBounds(a, phi2) ?? {};
18755
+ if (first) {
18756
+ acc = { lo: b.lo, hi: b.hi };
18757
+ first = false;
18758
+ continue;
18759
+ }
18760
+ if (name === "min") {
18761
+ acc = { lo: loMin(acc, b), hi: hiMin(acc, b) };
18762
+ } else {
18763
+ acc = { lo: loMax(acc, b), hi: hiMax(acc, b) };
18764
+ }
18765
+ }
18766
+ const pred = boundsToPred(term, acc);
18767
+ const bounded = abs({ k: "prim", type: "number" }, term, pred, "path");
18768
+ if (!mayNaN) return bounded;
18769
+ const nanArm = numLit(NaN);
18770
+ return makeSum(nanArm, bounded);
18771
+ }
18772
+ function roundingAbs(name, arg) {
18773
+ const phi2 = currentExecPhi();
18774
+ const impl = name === "round" ? Math.round : name === "floor" ? Math.floor : name === "ceil" ? Math.ceil : Math.trunc;
18775
+ const b = numericBounds(arg, phi2);
18776
+ const mayNaN = !isNonNaN(arg, phi2);
18777
+ const term = arg.term ? simplifyTerm(app(`Math.${name}`, [arg.term])) : void 0;
18778
+ let out = {};
18779
+ if (b) {
18780
+ if (b.lo !== void 0) {
18781
+ const v2 = impl(b.lo.value);
18782
+ out.lo = Number.isNaN(v2) ? void 0 : { value: v2, strict: false };
18783
+ }
18784
+ if (b.hi !== void 0) {
18785
+ const v2 = impl(b.hi.value);
18786
+ out.hi = Number.isNaN(v2) ? void 0 : { value: v2, strict: false };
18787
+ }
18788
+ }
18789
+ const pred = term ? boundsToPred(term, out) : void 0;
18790
+ const bounded = abs({ k: "prim", type: "number" }, term, pred, "path");
18791
+ if (!mayNaN) return bounded;
18792
+ return makeSum(numLit(NaN), bounded);
18793
+ }
18319
18794
  function evalMathMethod(name, args) {
18320
18795
  if (name === "random") return numPrim("path");
18796
+ if (name === "min" || name === "max") {
18797
+ const nums2 = [];
18798
+ let allLit = true;
18799
+ for (const a of args) {
18800
+ const n = coerceMathArg(a);
18801
+ if (n === void 0) {
18802
+ allLit = false;
18803
+ break;
18804
+ }
18805
+ if (n === "throw") throw new NudoThrow(errorTypeAbs("TypeError"));
18806
+ nums2.push(n);
18807
+ }
18808
+ if (allLit) {
18809
+ try {
18810
+ return numLit((name === "min" ? Math.min : Math.max)(...nums2));
18811
+ } catch {
18812
+ return numPrim();
18813
+ }
18814
+ }
18815
+ for (const a of args) {
18816
+ const n = coerceMathArg(a);
18817
+ if (n === "throw") throw new NudoThrow(errorTypeAbs("TypeError"));
18818
+ }
18819
+ return minMaxAbs(name, args);
18820
+ }
18821
+ if (name === "round" || name === "floor" || name === "ceil" || name === "trunc") {
18822
+ const n = coerceMathArg(args[0]);
18823
+ if (n === "throw") throw new NudoThrow(errorTypeAbs("TypeError"));
18824
+ if (typeof n === "number") {
18825
+ try {
18826
+ return numLit(
18827
+ name === "round" ? Math.round(n) : name === "floor" ? Math.floor(n) : name === "ceil" ? Math.ceil(n) : Math.trunc(n)
18828
+ );
18829
+ } catch {
18830
+ return numPrim();
18831
+ }
18832
+ }
18833
+ if (args[0]) {
18834
+ const c2 = coerceMathArg(args[0]);
18835
+ if (c2 === "throw") throw new NudoThrow(errorTypeAbs("TypeError"));
18836
+ return roundingAbs(name, args[0]);
18837
+ }
18838
+ return numPrim();
18839
+ }
18321
18840
  const impl = mathMethod(name);
18322
18841
  if (!impl) return void 0;
18323
18842
  const nums = [];
@@ -18337,28 +18856,17 @@ var init_math = __esm({
18337
18856
  "../core/src/algebra/builtins/math.ts"() {
18338
18857
  "use strict";
18339
18858
  init_abs();
18859
+ init_term();
18860
+ init_pred();
18861
+ init_arithmetic();
18862
+ init_objects();
18863
+ init_state();
18340
18864
  init_shared();
18341
18865
  init_nudo_throw();
18342
18866
  init_may_throw();
18343
18867
  }
18344
18868
  });
18345
18869
 
18346
- // ../core/src/algebra/containers.ts
18347
- function shouldWidenArrayLiteral(n) {
18348
- return n > TUPLE_LITERAL_CAP;
18349
- }
18350
- function widenedArrayConf() {
18351
- return "path";
18352
- }
18353
- var TUPLE_LITERAL_CAP, TUPLE_MATERIALIZE_CAP;
18354
- var init_containers = __esm({
18355
- "../core/src/algebra/containers.ts"() {
18356
- "use strict";
18357
- TUPLE_LITERAL_CAP = 8;
18358
- TUPLE_MATERIALIZE_CAP = 4096;
18359
- }
18360
- });
18361
-
18362
18870
  // ../core/src/algebra/builtins/ctor.ts
18363
18871
  function builtinCtorAbs(name) {
18364
18872
  let a = builtinCtorByName.get(name);
@@ -19130,8 +19638,19 @@ function evalNumberStatic(name, args) {
19130
19638
  switch (name) {
19131
19639
  case "isInteger":
19132
19640
  return foldStrictNumberPred(Number.isInteger) ?? boolPrim();
19133
- case "isNaN":
19134
- return foldStrictNumberPred(Number.isNaN) ?? boolPrim();
19641
+ case "isNaN": {
19642
+ const folded = foldStrictNumberPred(Number.isNaN);
19643
+ if (folded) return folded;
19644
+ if (a0Arg?.term) {
19645
+ return abs(
19646
+ { k: "prim", type: "boolean" },
19647
+ void 0,
19648
+ { op: "eq", a: a0Arg.term, b: { op: "lit", value: NaN } },
19649
+ "path"
19650
+ );
19651
+ }
19652
+ return boolPrim();
19653
+ }
19135
19654
  case "isFinite":
19136
19655
  return foldStrictNumberPred(Number.isFinite) ?? boolPrim();
19137
19656
  case "parseInt": {
@@ -20036,7 +20555,7 @@ function arrayJoinToString(recv) {
20036
20555
  }
20037
20556
  function arrayMethodAbs(name) {
20038
20557
  return absFunction(["thisArg"], {
20039
- body: noBody,
20558
+ body: noBody2,
20040
20559
  bindThis: true,
20041
20560
  apply: (a) => {
20042
20561
  const recv = a[0] ?? undefAbs();
@@ -20452,11 +20971,11 @@ function evalPromiseCtor(args) {
20452
20971
  return undefAbs();
20453
20972
  };
20454
20973
  const resolveAbs = absFunction(["value"], {
20455
- body: noBody,
20974
+ body: noBody2,
20456
20975
  apply: (args2) => onResolve(args2[0])
20457
20976
  });
20458
20977
  const rejectAbs = absFunction(["reason"], {
20459
- body: noBody,
20978
+ body: noBody2,
20460
20979
  apply: (args2) => onReject(args2[0])
20461
20980
  });
20462
20981
  enterPromiseExecutorScope();
@@ -21193,7 +21712,7 @@ function evalObjectProtoMethod(name, thisVal, args) {
21193
21712
  }
21194
21713
  function objectProtoMethodAbs(name) {
21195
21714
  return absFunction(["thisArg", "arg0"], {
21196
- body: noBody,
21715
+ body: noBody2,
21197
21716
  bindThis: true,
21198
21717
  apply: (a) => {
21199
21718
  const recv = a[0] ?? undefLit();
@@ -28294,319 +28813,6 @@ var init_transpile = __esm({
28294
28813
  }
28295
28814
  });
28296
28815
 
28297
- // ../core/src/algebra/exec/runtime/state.ts
28298
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
28299
- function writeInPlace(target, next) {
28300
- target.shape = next.shape;
28301
- target.conf = next.conf;
28302
- target.term = void 0;
28303
- target.pred = void 0;
28304
- return target;
28305
- }
28306
- function clearStaleTermPred(v2) {
28307
- v2.term = void 0;
28308
- v2.pred = void 0;
28309
- }
28310
- function currentExecPhi() {
28311
- return phi;
28312
- }
28313
- function withExecPhi(p, body) {
28314
- const prev = phi;
28315
- phi = p;
28316
- try {
28317
- return body();
28318
- } finally {
28319
- phi = prev;
28320
- }
28321
- }
28322
- function asAbsVal(v2) {
28323
- if (v2 && typeof v2 === "object" && "shape" in v2) return v2;
28324
- if (typeof v2 === "function") {
28325
- const n = Math.max(0, v2.length);
28326
- const params = Array.from({ length: n }, (_, i) => `arg${i}`);
28327
- return absFunction(params, {
28328
- body: noBody2,
28329
- // 与 $fnVal / $callNamed 同边界:callee 的 NudoReturn 不得冒泡成 caller
28330
- apply: (args) => callAtFunctionBoundary(() => v2(...args))
28331
- });
28332
- }
28333
- return $lit(v2);
28334
- }
28335
- function callAtFunctionBoundary(body) {
28336
- let forwarded = [];
28337
- try {
28338
- return runWithLoopExits(() => {
28339
- try {
28340
- const r = body();
28341
- forwarded = takeThrowExits();
28342
- return r;
28343
- } catch (e) {
28344
- forwarded = takeThrowExits();
28345
- if (isNudoReturn(e)) return e.absValue;
28346
- throw e;
28347
- }
28348
- });
28349
- } finally {
28350
- for (const x of forwarded) pushThrowExit(x);
28351
- }
28352
- }
28353
- function $fnVal(params, impl, opts) {
28354
- return absFunction(params, {
28355
- body: noBody2,
28356
- // bindThis(对象方法):receiver 走首参注入,无宿主 this;
28357
- // 非方法 fn:宿主 this 传递(call/apply/bind 的 thisArg 经 $rawThis 进入函数体)
28358
- apply: opts?.bindThis ? (args) => callAtFunctionBoundary(() => impl(...args)) : (args, thisVal) => callAtFunctionBoundary(() => impl.apply(thisVal, args)),
28359
- ...opts?.bindThis ? { bindThis: true } : {}
28360
- });
28361
- }
28362
- function $rawThis(v2) {
28363
- if (v2 === void 0 || v2 === globalThis) return $lit(void 0);
28364
- if (v2 && typeof v2 === "object" && "shape" in v2) return v2;
28365
- return $lit(v2);
28366
- }
28367
- function throwStrictWrite() {
28368
- throw new NudoThrow(errorTypeAbs("TypeError"));
28369
- }
28370
- function $throwConstAssign() {
28371
- throw new NudoThrow(errorTypeAbs("TypeError"));
28372
- }
28373
- function $litTruth(a) {
28374
- return litTruth(a);
28375
- }
28376
- function $lit(v2) {
28377
- if (v2 && typeof v2 === "object" && "shape" in v2 && "conf" in v2) {
28378
- return v2;
28379
- }
28380
- return litAbsFromJs(v2);
28381
- }
28382
- function litAbsFromJs(v2, depth = 0) {
28383
- if (v2 === null || v2 === void 0) {
28384
- return abs({ k: "unknown" }, { op: "lit", value: v2 }, pTrue, "exact");
28385
- }
28386
- const t = typeof v2;
28387
- if (t === "number" || t === "string" || t === "boolean" || t === "bigint") {
28388
- return abs(
28389
- { k: "prim", type: t },
28390
- { op: "lit", value: v2 },
28391
- pTrue,
28392
- "exact"
28393
- );
28394
- }
28395
- if (depth < 8) {
28396
- if (Array.isArray(v2)) {
28397
- const els = v2.map((x) => litAbsFromJs(x, depth + 1));
28398
- if (shouldWidenArrayLiteral(els.length)) {
28399
- return abs(
28400
- { k: "arr", element: els.reduce((x, y) => joinAbs(x, y)) },
28401
- void 0,
28402
- void 0,
28403
- widenedArrayConf()
28404
- );
28405
- }
28406
- return abs({ k: "tuple", elements: els }, void 0, void 0, "exact");
28407
- }
28408
- if (t === "object") {
28409
- const proto = Object.getPrototypeOf(v2);
28410
- if (proto === Object.prototype || proto === null) {
28411
- const slots = {};
28412
- for (const [k, val] of Object.entries(v2)) {
28413
- Object.defineProperty(slots, k, {
28414
- value: { value: litAbsFromJs(val, depth + 1) },
28415
- enumerable: true,
28416
- writable: true,
28417
- configurable: true
28418
- });
28419
- }
28420
- return objOf(slots);
28421
- }
28422
- }
28423
- }
28424
- return unknown;
28425
- }
28426
- function litTruth(a) {
28427
- if (a.term?.op === "lit") {
28428
- return Boolean(a.term.value);
28429
- }
28430
- switch (a.shape.k) {
28431
- case "obj":
28432
- case "arr":
28433
- case "tuple":
28434
- case "fn":
28435
- case "brand":
28436
- case "eff":
28437
- return true;
28438
- case "prim":
28439
- return a.shape.type === "symbol" ? true : void 0;
28440
- case "never":
28441
- return false;
28442
- default:
28443
- return void 0;
28444
- }
28445
- }
28446
- function isDefinitelyTrue(a) {
28447
- return litTruth(a) === true;
28448
- }
28449
- function isDefinitelyFalse(a) {
28450
- const t = litTruth(a);
28451
- if (t === false) return true;
28452
- if (a.shape.k === "never") return true;
28453
- return false;
28454
- }
28455
- function undef() {
28456
- return abs({ k: "unknown" }, { op: "lit", value: void 0 }, pTrue, "exact");
28457
- }
28458
- function runWithLoopExits(body) {
28459
- return loopExitsAls.run(
28460
- [],
28461
- () => throwExitsAls.run(
28462
- [],
28463
- () => tryMarksAls.run([], () => softFrameActiveAls.run([], body))
28464
- )
28465
- );
28466
- }
28467
- function takeLoopExits() {
28468
- return loopExitsAls.getStore() ?? [];
28469
- }
28470
- function takeThrowExits() {
28471
- return throwExitsAls.getStore() ?? [];
28472
- }
28473
- function pushLoopExit(v2) {
28474
- loopExitsAls.getStore()?.push(v2);
28475
- }
28476
- function pushThrowExit(v2) {
28477
- throwExitsAls.getStore()?.push(v2);
28478
- }
28479
- function $pushLoopExit(v2) {
28480
- pushLoopExit(v2);
28481
- }
28482
- function $tryMark() {
28483
- $tryMarkSoft();
28484
- softFrameActiveAls.getStore()?.push(true);
28485
- const store = throwExitsAls.getStore();
28486
- const m = store?.length ?? 0;
28487
- tryMarksAls.getStore()?.push(m);
28488
- return m;
28489
- }
28490
- function $tryCurrentMark() {
28491
- const stack = tryMarksAls.getStore();
28492
- return stack && stack.length > 0 ? stack[stack.length - 1] : 0;
28493
- }
28494
- function $tryPopMark() {
28495
- tryMarksAls.getStore()?.pop();
28496
- const soft = softFrameActiveAls.getStore();
28497
- if (soft && soft.length > 0) {
28498
- if (soft[soft.length - 1]) $tryReleaseSoftOut();
28499
- soft.pop();
28500
- }
28501
- }
28502
- function $tryTakeSince(mark) {
28503
- const store = throwExitsAls.getStore();
28504
- if (!store) return [];
28505
- return store.splice(Math.min(mark, store.length));
28506
- }
28507
- function peekThrowExitsSince(mark) {
28508
- const store = throwExitsAls.getStore();
28509
- if (!store) return [];
28510
- return store.slice(Math.min(mark, store.length));
28511
- }
28512
- function throwExitsMark() {
28513
- return throwExitsAls.getStore()?.length ?? 0;
28514
- }
28515
- function $tryDigestSoftCatch() {
28516
- const soft = softFrameActiveAls.getStore();
28517
- if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
28518
- $tryDigestSoft();
28519
- soft[soft.length - 1] = false;
28520
- }
28521
- function $tryReleaseSoftCatch() {
28522
- const soft = softFrameActiveAls.getStore();
28523
- if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
28524
- $tryReleaseSoft();
28525
- soft[soft.length - 1] = false;
28526
- }
28527
- function $tryDetachSoftCatch() {
28528
- const soft = softFrameActiveAls.getStore();
28529
- if (!soft || soft.length === 0 || !soft[soft.length - 1]) return [];
28530
- const effects = popMayThrowFrame(false);
28531
- soft[soft.length - 1] = false;
28532
- return effects;
28533
- }
28534
- function $tryDiscardSoft(_effects) {
28535
- }
28536
- function $tryOrphanSoft(effects) {
28537
- orphanMayThrowEffects(effects);
28538
- }
28539
- function $tryReleaseSoftOut() {
28540
- const soft = softFrameActiveAls.getStore();
28541
- if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
28542
- $tryReleaseSoft();
28543
- soft[soft.length - 1] = false;
28544
- }
28545
- function isNudoReturn(e) {
28546
- return e instanceof NudoReturn;
28547
- }
28548
- function $loopReturn(v2) {
28549
- throw new NudoReturn(v2);
28550
- }
28551
- function $loopBreak(label) {
28552
- throw new NudoLoopSignal("break", label || void 0);
28553
- }
28554
- function $loopContinue(label) {
28555
- throw new NudoLoopSignal("continue", label || void 0);
28556
- }
28557
- function loopSignalMatches(e, label) {
28558
- return e.label === void 0 || e.label === label;
28559
- }
28560
- function isNudoBreak(e, label) {
28561
- return e instanceof NudoLoopSignal && e.kind === "break" && loopSignalMatches(e, label);
28562
- }
28563
- function isNudoContinue(e, label) {
28564
- return e instanceof NudoLoopSignal && e.kind === "continue" && loopSignalMatches(e, label);
28565
- }
28566
- function $isBreakTo(e, label) {
28567
- return e instanceof NudoLoopSignal && e.kind === "break" && e.label === label;
28568
- }
28569
- function $rethrowIfNudoReturn(e) {
28570
- if (isNudoReturn(e)) throw e;
28571
- }
28572
- var phi, noBody2, loopExitsAls, throwExitsAls, tryMarksAls, softFrameActiveAls, NudoReturn, NudoLoopSignal;
28573
- var init_state = __esm({
28574
- "../core/src/algebra/exec/runtime/state.ts"() {
28575
- "use strict";
28576
- init_abs();
28577
- init_pred();
28578
- init_abs_fn();
28579
- init_nudo_throw();
28580
- init_may_throw();
28581
- init_containers();
28582
- init_objects();
28583
- phi = pTrue;
28584
- noBody2 = { type: "BlockStatement", body: [], directives: [] };
28585
- loopExitsAls = new AsyncLocalStorage2();
28586
- throwExitsAls = new AsyncLocalStorage2();
28587
- tryMarksAls = new AsyncLocalStorage2();
28588
- softFrameActiveAls = new AsyncLocalStorage2();
28589
- NudoReturn = class extends Error {
28590
- absValue;
28591
- constructor(absValue) {
28592
- super("nudo:return");
28593
- this.name = "NudoReturn";
28594
- this.absValue = absValue;
28595
- }
28596
- };
28597
- NudoLoopSignal = class extends Error {
28598
- kind;
28599
- label;
28600
- constructor(kind, label) {
28601
- super("nudo:loop");
28602
- this.name = "NudoLoopSignal";
28603
- this.kind = kind;
28604
- this.label = label;
28605
- }
28606
- };
28607
- }
28608
- });
28609
-
28610
28816
  // ../core/src/algebra/exec/runtime/ops.ts
28611
28817
  function $unknown() {
28612
28818
  return abs({ k: "unknown" }, void 0, void 0, "opaque");
@@ -29173,7 +29379,7 @@ function $instanceofNonIdent(_left) {
29173
29379
  }
29174
29380
  function $classExpr() {
29175
29381
  return absFunction(["_rest"], {
29176
- body: noBody2,
29382
+ body: noBody,
29177
29383
  apply: () => unknown
29178
29384
  });
29179
29385
  }
@@ -30100,7 +30306,7 @@ function $get(o, key, opts) {
30100
30306
  const raw = o[key];
30101
30307
  if (typeof raw === "function") {
30102
30308
  return absFunction([`${ns}.${key}`], {
30103
- body: noBody2,
30309
+ body: noBody,
30104
30310
  apply: (args) => evalNamespaceCall(ns, key, args) ?? unknown
30105
30311
  });
30106
30312
  }
@@ -30119,7 +30325,7 @@ function $get(o, key, opts) {
30119
30325
  }
30120
30326
  if (o.shape.k === "eff" && o.shape.eff === "promise" && (key === "then" || key === "catch" || key === "finally")) {
30121
30327
  return absFunction([key === "then" ? "onFulfilled" : key === "catch" ? "onRejected" : "onFinally"], {
30122
- body: noBody2
30328
+ body: noBody
30123
30329
  });
30124
30330
  }
30125
30331
  if (o.shape.k === "brand") {
@@ -30130,7 +30336,7 @@ function $get(o, key, opts) {
30130
30336
  const isClassVal = classNameOfValue(o) === o.shape.name;
30131
30337
  const builtinM = BUILTIN_BRAND_METHODS[o.shape.name];
30132
30338
  if (builtinM && !isClassVal && (key === "@@iterator" || builtinM.has(key))) {
30133
- return absFunction([], { body: noBody2 });
30339
+ return absFunction([], { body: noBody });
30134
30340
  }
30135
30341
  if (key === "size" && o.shape.name === "Map") return mapSizeAbs(o);
30136
30342
  if (key === "size" && o.shape.name === "Set") return setSizeAbs(o);
@@ -30146,14 +30352,14 @@ function $get(o, key, opts) {
30146
30352
  for (const n of evalClassChain(o.shape.name)) {
30147
30353
  const spec = getEvalClass(n);
30148
30354
  if (spec?.staticMethods?.[key]) {
30149
- return absFunction(spec.staticMethodParams?.[key] ?? [], { body: noBody2 });
30355
+ return absFunction(spec.staticMethodParams?.[key] ?? [], { body: noBody });
30150
30356
  }
30151
30357
  }
30152
30358
  if (key === "prototype") {
30153
30359
  return abs({ k: "obj", slots: {} }, void 0, void 0, "path");
30154
30360
  }
30155
30361
  if (key === "call" || key === "apply" || key === "bind") {
30156
- return absFunction([], { body: noBody2 });
30362
+ return absFunction([], { body: noBody });
30157
30363
  }
30158
30364
  } else {
30159
30365
  const acc = findClassAccessor(o.shape.name, key);
@@ -30162,7 +30368,7 @@ function $get(o, key, opts) {
30162
30368
  for (const n of evalClassChain(o.shape.name)) {
30163
30369
  const spec = getEvalClass(n);
30164
30370
  if (spec?.methods?.[key]) {
30165
- return absFunction(spec.methodParams?.[key] ?? [], { body: noBody2 });
30371
+ return absFunction(spec.methodParams?.[key] ?? [], { body: noBody });
30166
30372
  }
30167
30373
  }
30168
30374
  }
@@ -36268,60 +36474,92 @@ function isBoundedEvidenceMissing(ret, constraint) {
36268
36474
  if (ret.pred && ret.pred.op !== "true") return false;
36269
36475
  return true;
36270
36476
  }
36477
+ function flattenSumArms(ret) {
36478
+ if (ret.shape.k !== "sum") return [ret];
36479
+ const out = [];
36480
+ for (const m of ret.shape.members) {
36481
+ if (m.shape.k === "sum") out.push(...flattenSumArms(m));
36482
+ else out.push(m);
36483
+ }
36484
+ return out;
36485
+ }
36486
+ function isWidenedSumArm(m, parent) {
36487
+ return parent.conf === "partial" && m.shape.k === "prim" && !m.term && (!m.pred || m.pred.op === "true");
36488
+ }
36271
36489
  function assertImplies(ret, constraint, opts) {
36272
36490
  const phi2 = opts?.phi ?? pTrue;
36273
36491
  if (ret.shape.k === "never") return proved();
36274
36492
  if (isAnyConstraint(constraint)) return proved();
36275
- const nullishOk = constraintAdmitsNullish(constraint);
36276
- if (isNullishLitAbs(ret)) {
36277
- return nullishOk ? proved() : disproved(`nullish return \u22AD ${formatConstraint(constraint)}`);
36278
- }
36279
- let sumMembers;
36280
- if (ret.shape.k === "sum") {
36281
- const members = ret.shape.members;
36282
- const nullishMembers = members.filter((m) => isNullishLitAbs(m));
36283
- if (nullishMembers.length > 0 && !nullishOk) {
36284
- return disproved(
36285
- `nullish return arm \u22AD ${formatConstraint(constraint)} (contract does not admit nullish)`
36286
- );
36287
- }
36288
- sumMembers = members.filter((m) => !isNullishLitAbs(m));
36289
- }
36290
36493
  if (isValueSetUnknown(ret)) {
36291
36494
  return unprovable(
36292
36495
  ret.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
36293
36496
  );
36294
36497
  }
36498
+ const arms = flattenSumArms(ret);
36499
+ if (arms.length > 1) {
36500
+ return assertSumArms(arms, ret, constraint, opts, phi2);
36501
+ }
36502
+ return assertImpliesSingle(arms[0], constraint, opts, phi2);
36503
+ }
36504
+ function assertSumArms(arms, parent, constraint, opts, phi2) {
36505
+ const hasWidenedArm = arms.some(
36506
+ (a) => isValueSetUnknown(a) || isWidenedSumArm(a, parent)
36507
+ );
36508
+ let sawUnprovable = false;
36509
+ for (const arm of arms) {
36510
+ if (isNullishLitAbs(arm)) {
36511
+ if (!constraintAdmitsNullish(constraint)) {
36512
+ return disproved(
36513
+ `nullish return arm \u22AD ${formatConstraint(constraint)} (contract does not admit nullish)`
36514
+ );
36515
+ }
36516
+ continue;
36517
+ }
36518
+ if (isValueSetUnknown(arm) || isWidenedSumArm(arm, parent)) {
36519
+ sawUnprovable = true;
36520
+ continue;
36521
+ }
36522
+ const r = assertImpliesSingle(arm, constraint, opts, phi2);
36523
+ if (r.status === "disproved") {
36524
+ if (hasWidenedArm) {
36525
+ sawUnprovable = true;
36526
+ continue;
36527
+ }
36528
+ return r;
36529
+ }
36530
+ if (r.status === "unprovable") sawUnprovable = true;
36531
+ }
36532
+ return sawUnprovable ? unprovable("sum: some arms unprovable") : proved();
36533
+ }
36534
+ function assertImpliesSingle(arm, constraint, opts, phi2) {
36535
+ if (isNullishLitAbs(arm)) {
36536
+ return constraintAdmitsNullish(constraint) ? proved() : disproved(`nullish return \u22AD ${formatConstraint(constraint)}`);
36537
+ }
36538
+ if (isValueSetUnknown(arm)) {
36539
+ return unprovable(
36540
+ arm.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
36541
+ );
36542
+ }
36295
36543
  if (constraint.members && constraint.members.length > 0) {
36296
36544
  let sawUnprovable = false;
36297
36545
  for (const m of constraint.members) {
36298
- const r = assertImplies(ret, m, opts);
36546
+ const r = assertImplies(arm, m, opts);
36299
36547
  if (r.status === "proved") return proved();
36300
36548
  if (r.status === "unprovable") sawUnprovable = true;
36301
36549
  }
36302
36550
  return sawUnprovable ? unprovable("union: no member proved the return contract") : disproved(`return \u22AD union(${constraint.members.map((m) => formatConstraint(m)).join(", ")})`);
36303
36551
  }
36304
- if (sumMembers && (constraint.fields || constraint.element)) {
36305
- let sawUnprovable = false;
36306
- for (const m of sumMembers) {
36307
- if (isValueSetUnknown(m)) continue;
36308
- const r = assertImplies(m, constraint, opts);
36309
- if (r.status === "disproved") return r;
36310
- if (r.status === "unprovable") sawUnprovable = true;
36311
- }
36312
- return sawUnprovable ? unprovable("sum: some arms unprovable") : proved();
36313
- }
36314
36552
  if (constraint.fields) {
36315
- return assertShapeFields(ret, constraint, opts);
36553
+ return assertShapeFields(arm, constraint, opts);
36316
36554
  }
36317
36555
  if (constraint.element) {
36318
- if (ret.shape.k !== "arr" && ret.shape.k !== "tuple") {
36319
- return disproved(`return shape ${ret.shape.k} \u22AD array(...)`);
36556
+ if (arm.shape.k !== "arr" && arm.shape.k !== "tuple") {
36557
+ return disproved(`return shape ${arm.shape.k} \u22AD array(...)`);
36320
36558
  }
36321
36559
  return proved();
36322
36560
  }
36323
36561
  if (constraint.fn) return proved();
36324
- return assertScalar(ret, constraint, phi2);
36562
+ return assertScalar(arm, constraint, phi2);
36325
36563
  }
36326
36564
  function isAnyConstraint(c) {
36327
36565
  return !c.prim && c.preds.length === 0 && !c.fields && !c.element && !c.members && !c.fn && !isIntFlag(c);
@@ -39360,7 +39598,7 @@ function checkSourceInner(filePath, source, file, phi2, opts, issues, signatures
39360
39598
  message: `${name} (export): may throw ${gateDisplay}`,
39361
39599
  actual: `${name}(\u2026) throws ${gateDisplay}`,
39362
39600
  expected: "entry total, or @nudo:throws / try-catch",
39363
- 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`,
39601
+ 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`,
39364
39602
  fn: name,
39365
39603
  ...loc.line !== void 0 ? { line: loc.line } : {},
39366
39604
  ...loc.column !== void 0 ? { column: loc.column } : {}
@@ -39405,7 +39643,7 @@ function checkSourceInner(filePath, source, file, phi2, opts, issues, signatures
39405
39643
  message: `${name} (export): may throw ${gateDisplay}`,
39406
39644
  actual: `${formatEntrySigLine(name, g, gateDisplay)}`,
39407
39645
  expected: "entry total, or @nudo:throws / try-catch",
39408
- 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`,
39646
+ 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`,
39409
39647
  fn: name,
39410
39648
  ...loc.line !== void 0 ? { line: loc.line } : {},
39411
39649
  ...loc.column !== void 0 ? { column: loc.column } : {}
@@ -39805,6 +40043,19 @@ function actionsForIssue(i) {
39805
40043
  label: "migration switch: ignore this throw class on L2"
39806
40044
  }
39807
40045
  ];
40046
+ case "nudo:unproven-return":
40047
+ return [
40048
+ {
40049
+ kind: "relax",
40050
+ label: `relax the return contract${i.fn ? ` of ${i.fn}` : ""} to the inferred surface (review the diff \u2014 not a silent green)`,
40051
+ ...i.expected ? { hint: i.expected } : {}
40052
+ },
40053
+ draft,
40054
+ {
40055
+ kind: "info",
40056
+ label: "or narrow the return expression / add a precondition so the bound is implied"
40057
+ }
40058
+ ];
39808
40059
  case "nudo:unknown-inference":
39809
40060
  case "nudo:opaque-result":
39810
40061
  return [
@@ -277240,14 +277491,20 @@ __export(emit_exports, {
277240
277491
  absToStandardSchemaModule: () => absToStandardSchemaModule,
277241
277492
  absToTSType: () => absToTSType,
277242
277493
  absToZodSchemaModule: () => absToZodSchemaModule,
277494
+ addBudgetAnnotation: () => addBudgetAnnotation,
277495
+ addThrowsAnnotation: () => addThrowsAnnotation,
277496
+ applyTextEdits: () => applyTextEdits,
277497
+ bodyReadFieldsFor: () => bodyReadFieldsFor,
277243
277498
  buildCaseDirective: () => buildCaseDirective,
277244
277499
  collectParamBodyAccesses: () => collectParamBodyAccesses,
277500
+ collectParamBodyReadTypes: () => collectParamBodyReadTypes,
277245
277501
  constraintToSchemaNode: () => constraintToSchemaNode,
277246
277502
  deriveFromRoot: () => deriveFromRoot,
277247
277503
  draftInterface: () => draftInterface,
277248
277504
  emitDerivedFromRoot: () => emitDerivedFromRoot,
277249
277505
  emitInterface: () => emitInterface,
277250
277506
  extractFnConstraintSources: () => extractFnConstraintSources,
277507
+ findFnDeclStart: () => findFnDeclStart,
277251
277508
  formatDerivedSection: () => formatDerivedSection,
277252
277509
  formatDraftModule: () => formatDraftModule,
277253
277510
  formatDraftSummary: () => formatDraftSummary,
@@ -277261,15 +277518,19 @@ __export(emit_exports, {
277261
277518
  insertGeneratedCaseDirectives: () => insertGeneratedCaseDirectives,
277262
277519
  interfaceSurface: () => interfaceSurface,
277263
277520
  isDraftableEntry: () => isDraftableEntry,
277521
+ materializeAction: () => materializeAction,
277264
277522
  projectAbsToSchema: () => projectAbsToSchema,
277265
277523
  schemaNodeToZod: () => schemaNodeToZod,
277266
277524
  serializeCaseArg: () => serializeCaseArg,
277267
277525
  serializeCaseJson: () => serializeCaseJson,
277526
+ shapeDslFromFields: () => shapeDslFromFields,
277268
277527
  sidecarDraftPath: () => sidecarDraftPath,
277269
277528
  stripGeneratedCaseDirectives: () => stripGeneratedCaseDirectives,
277529
+ titleKindFor: () => titleKindFor,
277270
277530
  typeExprToDirective: () => typeExprToDirective2,
277271
277531
  unifiedDiff: () => unifiedDiff,
277272
277532
  validateSchemaNode: () => validateSchemaNode,
277533
+ wrapReturnNullable: () => wrapReturnNullable,
277273
277534
  writeInterfaceDraft: () => writeInterfaceDraft
277274
277535
  });
277275
277536
  import { readFileSync as readFileSync19, existsSync as existsSync18 } from "fs";
@@ -278123,6 +278384,302 @@ function joinSections(base, sectionTexts) {
278123
278384
  `;
278124
278385
  return lead + normalized.join("\n");
278125
278386
  }
278387
+ function keyOf(node) {
278388
+ if (!node) return void 0;
278389
+ if (node.type === "Identifier") return node.name;
278390
+ if (node.type === "StringLiteral") return node.value;
278391
+ return void 0;
278392
+ }
278393
+ function litKind(node) {
278394
+ if (!node) return void 0;
278395
+ if (node.type === "StringLiteral") return "string";
278396
+ if (node.type === "NumericLiteral") return "number";
278397
+ if (node.type === "BooleanLiteral") return "boolean";
278398
+ return void 0;
278399
+ }
278400
+ function hintFromUse(parent, key) {
278401
+ if (!parent) return void 0;
278402
+ const t = parent.type;
278403
+ if (t === "BinaryExpression") {
278404
+ const op = parent.operator;
278405
+ const other = key === "left" ? parent.right : parent.left;
278406
+ const lk = litKind(other);
278407
+ if (op === "===" || op === "==" || op === "!==" || op === "!=") {
278408
+ if (lk === "string") return { type: "string()", via: "compare string lit" };
278409
+ if (lk === "number") return { type: "number()", via: "compare number lit" };
278410
+ if (lk === "boolean") return { type: "boolean()", via: "compare boolean lit" };
278411
+ }
278412
+ if (op === "+") {
278413
+ if (lk === "number") return { type: "number()", via: "add number" };
278414
+ if (lk === "string") return { type: "string()", via: "concat string" };
278415
+ return { type: "any()", via: "add (unknown coerce)" };
278416
+ }
278417
+ if (op === "-" || op === "*" || op === "/" || op === "%" || op === "**") {
278418
+ return { type: "number()", via: `arith ${op}` };
278419
+ }
278420
+ if (op === "<" || op === ">" || op === "<=" || op === ">=") {
278421
+ return { type: "number()", via: `rel ${op}` };
278422
+ }
278423
+ return void 0;
278424
+ }
278425
+ if (t === "UnaryExpression" && parent.operator === "!") {
278426
+ return { type: "boolean()", via: "truthiness" };
278427
+ }
278428
+ if (t === "MemberExpression" || t === "OptionalMemberExpression") {
278429
+ const prop = keyOf(parent.property);
278430
+ if (prop && STRING_METHODS2.has(prop) && prop !== "includes" && prop !== "indexOf" && prop !== "slice" && prop !== "concat" && prop !== "at") {
278431
+ return { type: "string()", via: `.${prop}()` };
278432
+ }
278433
+ if (prop && NUMBER_METHODS.has(prop)) {
278434
+ return { type: "number()", via: `.${prop}()` };
278435
+ }
278436
+ if (prop === "length") {
278437
+ return { type: "union(string(), array(any()))", via: ".length" };
278438
+ }
278439
+ if (prop === "size") {
278440
+ return { type: "any()", via: ".size (Set/Map)" };
278441
+ }
278442
+ if (prop && ARRAY_METHODS.has(prop)) {
278443
+ return { type: "array(any())", via: `.${prop}()` };
278444
+ }
278445
+ return void 0;
278446
+ }
278447
+ if (t === "CallExpression" || t === "OptionalCallExpression") {
278448
+ const callee = parent.callee;
278449
+ const cname = callee?.type === "Identifier" ? callee.name : void 0;
278450
+ if (cname === "String") return { type: "string()", via: "String()" };
278451
+ if (cname === "Number") return { type: "number()", via: "Number()" };
278452
+ if (cname === "Boolean") return { type: "boolean()", via: "Boolean()" };
278453
+ if (callee?.type === "MemberExpression" && callee.object?.type === "Identifier" && callee.object.name === "Array" && callee.property?.type === "Identifier" && callee.property.name === "isArray") {
278454
+ return { type: "array(any())", via: "Array.isArray" };
278455
+ }
278456
+ return void 0;
278457
+ }
278458
+ if (t === "UnaryExpression" && parent.operator === "typeof") {
278459
+ return void 0;
278460
+ }
278461
+ return void 0;
278462
+ }
278463
+ function hintFromTypeof(typeofNode, cmp2) {
278464
+ if (!typeofNode || !cmp2) return void 0;
278465
+ if (typeofNode.type !== "UnaryExpression" || typeofNode.operator !== "typeof") return void 0;
278466
+ if (cmp2.type !== "BinaryExpression") return void 0;
278467
+ const op = cmp2.operator;
278468
+ if (op !== "===" && op !== "==" && op !== "!==" && op !== "!=") return void 0;
278469
+ const other = cmp2.left === typeofNode ? cmp2.right : cmp2.left;
278470
+ const lk = litKind(other);
278471
+ if (lk !== "string") return void 0;
278472
+ const name = other?.value;
278473
+ const map = {
278474
+ string: "string()",
278475
+ number: "number()",
278476
+ boolean: "boolean()",
278477
+ object: "any()",
278478
+ function: "any()",
278479
+ undefined: "any()",
278480
+ bigint: "any()",
278481
+ symbol: "any()"
278482
+ };
278483
+ const type = name ? map[name] : void 0;
278484
+ if (!type) return void 0;
278485
+ return { type, via: `typeof === "${name}"` };
278486
+ }
278487
+ function collectParamBodyReadTypes(source) {
278488
+ const out = /* @__PURE__ */ new Map();
278489
+ let ast;
278490
+ try {
278491
+ ast = parse2(source);
278492
+ } catch {
278493
+ return out;
278494
+ }
278495
+ const visitFn = (fnName, fnNode, paramNames) => {
278496
+ if (paramNames.size === 0) return;
278497
+ const byParam = /* @__PURE__ */ new Map();
278498
+ const add2 = (pname, field, hint) => {
278499
+ if (!byParam.has(pname)) byParam.set(pname, /* @__PURE__ */ new Map());
278500
+ const fields = byParam.get(pname);
278501
+ if (!fields.has(field)) fields.set(field, []);
278502
+ if (hint) fields.get(field).push(hint);
278503
+ };
278504
+ const walk = (node, shadowed, parent, parentKey) => {
278505
+ if (!node || typeof node !== "object") return;
278506
+ const n = node;
278507
+ if ((n.type === "VariableDeclarator" || n.type === "FunctionDeclaration") && n.id?.type === "Identifier") {
278508
+ const id = n.id.name;
278509
+ if (paramNames.has(id)) shadowed = new Set(shadowed).add(id);
278510
+ }
278511
+ if (n.type === "UnaryExpression" && n.operator === "typeof") {
278512
+ const arg = n.argument;
278513
+ const mem = arg;
278514
+ if (mem && (mem.type === "MemberExpression" || mem.type === "OptionalMemberExpression")) {
278515
+ const obj2 = mem.object;
278516
+ const prop = mem.property;
278517
+ if (obj2?.type === "Identifier" && paramNames.has(obj2.name) && !shadowed.has(obj2.name) && prop && mem.computed !== true) {
278518
+ const key = keyOf(prop);
278519
+ const pname = obj2.name;
278520
+ if (key !== void 0) {
278521
+ const gp = parent;
278522
+ add2(pname, key, hintFromTypeof(n, gp));
278523
+ }
278524
+ }
278525
+ }
278526
+ }
278527
+ if (n.type === "MemberExpression" || n.type === "OptionalMemberExpression") {
278528
+ const obj2 = n.object;
278529
+ const prop = n.property;
278530
+ const computed = n.computed === true;
278531
+ if (obj2?.type === "Identifier" && paramNames.has(obj2.name) && !shadowed.has(obj2.name) && prop && !computed) {
278532
+ const key = keyOf(prop);
278533
+ const pname = obj2.name;
278534
+ if (key !== void 0) {
278535
+ const hint = hintFromUse(parent, parentKey ?? "object");
278536
+ add2(pname, key, hint);
278537
+ }
278538
+ }
278539
+ }
278540
+ for (const k of Object.keys(n)) {
278541
+ if (k === "loc" || k === "start" || k === "end") continue;
278542
+ const child = n[k];
278543
+ if (Array.isArray(child)) {
278544
+ for (const item of child) walk(item, shadowed, n, k);
278545
+ } else if (child && typeof child === "object") {
278546
+ walk(child, shadowed, n, k);
278547
+ }
278548
+ }
278549
+ };
278550
+ walk(fnNode, /* @__PURE__ */ new Set());
278551
+ if (byParam.size === 0) return;
278552
+ const fieldsOf = /* @__PURE__ */ new Map();
278553
+ for (const [pname, fieldMap] of byParam) {
278554
+ const list = [];
278555
+ for (const [field, hints] of fieldMap) {
278556
+ list.push({ field, ...mergeHints(hints) });
278557
+ }
278558
+ list.sort((a, b) => a.field < b.field ? -1 : 1);
278559
+ fieldsOf.set(pname, list);
278560
+ }
278561
+ out.set(fnName, fieldsOf);
278562
+ };
278563
+ const paramSet = (fnNode) => {
278564
+ const names2 = /* @__PURE__ */ new Set();
278565
+ const params = fnNode.params ?? [];
278566
+ for (const p of params) {
278567
+ if (!p) continue;
278568
+ if (p.type === "Identifier") names2.add(p.name);
278569
+ else if (p.type === "AssignmentPattern" && p.left?.type === "Identifier") {
278570
+ names2.add(p.left.name);
278571
+ } else if (p.type === "RestElement" && p.argument?.type === "Identifier") {
278572
+ names2.add(p.argument.name);
278573
+ } else if (p.type === "ObjectPattern") {
278574
+ for (const prop of p.properties ?? []) {
278575
+ if (prop.type === "ObjectProperty") {
278576
+ const v2 = prop.value;
278577
+ if (v2.type === "Identifier") names2.add(v2.name);
278578
+ else if (v2.type === "AssignmentPattern" && v2.left?.type === "Identifier") {
278579
+ names2.add(v2.left.name);
278580
+ }
278581
+ }
278582
+ }
278583
+ }
278584
+ }
278585
+ return names2;
278586
+ };
278587
+ const visitClassMethods = (className, classNode) => {
278588
+ const body = classNode.body?.body ?? [];
278589
+ for (const m of body) {
278590
+ const mem = m;
278591
+ const isMethod3 = mem.type === "MethodDefinition" || mem.type === "ClassMethod" || mem.type === "TSDeclareMethod";
278592
+ if (!isMethod3 || mem.static) continue;
278593
+ if (mem.kind && mem.kind !== "method") continue;
278594
+ const keyName = mem.key?.type === "Identifier" ? mem.key.name : void 0;
278595
+ if (!keyName) continue;
278596
+ const methodNode = mem.type === "MethodDefinition" ? mem.value : mem;
278597
+ if (!methodNode) continue;
278598
+ visitFn(`${className}.${keyName}`, methodNode, paramSet(methodNode));
278599
+ }
278600
+ };
278601
+ const considerDecl = (decl, exported) => {
278602
+ if (!decl) return;
278603
+ if (decl.type === "FunctionDeclaration" && decl.id) {
278604
+ const id = decl.id;
278605
+ visitFn(id.name, decl, paramSet(decl));
278606
+ return;
278607
+ }
278608
+ if (decl.type === "ClassDeclaration" && decl.id?.name) {
278609
+ visitClassMethods(decl.id.name, decl);
278610
+ return;
278611
+ }
278612
+ if (decl.type === "VariableDeclaration") {
278613
+ for (const d of decl.declarations ?? []) {
278614
+ const id = d.id;
278615
+ const init = d.init;
278616
+ if (exported && id?.type === "Identifier" && init && (init.type === "ArrowFunctionExpression" || init.type === "FunctionExpression")) {
278617
+ visitFn(id.name, init, paramSet(init));
278618
+ }
278619
+ }
278620
+ }
278621
+ };
278622
+ const program3 = ast.program;
278623
+ const bodyStmts = program3?.body ?? [];
278624
+ for (const stmt of bodyStmts) {
278625
+ if (stmt.type === "ExportNamedDeclaration") {
278626
+ considerDecl(stmt.declaration, true);
278627
+ } else if (stmt.type === "ExportDefaultDeclaration") {
278628
+ considerDecl(stmt.declaration, true);
278629
+ } else if (stmt.type === "ClassDeclaration") {
278630
+ const id = stmt.id;
278631
+ if (id?.name) visitClassMethods(id.name, stmt);
278632
+ } else if (stmt.type === "FunctionDeclaration") {
278633
+ considerDecl(stmt, false);
278634
+ }
278635
+ }
278636
+ return out;
278637
+ }
278638
+ function mergeHints(hints) {
278639
+ if (hints.length === 0) return { type: "any()", via: "read (no type evidence)" };
278640
+ const types2 = [...new Set(hints.map((h) => h.type))];
278641
+ if (types2.length === 1) {
278642
+ return { type: types2[0], via: hints[0].via };
278643
+ }
278644
+ const concrete = types2.filter((t) => t !== "any()");
278645
+ if (concrete.length === 0) return { type: "any()", via: hints[0].via };
278646
+ if (concrete.length === 1) {
278647
+ const h = hints.find((x) => x.type === concrete[0]);
278648
+ return { type: concrete[0], via: h.via };
278649
+ }
278650
+ const specific = concrete.filter((t) => !t.startsWith("union("));
278651
+ if (specific.length === 1) {
278652
+ const h = hints.find((x) => x.type === specific[0]);
278653
+ return { type: specific[0], via: h.via };
278654
+ }
278655
+ if (specific.length > 1) {
278656
+ return {
278657
+ type: `union(${specific.join(", ")})`,
278658
+ via: hints.filter((h) => specific.includes(h.type)).map((h) => h.via).join(" + ")
278659
+ };
278660
+ }
278661
+ const flat = /* @__PURE__ */ new Set();
278662
+ for (const t of concrete) {
278663
+ if (t.startsWith("union(") && t.endsWith(")")) {
278664
+ for (const part of t.slice(6, -1).split(",")) flat.add(part.trim());
278665
+ } else {
278666
+ flat.add(t);
278667
+ }
278668
+ }
278669
+ const parts = [...flat];
278670
+ return {
278671
+ type: parts.length === 1 ? parts[0] : `union(${parts.join(", ")})`,
278672
+ via: hints.map((h) => h.via).join(" + ")
278673
+ };
278674
+ }
278675
+ function bodyReadFieldsFor(map, fnName, paramName2) {
278676
+ return map.get(fnName)?.get(paramName2);
278677
+ }
278678
+ function shapeDslFromFields(fields) {
278679
+ if (fields.length === 0) return "shape({})";
278680
+ const parts = fields.map((f) => `${f.field}: ${f.type}`);
278681
+ return `shape({ ${parts.join(", ")} })`;
278682
+ }
278126
278683
  function collectParamBodyAccesses(source) {
278127
278684
  const out = /* @__PURE__ */ new Map();
278128
278685
  let ast;
@@ -278131,7 +278688,7 @@ function collectParamBodyAccesses(source) {
278131
278688
  } catch {
278132
278689
  return out;
278133
278690
  }
278134
- const keyOf = (node) => {
278691
+ const keyOf2 = (node) => {
278135
278692
  if (node.type === "Identifier") return node.name;
278136
278693
  if (node.type === "StringLiteral") return node.value;
278137
278694
  return void 0;
@@ -278153,7 +278710,7 @@ function collectParamBodyAccesses(source) {
278153
278710
  const prop = n.property;
278154
278711
  const computed = n.computed === true;
278155
278712
  if (obj2?.type === "Identifier" && paramNames.has(obj2.name) && !shadowed.has(obj2.name) && prop && !computed) {
278156
- const key = keyOf(prop);
278713
+ const key = keyOf2(prop);
278157
278714
  const pname = obj2.name;
278158
278715
  if (key !== void 0) {
278159
278716
  if (!byParam.has(pname)) byParam.set(pname, /* @__PURE__ */ new Set());
@@ -278332,7 +278889,7 @@ function litPrimOf(c) {
278332
278889
  if (typeof v2 === "boolean") return "boolean";
278333
278890
  return c.members?.[0] ? litPrimOf(c.members[0]) : void 0;
278334
278891
  }
278335
- function projectDraftParams(fn2, paramCases, bodyByParam, formals) {
278892
+ function projectDraftParams(fn2, paramCases, bodyByParam, formals, bodyReadByParam) {
278336
278893
  const bodyFor = (name, index2) => {
278337
278894
  if (!bodyByParam) return void 0;
278338
278895
  const hit = bodyByParam.get(name);
@@ -278346,8 +278903,23 @@ function projectDraftParams(fn2, paramCases, bodyByParam, formals) {
278346
278903
  }
278347
278904
  return bodyByParam.get(`_p${index2}`);
278348
278905
  };
278906
+ const fieldsFor = (name, index2) => {
278907
+ if (!bodyReadByParam) return void 0;
278908
+ const hit = bodyReadByParam.get(name);
278909
+ if (hit && hit.length > 0) return hit;
278910
+ const formal = formals?.[index2];
278911
+ if (formal && formal.kind === "pattern") {
278912
+ for (const b of formal.bound) {
278913
+ const boundHit = bodyReadByParam.get(b);
278914
+ if (boundHit && boundHit.length > 0) return boundHit;
278915
+ }
278916
+ }
278917
+ return bodyReadByParam.get(`_p${index2}`);
278918
+ };
278349
278919
  return fn2.paramNames.map((name, i) => {
278350
278920
  const bodyAccesses = bodyFor(name, i) ? [...bodyFor(name, i)].sort() : void 0;
278921
+ const bodyReadFields = fieldsFor(name, i);
278922
+ const bodyExtra = bodyReadFields ? { bodyAccesses: bodyReadFields.map((f) => f.field), bodyReadFields } : bodyAccesses ? { bodyAccesses } : {};
278351
278923
  const argAbs = [];
278352
278924
  for (const c of paramCases) {
278353
278925
  const a = c.argAbs[i];
@@ -278355,11 +278927,12 @@ function projectDraftParams(fn2, paramCases, bodyByParam, formals) {
278355
278927
  }
278356
278928
  if (argAbs.length === 0) {
278357
278929
  if (bodyAccesses && bodyAccesses.length > 0) {
278930
+ const shapeText = bodyReadFields ? shapeDslFromFields(bodyReadFields) : `shape({ ${bodyAccesses.map((k) => `${k}: any()`).join(", ")} })`;
278358
278931
  return {
278359
278932
  name,
278360
- display: `/* body-read { ${bodyAccesses.join(", ")} } \u2014 fill types when accepting */`,
278933
+ display: `/* body-read ${shapeText} */`,
278361
278934
  projected: false,
278362
- bodyAccesses
278935
+ ...bodyExtra
278363
278936
  };
278364
278937
  }
278365
278938
  return { name, display: "/* no evidence \u2014 tighten */", projected: false };
@@ -278370,7 +278943,7 @@ function projectDraftParams(fn2, paramCases, bodyByParam, formals) {
278370
278943
  name,
278371
278944
  display: `/* not projectable: ${argAbs.map((a) => formatShape(a)).join(" | ")} */`,
278372
278945
  projected: false,
278373
- ...bodyAccesses ? { bodyAccesses } : {}
278946
+ ...bodyExtra
278374
278947
  };
278375
278948
  }
278376
278949
  const constraint = widenDraftConstraint(raw);
@@ -278380,7 +278953,7 @@ function projectDraftParams(fn2, paramCases, bodyByParam, formals) {
278380
278953
  name,
278381
278954
  display: `/* observed: ${observed2} \u2014 widen/confirm before accepting */`,
278382
278955
  projected: false,
278383
- ...bodyAccesses ? { bodyAccesses } : {}
278956
+ ...bodyExtra
278384
278957
  };
278385
278958
  }
278386
278959
  let display = formatConstraint(constraint);
@@ -278388,7 +278961,9 @@ function projectDraftParams(fn2, paramCases, bodyByParam, formals) {
278388
278961
  if (observed !== display) {
278389
278962
  display += ` /* observed: ${observed} */`;
278390
278963
  }
278391
- if (bodyAccesses && bodyAccesses.length > 0) {
278964
+ if (bodyReadFields && bodyReadFields.length > 0) {
278965
+ display += ` /* body also reads: ${shapeDslFromFields(bodyReadFields)} */`;
278966
+ } else if (bodyAccesses && bodyAccesses.length > 0) {
278392
278967
  display += ` /* body also reads: ${bodyAccesses.join(", ")} */`;
278393
278968
  }
278394
278969
  return {
@@ -278396,7 +278971,7 @@ function projectDraftParams(fn2, paramCases, bodyByParam, formals) {
278396
278971
  constraint,
278397
278972
  display,
278398
278973
  projected: true,
278399
- ...bodyAccesses ? { bodyAccesses } : {}
278974
+ ...bodyExtra
278400
278975
  };
278401
278976
  });
278402
278977
  }
@@ -278483,8 +279058,8 @@ function suggestedBodyDsl(fnName, params) {
278483
279058
  const withBody = params.filter((p) => p.bodyAccesses && p.bodyAccesses.length > 0 && !p.projected);
278484
279059
  if (withBody.length === 0) return void 0;
278485
279060
  const parts = withBody.map((p) => {
278486
- const fields = p.bodyAccesses.map((k) => `${k}: /* TODO */`).join(", ");
278487
- return `${p.name}: shape({ ${fields} })`;
279061
+ const shapeText = p.bodyReadFields ? shapeDslFromFields(p.bodyReadFields) : `shape({ ${p.bodyAccesses.map((k) => `${k}: any()`).join(", ")} })`;
279062
+ return `${p.name}: ${shapeText}`;
278488
279063
  });
278489
279064
  return `// suggested (body-read, not a contract): ${sanitizeCommentText(
278490
279065
  `${fnName} = fn({ ${parts.join(", ")} })`
@@ -278499,6 +279074,7 @@ async function draftInterface(filePath, opts = {}) {
278499
279074
  const exported = localNamedExports(source);
278500
279075
  const selected = opts.fnNames && opts.fnNames.length > 0 ? new Set(opts.fnNames) : exported;
278501
279076
  const bodyMap = wantBody ? collectParamBodyAccesses(source) : /* @__PURE__ */ new Map();
279077
+ const bodyReadTypes = wantBody ? collectParamBodyReadTypes(source) : /* @__PURE__ */ new Map();
278502
279078
  const entries = [];
278503
279079
  for (const fn2 of analysis.functions) {
278504
279080
  if (!selected.has(fn2.name) && !opts.fnNames?.includes(fn2.name)) continue;
@@ -278547,7 +279123,8 @@ async function draftInterface(filePath, opts = {}) {
278547
279123
  }
278548
279124
  const { paramCases, returnCases, paramEvidence, rawReturnEvidence } = caseEvidence(fn2);
278549
279125
  const bodyByParam = bodyMap.get(fn2.name);
278550
- const params = projectDraftParams(fn2, paramCases, bodyByParam, fn2.formals);
279126
+ const bodyReadByParam = bodyReadTypes.get(fn2.name);
279127
+ const params = projectDraftParams(fn2, paramCases, bodyByParam, fn2.formals, bodyReadByParam);
278551
279128
  const ret = projectDraftReturn(fn2, returnCases, source, rawReturnEvidence, loadModule, filePath);
278552
279129
  const { evidence: returnEvidence, ...returns } = ret;
278553
279130
  let evidence = paramEvidence;
@@ -280780,7 +281357,287 @@ function serializeCaseJson(result, file) {
280780
281357
  if (external) json.externalFunctions = external;
280781
281358
  return json;
280782
281359
  }
280783
- var GENERATED_PREFIX, GENERATED_CASE_LINE_REGEX, IDENT_KEY_REGEX, NUMBER_LITERAL_REGEX, UNSAFE_STRING_CHARS, UNSAFE_KEY_CHARS, CONTROL_CHARS, DIFF_CONTEXT, GENERATED_HEADER, NameAllocator, DERIVED_HEADER, TS_PARAM_RESERVED, DIALECT_RENDERERS, CHECK_FN_SOURCE;
281360
+ function titlePrefix(k) {
281361
+ return `[${k}]`;
281362
+ }
281363
+ function titleKindFor(code2, action) {
281364
+ switch (action.kind) {
281365
+ case "draft":
281366
+ return "fix";
281367
+ case "relax":
281368
+ return code2 === "nudo:unproven-return" ? "review" : "silence";
281369
+ case "mock":
281370
+ case "assume":
281371
+ case "emit":
281372
+ return "scaffold";
281373
+ case "ignore-throws":
281374
+ return "silence";
281375
+ case "callsite":
281376
+ return "fix";
281377
+ default:
281378
+ return "adjust";
281379
+ }
281380
+ }
281381
+ function escapeRegExp22(s) {
281382
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
281383
+ }
281384
+ function findFnDeclStart(lines, fnName) {
281385
+ const re = new RegExp(
281386
+ `(?:export\\s+)?(?:async\\s+)?function\\s+(?<![\\w$])${escapeRegExp22(fnName)}(?![\\w$])|(?:export\\s+)?const\\s+(?<![\\w$])${escapeRegExp22(fnName)}(?![\\w$])\\s*=`
281387
+ );
281388
+ for (let i = 0; i < lines.length; i++) {
281389
+ if (re.test(lines[i])) {
281390
+ let j = i - 1;
281391
+ while (j >= 0 && (lines[j].trim() === "" || lines[j].trim().startsWith("*") || lines[j].trim().startsWith("/*") || lines[j].trim().startsWith("//"))) {
281392
+ if (lines[j].includes("/**") || lines[j].trim().startsWith("//")) return j;
281393
+ j--;
281394
+ }
281395
+ return i;
281396
+ }
281397
+ }
281398
+ return -1;
281399
+ }
281400
+ function addThrowsAnnotation(source, fnName, kind) {
281401
+ const lines = source.split("\n");
281402
+ const start = findFnDeclStart(lines, fnName);
281403
+ if (start < 0) return void 0;
281404
+ const kindSafe = kind.replace(/[^\w.$]/g, "") || "Error";
281405
+ const tag = ` * @nudo:throws ${kindSafe}`;
281406
+ for (let i = Math.max(0, start - 15); i < Math.min(lines.length, start + 3); i++) {
281407
+ if (lines[i].includes(`@nudo:throws ${kindSafe}`)) return { edits: [] };
281408
+ }
281409
+ for (let i = start; i < Math.min(lines.length, start + 30); i++) {
281410
+ const t = lines[i];
281411
+ const closeIdx = t.indexOf("*/");
281412
+ const openIdx = t.indexOf("/**");
281413
+ if (openIdx !== -1 && closeIdx > openIdx) {
281414
+ const inner = t.slice(openIdx + 3, closeIdx).trim();
281415
+ const innerLine = inner ? ` * ${inner}
281416
+ ` : "";
281417
+ return {
281418
+ edits: [
281419
+ {
281420
+ startLine: i,
281421
+ startCol: 0,
281422
+ endLine: i,
281423
+ endCol: t.length,
281424
+ newText: `/**
281425
+ ${innerLine}${tag}
281426
+ */`
281427
+ }
281428
+ ]
281429
+ };
281430
+ }
281431
+ if (closeIdx !== -1) {
281432
+ return {
281433
+ edits: [
281434
+ {
281435
+ startLine: i,
281436
+ startCol: 0,
281437
+ endLine: i,
281438
+ endCol: 0,
281439
+ newText: `${tag}
281440
+ `
281441
+ }
281442
+ ]
281443
+ };
281444
+ }
281445
+ if (t.trim().startsWith("/**")) continue;
281446
+ if (i > start && !t.trim().startsWith("*") && !t.trim().startsWith("/*")) break;
281447
+ }
281448
+ return {
281449
+ edits: [
281450
+ {
281451
+ startLine: start,
281452
+ startCol: 0,
281453
+ endLine: start,
281454
+ endCol: 0,
281455
+ newText: `/**
281456
+ ${tag}
281457
+ */
281458
+ `
281459
+ }
281460
+ ]
281461
+ };
281462
+ }
281463
+ function wrapReturnNullable(sidecarSource, fnName) {
281464
+ const fn2 = escapeRegExp22(fnName);
281465
+ const startRe = new RegExp(
281466
+ `(?:export\\s+const\\s+${fn2}\\s*=\\s*|(?<![\\w$])${fn2}\\s*=\\s*)fn\\s*\\(`
281467
+ );
281468
+ const m = sidecarSource.match(startRe);
281469
+ if (!m || m.index === void 0) return void 0;
281470
+ const start = m.index;
281471
+ const open = start + m[0].lastIndexOf("(");
281472
+ let depth = 0;
281473
+ let end = -1;
281474
+ for (let i = open; i < sidecarSource.length; i++) {
281475
+ const ch = sidecarSource[i];
281476
+ if (ch === "(") depth++;
281477
+ else if (ch === ")") {
281478
+ depth--;
281479
+ if (depth === 0) {
281480
+ end = i;
281481
+ break;
281482
+ }
281483
+ }
281484
+ }
281485
+ if (end < 0) return void 0;
281486
+ const region = sidecarSource.slice(start, end + 1);
281487
+ let argDepth = 0;
281488
+ let comma = -1;
281489
+ for (let i = open + 1; i < end; i++) {
281490
+ const ch = sidecarSource[i];
281491
+ if (ch === "(" || ch === "{" || ch === "[") argDepth++;
281492
+ else if (ch === ")" || ch === "}" || ch === "]") argDepth--;
281493
+ else if (ch === "," && argDepth === 0) {
281494
+ comma = i;
281495
+ break;
281496
+ }
281497
+ }
281498
+ if (comma < 0) return void 0;
281499
+ let retStart = comma + 1;
281500
+ while (retStart < end && /\s/.test(sidecarSource[retStart])) retStart++;
281501
+ const retExpr = sidecarSource.slice(retStart, end).trim();
281502
+ if (!retExpr || retExpr.startsWith("nullable(") || retExpr.startsWith("union(")) {
281503
+ return void 0;
281504
+ }
281505
+ const next = sidecarSource.slice(0, retStart) + `nullable(${retExpr})` + sidecarSource.slice(end);
281506
+ return next;
281507
+ }
281508
+ function addBudgetAnnotation(source, fnName, forks = 64) {
281509
+ const lines = source.split("\n");
281510
+ const start = findFnDeclStart(lines, fnName);
281511
+ if (start < 0) return void 0;
281512
+ if (source.includes(`@nudo:budget`)) return { edits: [] };
281513
+ return {
281514
+ edits: [
281515
+ {
281516
+ startLine: start,
281517
+ startCol: 0,
281518
+ endLine: start,
281519
+ endCol: 0,
281520
+ newText: `/**
281521
+ * @nudo:budget forks=${forks}
281522
+ */
281523
+ `
281524
+ }
281525
+ ]
281526
+ };
281527
+ }
281528
+ function applyTextEdits(source, edits) {
281529
+ const lines = source.split("\n");
281530
+ const sorted = [...edits].sort(
281531
+ (a, b) => b.startLine - a.startLine || b.startCol - a.startCol
281532
+ );
281533
+ for (const e of sorted) {
281534
+ const before = lines.slice(0, e.startLine);
281535
+ const after = lines.slice(e.endLine + 1);
281536
+ const startLineText = lines[e.startLine] ?? "";
281537
+ const endLineText = lines[e.endLine] ?? startLineText;
281538
+ const merged = startLineText.slice(0, e.startCol) + e.newText + endLineText.slice(e.endCol);
281539
+ lines.splice(e.startLine, e.endLine - e.startLine + 1, merged);
281540
+ }
281541
+ return lines.join("\n");
281542
+ }
281543
+ function materializeAction(input) {
281544
+ const { code: code2, action, fn: fn2, source, sidecarText, sidecarPath } = input;
281545
+ const tk = titleKindFor(code2, action);
281546
+ if (code2 === "nudo:entry-may-throw" && action.kind === "relax" && fn2) {
281547
+ const kind = input.throwsKind ?? input.suggestion?.match(/@nudo:throws\s+(\w+)/)?.[1] ?? "Error";
281548
+ const r = addThrowsAnnotation(source, fn2, kind);
281549
+ if (!r) return void 0;
281550
+ return {
281551
+ titleKind: "silence",
281552
+ title: `${titlePrefix("silence")} Declare @nudo:throws ${kind} on ${fn2}`,
281553
+ edits: r.edits
281554
+ };
281555
+ }
281556
+ if (code2 === "nudo:entry-may-throw" && action.kind === "draft" && fn2) {
281557
+ const bodyRead = input.suggestion?.match(/body-read\s*\{([^}]+)\}/)?.[1];
281558
+ const fieldNames = bodyRead?.split(",").map((s) => s.trim()).filter(Boolean);
281559
+ const inferred = collectParamBodyReadTypes(source).get(fn2);
281560
+ let fields;
281561
+ let paramName2 = "arg";
281562
+ if (inferred) {
281563
+ for (const [pname, list] of inferred) {
281564
+ if (fieldNames && fieldNames.length > 0) {
281565
+ const hit = list.filter((f) => fieldNames.includes(f.field));
281566
+ if (hit.length > 0) {
281567
+ fields = hit;
281568
+ paramName2 = pname;
281569
+ break;
281570
+ }
281571
+ } else if (list.length > 0) {
281572
+ fields = list;
281573
+ paramName2 = pname;
281574
+ break;
281575
+ }
281576
+ }
281577
+ }
281578
+ if (!fields || fields.length === 0) {
281579
+ if (!fieldNames || fieldNames.length === 0) {
281580
+ return {
281581
+ titleKind: "fix",
281582
+ title: `${titlePrefix("fix")} Add sidecar param contract for ${fn2} (via nudo contract --draft)`,
281583
+ edits: [],
281584
+ openPath: sidecarPath
281585
+ };
281586
+ }
281587
+ fields = fieldNames.map((f) => ({ field: f, type: "any()", via: "read (no type evidence)" }));
281588
+ }
281589
+ const shapeText = shapeDslFromFields(fields);
281590
+ const clause = `export const ${fn2} = fn({ ${paramName2}: ${shapeText} });
281591
+ `;
281592
+ const next = sidecarText && sidecarText.trim().length > 0 ? sidecarText.endsWith("\n") ? sidecarText + clause : sidecarText + "\n" + clause : `// Generated by quickfix \u2014 review before accepting
281593
+ ${clause}`;
281594
+ return {
281595
+ titleKind: "fix",
281596
+ title: `${titlePrefix("fix")} Add sidecar param contract for ${fn2} (${fields.map((f) => `${f.field}: ${f.type}`).join(", ")})`,
281597
+ edits: [],
281598
+ sidecar: { path: sidecarPath, newText: next },
281599
+ openPath: sidecarPath
281600
+ };
281601
+ }
281602
+ if (code2 === "nudo:constraint-violated" && (action.kind === "relax" || action.kind === "draft") && fn2 && sidecarText && (/nullish/i.test(input.suggestion ?? "") || /nullish/i.test(input.expected ?? "") || /use nullable/i.test(input.suggestion ?? ""))) {
281603
+ const next = wrapReturnNullable(sidecarText, fn2);
281604
+ if (next && next !== sidecarText) {
281605
+ return {
281606
+ titleKind: "fix",
281607
+ title: `${titlePrefix("fix")} Wrap ${fn2} return contract in nullable(\u2026)`,
281608
+ edits: [],
281609
+ sidecar: { path: sidecarPath, newText: next }
281610
+ };
281611
+ }
281612
+ }
281613
+ if (code2 === "nudo:unproven-return" && action.kind === "relax" && fn2 && sidecarText) {
281614
+ return {
281615
+ titleKind: "review",
281616
+ title: `${titlePrefix("review")} Relax return contract for ${fn2} to inferred surface`,
281617
+ edits: [],
281618
+ openPath: sidecarPath
281619
+ };
281620
+ }
281621
+ if (code2 === "nudo:recursion-truncated" && fn2) {
281622
+ const r = addBudgetAnnotation(source, fn2);
281623
+ if (!r) return void 0;
281624
+ return {
281625
+ titleKind: "adjust",
281626
+ title: `${titlePrefix("adjust")} Add @nudo:budget forks=64 on ${fn2}`,
281627
+ edits: r.edits
281628
+ };
281629
+ }
281630
+ if ((code2 === "nudo:unknown-inference" || code2 === "nudo:opaque-result") && (action.kind === "mock" || action.kind === "draft")) {
281631
+ return {
281632
+ titleKind: "scaffold",
281633
+ title: `${titlePrefix("scaffold")} ${action.label}`,
281634
+ edits: [],
281635
+ openPath: code2 === "nudo:opaque-result" ? input.file : sidecarPath
281636
+ };
281637
+ }
281638
+ return void 0;
281639
+ }
281640
+ var GENERATED_PREFIX, GENERATED_CASE_LINE_REGEX, IDENT_KEY_REGEX, NUMBER_LITERAL_REGEX, UNSAFE_STRING_CHARS, UNSAFE_KEY_CHARS, CONTROL_CHARS, DIFF_CONTEXT, GENERATED_HEADER, STRING_METHODS2, NUMBER_METHODS, ARRAY_METHODS, NameAllocator, DERIVED_HEADER, TS_PARAM_RESERVED, DIALECT_RENDERERS, CHECK_FN_SOURCE;
280784
281641
  var init_emit2 = __esm({
280785
281642
  "../service/dist/emit/index.js"() {
280786
281643
  "use strict";
@@ -280795,6 +281652,7 @@ var init_emit2 = __esm({
280795
281652
  init_internal();
280796
281653
  init_src2();
280797
281654
  init_src2();
281655
+ init_src2();
280798
281656
  init_src();
280799
281657
  init_internal();
280800
281658
  init_src();
@@ -280817,6 +281675,66 @@ var init_emit2 = __esm({
280817
281675
  CONTROL_CHARS = /[\x00-\x1f\x7f]/;
280818
281676
  DIFF_CONTEXT = 3;
280819
281677
  GENERATED_HEADER = "// @generated by nudo \u2014 do not edit; regenerate with `nudo contract --emit`";
281678
+ STRING_METHODS2 = /* @__PURE__ */ new Set([
281679
+ "toLowerCase",
281680
+ "toUpperCase",
281681
+ "trim",
281682
+ "trimStart",
281683
+ "trimEnd",
281684
+ "slice",
281685
+ "substring",
281686
+ "substr",
281687
+ "charAt",
281688
+ "charCodeAt",
281689
+ "codePointAt",
281690
+ "includes",
281691
+ "startsWith",
281692
+ "endsWith",
281693
+ "split",
281694
+ "replace",
281695
+ "replaceAll",
281696
+ "repeat",
281697
+ "padStart",
281698
+ "padEnd",
281699
+ "normalize",
281700
+ "concat",
281701
+ "match",
281702
+ "matchAll",
281703
+ "search",
281704
+ "at",
281705
+ "indexOf",
281706
+ "lastIndexOf"
281707
+ ]);
281708
+ NUMBER_METHODS = /* @__PURE__ */ new Set([
281709
+ "toFixed",
281710
+ "toPrecision",
281711
+ "toExponential",
281712
+ "valueOf"
281713
+ ]);
281714
+ ARRAY_METHODS = /* @__PURE__ */ new Set([
281715
+ "map",
281716
+ "filter",
281717
+ "reduce",
281718
+ "forEach",
281719
+ "find",
281720
+ "findIndex",
281721
+ "some",
281722
+ "every",
281723
+ "push",
281724
+ "pop",
281725
+ "shift",
281726
+ "unshift",
281727
+ "sort",
281728
+ "reverse",
281729
+ "join",
281730
+ "flat",
281731
+ "flatMap",
281732
+ "includes",
281733
+ "indexOf",
281734
+ "slice",
281735
+ "splice",
281736
+ "concat"
281737
+ ]);
280820
281738
  NameAllocator = class {
280821
281739
  taken;
280822
281740
  constructor(initial) {
@@ -282690,6 +283608,109 @@ async function runCheck(file, opts = {}) {
282690
283608
  process.exitCode = 1;
282691
283609
  }
282692
283610
  }
283611
+ async function runCheckFix(opts) {
283612
+ const core = await Promise.resolve().then(() => (init_src(), src_exports));
283613
+ const { checkSource: checkSource2, pTrue: pTrue3, sidecarPathOf: sidecarPathOf2, actionsForIssue: actionsForIssue2 } = core;
283614
+ const { collectSkipReturns: collectSkipReturns2, defaultLoadModule: defaultLoadModule3 } = await Promise.resolve().then(() => (init_src4(), src_exports4));
283615
+ const {
283616
+ materializeAction: materializeAction2,
283617
+ applyTextEdits: applyTextEdits2,
283618
+ unifiedDiff: unifiedDiff2
283619
+ } = await Promise.resolve().then(() => (init_emit2(), emit_exports));
283620
+ const { writeFileSync: writeFileSync11, readFileSync: readFileSync29, existsSync: existsSync26 } = await import("fs");
283621
+ const only = opts.only && opts.only.length > 0 ? new Set(opts.only) : void 0;
283622
+ let planned = 0;
283623
+ let written = 0;
283624
+ for (const file of opts.targets) {
283625
+ let source;
283626
+ try {
283627
+ source = readFileSync29(file, "utf-8");
283628
+ } catch {
283629
+ continue;
283630
+ }
283631
+ const report = checkSource2(file, source, pTrue3, {
283632
+ loadModule: defaultLoadModule3,
283633
+ fromFile: file,
283634
+ ...opts.ignoreThrows ? { ignoreThrows: opts.ignoreThrows } : {},
283635
+ ...opts.entryThrows ? { entryThrows: opts.entryThrows } : {},
283636
+ skips: collectSkipReturns2(source)
283637
+ });
283638
+ const sidecar = sidecarPathOf2(file);
283639
+ let sidecarText;
283640
+ try {
283641
+ sidecarText = existsSync26(sidecar) ? readFileSync29(sidecar, "utf-8") : void 0;
283642
+ } catch {
283643
+ sidecarText = void 0;
283644
+ }
283645
+ for (const issue of report.issues) {
283646
+ if (only && !only.has(issue.code)) continue;
283647
+ const acts = issue.actions ?? actionsForIssue2(issue);
283648
+ const throwsKind = issue.suggestion?.match(/@nudo:throws\s+(\w+)/)?.[1] ?? issue.actual?.match(/throws\s+([A-Za-z]+)/)?.[1];
283649
+ const rank = (k) => k === "fix" ? 0 : k === "adjust" ? 1 : 2;
283650
+ const plans = [];
283651
+ for (const action of acts) {
283652
+ if (action.kind === "info") continue;
283653
+ const plan2 = materializeAction2({
283654
+ code: issue.code,
283655
+ fn: issue.fn,
283656
+ file,
283657
+ source,
283658
+ sidecarText,
283659
+ sidecarPath: sidecar,
283660
+ action,
283661
+ throwsKind,
283662
+ expected: issue.expected,
283663
+ suggestion: issue.suggestion
283664
+ });
283665
+ if (plan2) plans.push(plan2);
283666
+ }
283667
+ plans.sort((a, b) => rank(a.titleKind) - rank(b.titleKind));
283668
+ const plan = plans.find((p) => rank(p.titleKind) <= 1);
283669
+ if (!plan) continue;
283670
+ if (plan.edits.length > 0) {
283671
+ const next = applyTextEdits2(source, plan.edits);
283672
+ if (next !== source) {
283673
+ planned++;
283674
+ console.log(`
283675
+ --- ${file}`);
283676
+ console.log(`+++ ${file} (${plan.title})`);
283677
+ console.log(unifiedDiff2(source, next, file) || "(no line diff)");
283678
+ if (opts.write) {
283679
+ writeFileSync11(file, next, "utf-8");
283680
+ source = next;
283681
+ written++;
283682
+ }
283683
+ }
283684
+ }
283685
+ if (plan.sidecar) {
283686
+ const cur = sidecarText ?? "";
283687
+ const next = plan.sidecar.newText;
283688
+ if (next !== cur) {
283689
+ planned++;
283690
+ console.log(`
283691
+ --- ${plan.sidecar.path}`);
283692
+ console.log(`+++ ${plan.sidecar.path} (${plan.title})`);
283693
+ console.log(unifiedDiff2(cur, next, plan.sidecar.path) || "(new file)");
283694
+ if (opts.write) {
283695
+ writeFileSync11(plan.sidecar.path, next, "utf-8");
283696
+ sidecarText = next;
283697
+ written++;
283698
+ }
283699
+ }
283700
+ }
283701
+ }
283702
+ }
283703
+ const mode = opts.write ? "written" : "planned (dry-run)";
283704
+ console.log(
283705
+ `
283706
+ check --fix: ${planned} edit(s) ${mode}${opts.write ? `, ${written} applied` : " \u2014 pass --write to apply"}`
283707
+ );
283708
+ if (!opts.write && planned > 0) {
283709
+ console.log(
283710
+ "hint: only [fix]/[adjust] are auto-applied; [silence]/[review] need a human (or LSP quickfix)"
283711
+ );
283712
+ }
283713
+ }
282693
283714
  function registerCheckCommand(program3) {
282694
283715
  program3.command("check").description("Gate contracts + entry throws; print signatures (CI). Day 0 observation lives here.").argument("<paths...>", "File(s) or directory(s) to check").option("--watch, -w", "Watch files and re-run check on change").option("--json", "Emit stable CheckJson (1 file) or CheckJsonMulti envelope (N files) for CI / Agent").option("--gha", "GitHub Actions inline annotations (::error/::warning). Auto when GITHUB_ACTIONS=true").option("--gitlab", "GitLab Code Quality JSON array (write as gl-code-quality-report.json)").option("--verbose", "Expand Abs signatures (term/pred/conf detail)").option("--abs", "Algebra face: term/pred/conf per function").option("--fn <name>", "With --abs: only this function").option("--assume <pred...>", "With --abs: assume constraints, e.g. x>0 y>=1").option("--generalize", "With --abs: polymorphic signatures via symbolic execution").option(
282695
283716
  "--from <paths...>",
@@ -282706,7 +283727,7 @@ function registerCheckCommand(program3) {
282706
283727
  ).option(
282707
283728
  "--what-if <binding...>",
282708
283729
  "AI3: assume `name:type` bindings (e.g. raw:string) and report --target"
282709
- ).option("--target <name>", "With --what-if: binding name whose inferred type to print").action(
283730
+ ).option("--target <name>", "With --what-if: binding name whose inferred type to print").option("--fix", "Materialize one fix/adjust edit per issue (default --dry-run: print unified diff)").option("--only <codes...>", "With --fix: only these diagnostic codes (e.g. nudo:entry-may-throw)").option("--write", "With --fix: apply edits to disk (default dry-run)").option("--dry-run", "With --fix: print diffs only (default; kept for explicitness)").action(
282710
283731
  async (paths, opts) => {
282711
283732
  if (opts.whatIf && opts.whatIf.length > 0) {
282712
283733
  const targets2 = [];
@@ -282764,6 +283785,17 @@ function registerCheckCommand(program3) {
282764
283785
  }
282765
283786
  const entryThrows = isEntryThrowsMode(opts.entryThrows) ? opts.entryThrows : void 0;
282766
283787
  const profile = isGateProfile(opts.profile) ? opts.profile : void 0;
283788
+ if (opts.fix) {
283789
+ await runCheckFix({
283790
+ targets,
283791
+ only: opts.only,
283792
+ write: opts.write === true,
283793
+ ignoreThrows,
283794
+ entryThrows,
283795
+ profile
283796
+ });
283797
+ return;
283798
+ }
282767
283799
  const shared = {
282768
283800
  from: externalRecords,
282769
283801
  verbose: opts.verbose,