doppeldiff 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -64,6 +64,10 @@ function num(n3) {
64
64
  if (Object.is(n3, -0)) return "-0";
65
65
  return String(n3);
66
66
  }
67
+ function list(items, f) {
68
+ if (!abbreviateLists || items.length <= MAX_ITEMS) return items.map(f).join(", ");
69
+ return `${items.slice(0, SHOWN_ITEMS).map(f).join(", ")}, \u2026 ${items.length - SHOWN_ITEMS} more`;
70
+ }
67
71
  function formatValue(v, max = MAX_LEN) {
68
72
  const seen = /* @__PURE__ */ new Set();
69
73
  const f = (x) => {
@@ -91,12 +95,11 @@ function formatValue(v, max = MAX_LEN) {
91
95
  if (seen.has(x)) return "[Circular]";
92
96
  seen.add(x);
93
97
  try {
94
- if (Array.isArray(x)) return `[${x.map(f).join(", ")}]`;
98
+ if (Array.isArray(x)) return `[${list(x, f)}]`;
95
99
  if (x instanceof Date)
96
100
  return Number.isNaN(x.getTime()) ? "new Date(NaN)" : `new Date(${JSON.stringify(x.toISOString())})`;
97
- if (x instanceof Map)
98
- return `new Map([${[...x].map(([k, val]) => `[${f(k)}, ${f(val)}]`).join(", ")}])`;
99
- if (x instanceof Set) return `new Set([${[...x].map(f).join(", ")}])`;
101
+ if (x instanceof Map) return `new Map([${list([...x], ([k, val]) => `[${f(k)}, ${f(val)}]`)}])`;
102
+ if (x instanceof Set) return `new Set([${list([...x], f)}])`;
100
103
  if (x instanceof RegExp) return String(x);
101
104
  if (isProtoDescriptor(x)) {
102
105
  const { proto, own } = x[PROTO_TAG];
@@ -110,7 +113,7 @@ function formatValue(v, max = MAX_LEN) {
110
113
  return `new ${x.constructor.name}([${Array.from(x).join(", ")}])`;
111
114
  const entries = Object.entries(x);
112
115
  if (entries.length === 0) return "{}";
113
- return `{ ${entries.map(([k, val]) => `${key(k)}: ${f(val)}`).join(", ")} }`;
116
+ return `{ ${list(entries, ([k, val]) => `${key(k)}: ${f(val)}`)} }`;
114
117
  } finally {
115
118
  seen.delete(x);
116
119
  }
@@ -120,7 +123,16 @@ function formatValue(v, max = MAX_LEN) {
120
123
  function formatArgs(args, max = MAX_LEN) {
121
124
  return clip(args.map((a) => formatValue(a, max)).join(", "), max);
122
125
  }
123
- function formatEnc(e, max = MAX_LEN) {
126
+ function formatEnc(e, max = MAX_LEN, abbreviate = true) {
127
+ const previous = abbreviateLists;
128
+ abbreviateLists = abbreviate;
129
+ try {
130
+ return formatEncInner(e, max);
131
+ } finally {
132
+ abbreviateLists = previous;
133
+ }
134
+ }
135
+ function formatEncInner(e, max) {
124
136
  const f = (x) => {
125
137
  switch (x.t) {
126
138
  case "undefined":
@@ -138,18 +150,18 @@ function formatEnc(e, max = MAX_LEN) {
138
150
  case "symbol":
139
151
  return `Symbol(${x.d})`;
140
152
  case "array":
141
- return `[${x.items.map(f).join(", ")}]`;
153
+ return `[${list(x.items, f)}]`;
142
154
  case "object": {
143
155
  const prefix = x.ctor && x.ctor !== "null-prototype" ? `${x.ctor} ` : "";
144
156
  if (x.entries.length === 0) return `${prefix}{}`;
145
- return `${prefix}{ ${x.entries.map(([k, v]) => `${key(k)}: ${f(v)}`).join(", ")} }`;
157
+ return `${prefix}{ ${list(x.entries, ([k, v]) => `${key(k)}: ${f(v)}`)} }`;
146
158
  }
147
159
  case "date":
148
160
  return Number.isNaN(x.v) ? "Invalid Date" : new Date(x.v).toISOString();
149
161
  case "map":
150
- return `Map(${x.entries.length}) { ${x.entries.map(([k, v]) => `${f(k)} => ${f(v)}`).join(", ")} }`;
162
+ return `Map(${x.entries.length}) { ${list(x.entries, ([k, v]) => `${f(k)} => ${f(v)}`)} }`;
151
163
  case "set":
152
- return `Set(${x.items.length}) { ${x.items.map(f).join(", ")} }`;
164
+ return `Set(${x.items.length}) { ${list(x.items, f)} }`;
153
165
  case "regexp":
154
166
  return `/${x.source}/${x.flags}`;
155
167
  case "function":
@@ -157,7 +169,7 @@ function formatEnc(e, max = MAX_LEN) {
157
169
  case "error":
158
170
  return `${x.ctor}: ${x.message}`;
159
171
  case "typed":
160
- return `${x.ctor} [${x.items.join(", ")}]`;
172
+ return `${x.ctor} [${list(x.items, String)}]`;
161
173
  case "promise":
162
174
  return "Promise";
163
175
  case "cycle":
@@ -168,12 +180,12 @@ function formatEnc(e, max = MAX_LEN) {
168
180
  };
169
181
  return clip(f(e), max);
170
182
  }
171
- function formatOutcome(o, max = MAX_LEN) {
183
+ function formatOutcome(o, max = MAX_LEN, abbreviate = true) {
172
184
  switch (o.kind) {
173
185
  case "return":
174
- return o.async ? `resolves ${formatEnc(o.value, max)}` : formatEnc(o.value, max);
186
+ return o.async ? `resolves ${formatEnc(o.value, max, abbreviate)}` : formatEnc(o.value, max, abbreviate);
175
187
  case "throw": {
176
- const e = o.error.t === "error" ? `${o.error.ctor}: ${o.error.message}` : formatEnc(o.error, max);
188
+ const e = o.error.t === "error" ? `${o.error.ctor}: ${o.error.message}` : formatEnc(o.error, max, abbreviate);
177
189
  return clip(`${o.async ? "rejects" : "throws"} ${e}`, max);
178
190
  }
179
191
  case "timeout":
@@ -216,12 +228,15 @@ function outcomeCategory(o) {
216
228
  return "crash";
217
229
  }
218
230
  }
219
- var MAX_LEN, IDENT, key;
231
+ var MAX_LEN, MAX_ITEMS, SHOWN_ITEMS, abbreviateLists, IDENT, key;
220
232
  var init_format = __esm({
221
233
  "src/core/format/format.ts"() {
222
234
  "use strict";
223
235
  init_tags();
224
236
  MAX_LEN = 120;
237
+ MAX_ITEMS = 10;
238
+ SHOWN_ITEMS = 6;
239
+ abbreviateLists = true;
225
240
  IDENT = /^[A-Za-z_$][\w$]*$/;
226
241
  key = (k) => IDENT.test(k) ? k : JSON.stringify(k);
227
242
  }
@@ -955,6 +970,10 @@ var init_model = __esm({
955
970
  inputsRun: z.number().int().nonnegative(),
956
971
  stoppedBy: z.enum(["runs", "deadline", "failures", "exhausted"]).optional(),
957
972
  failures: z.number().int().nonnegative(),
973
+ /** Timeouts/crashes on edge-case inputs (huge numbers, NaN, …), included in `failures`. */
974
+ edgeTimeouts: z.number().int().nonnegative().optional(),
975
+ /** Edge-case inputs skipped after repeated timeouts on edge-case inputs. */
976
+ skippedEdgeInputs: z.number().int().nonnegative().optional(),
958
977
  durationMs: z.number().nonnegative(),
959
978
  seed: z.number().int(),
960
979
  usage: z.object({ files: z.number().int(), callSites: z.number().int(), values: z.number().int() }).optional(),
@@ -1054,14 +1073,14 @@ function applyRuleLabels(report, forceRefactor = false) {
1054
1073
  report.summary = summarize(report.functions, report.skipped.length, report.summary.durationMs);
1055
1074
  return report;
1056
1075
  }
1057
- function outcomeView(o) {
1076
+ function outcomeView(o, abbreviate = true) {
1058
1077
  switch (o.kind) {
1059
1078
  case "return": {
1060
1079
  const code2 = encToCode(o.value);
1061
1080
  return {
1062
1081
  kind: "return",
1063
1082
  async: o.async,
1064
- display: formatOutcome(o, MAX_DISPLAY),
1083
+ display: formatOutcome(o, MAX_DISPLAY, abbreviate),
1065
1084
  ...code2 !== void 0 && code2.length < 4e3 ? { code: code2 } : {}
1066
1085
  };
1067
1086
  }
@@ -1070,7 +1089,7 @@ function outcomeView(o) {
1070
1089
  return {
1071
1090
  kind: "throw",
1072
1091
  async: o.async,
1073
- display: formatOutcome(o, MAX_DISPLAY),
1092
+ display: formatOutcome(o, MAX_DISPLAY, abbreviate),
1074
1093
  ...e.t === "error" ? { errorClass: e.ctor.slice(0, 200), message: e.message.slice(0, 4e3) } : {}
1075
1094
  };
1076
1095
  }
@@ -1087,16 +1106,21 @@ function exampleFrom(exportName, w) {
1087
1106
  new: outcomeView(w.head),
1088
1107
  minimal: w.minimal
1089
1108
  };
1109
+ if (ex.old.display === ex.new.display) {
1110
+ ex.old = outcomeView(w.base, false);
1111
+ ex.new = outcomeView(w.head, false);
1112
+ }
1090
1113
  if (w.diff.aspect === "mutation" && (w.base.kind === "return" || w.base.kind === "throw") && (w.head.kind === "return" || w.head.kind === "throw")) {
1091
1114
  const i = Number(w.diff.path[0]);
1092
1115
  const a = w.base.args[i];
1093
1116
  const b = w.head.args[i];
1094
1117
  if (a && b) {
1095
1118
  const newCode = encToCode(b);
1119
+ const full = formatEnc(a, MAX_DISPLAY) === formatEnc(b, MAX_DISPLAY);
1096
1120
  ex.mutation = {
1097
1121
  argIndex: i,
1098
- old: formatEnc(a, MAX_DISPLAY),
1099
- new: formatEnc(b, MAX_DISPLAY),
1122
+ old: formatEnc(a, MAX_DISPLAY, !full),
1123
+ new: formatEnc(b, MAX_DISPLAY, !full),
1100
1124
  ...newCode !== void 0 && newCode.length < 4e3 ? { newCode } : {}
1101
1125
  };
1102
1126
  }
@@ -1128,6 +1152,8 @@ function functionReport(f) {
1128
1152
  inputsRun: f.inputsRun,
1129
1153
  ...f.stoppedBy ? { stoppedBy: f.stoppedBy } : {},
1130
1154
  failures: f.failures,
1155
+ ...f.edgeFailures ? { edgeTimeouts: f.edgeFailures } : {},
1156
+ ...f.skippedEdgeInputs ? { skippedEdgeInputs: f.skippedEdgeInputs } : {},
1131
1157
  durationMs: f.durationMs,
1132
1158
  seed: f.seed,
1133
1159
  ...f.usage ? { usage: f.usage } : {},
@@ -1312,6 +1338,18 @@ function render(r, maxExamples, sticky) {
1312
1338
  const edge = r.functions.flatMap(
1313
1339
  (f) => f.behaviors.filter((b) => b.realism === "edge").map((b) => ({ f, b }))
1314
1340
  );
1341
+ const timedOut = r.functions.filter((f) => (f.edgeTimeouts ?? 0) > 0);
1342
+ const timeoutLine = timedOut.length ? `\u23F1\uFE0F Timed out on edge-case inputs (huge numbers, NaN, \u2026); similar inputs were skipped: ${timedOut.map((f) => `${code(f.exportName, 60)} (${n(f.edgeTimeouts ?? 0)})`).join(", ")}.` : "";
1343
+ if (edge.length === 0 && timeoutLine) {
1344
+ lines.push(
1345
+ "",
1346
+ `<details><summary>\u23F1\uFE0F Some edge-case inputs timed out</summary>`,
1347
+ "",
1348
+ timeoutLine,
1349
+ "",
1350
+ "</details>"
1351
+ );
1352
+ }
1315
1353
  if (edge.length > 0) {
1316
1354
  const reasons = [...new Set(edge.map(({ b }) => b.realismNote).filter(Boolean))].slice(0, 4).join(", ");
1317
1355
  const tag = {
@@ -1324,7 +1362,9 @@ function render(r, maxExamples, sticky) {
1324
1362
  "",
1325
1363
  `<details><summary>\u{1F9EA} ${edge.length} behavior change${edge.length === 1 ? "" : "s"} only on edge-case inputs${reasons ? ` (${escapeText(reasons)})` : ""}</summary>`,
1326
1364
  "",
1327
- edge.map(({ f, b }) => `${tag[b.label] ?? ""}${behaviorBlock(f, b, maxExamples)}`).join("\n\n"),
1365
+ // Compact: one example per edge-case behavior.
1366
+ edge.map(({ f, b }) => `${tag[b.label] ?? ""}${behaviorBlock(f, b, 1)}`).join("\n\n"),
1367
+ ...timeoutLine ? ["", timeoutLine] : [],
1328
1368
  "",
1329
1369
  "</details>"
1330
1370
  );
@@ -1724,7 +1764,7 @@ var init_pool = __esm({
1724
1764
  }
1725
1765
  /** Execute a job; timeouts and crashes become outcomes, and the process is respawned. */
1726
1766
  async run(job) {
1727
- const { timeoutMs } = this.options;
1767
+ const timeoutMs = Math.round(this.options.timeoutMs * (job.timeoutScale ?? 1));
1728
1768
  const watchdogMs = timeoutMs + Math.max(150, Math.round(timeoutMs * 0.3));
1729
1769
  const guardKey = `${job.moduleId}#${job.exportName}`;
1730
1770
  const outcomes = new Array(job.inputs.length);
@@ -1748,6 +1788,11 @@ var init_pool = __esm({
1748
1788
  if (m.t === "result" && m.reqId === reqId) {
1749
1789
  outcomes[offset + m.index] = m.outcome;
1750
1790
  count = m.index + 1;
1791
+ if (m.outcome.kind === "timeout") {
1792
+ this.guarded.add(guardKey);
1793
+ finish({ count }, true);
1794
+ return;
1795
+ }
1751
1796
  arm();
1752
1797
  } else if (m.t === "done" && m.reqId === reqId) {
1753
1798
  finish({ count }, false);
@@ -1829,18 +1874,18 @@ var init_pool = __esm({
1829
1874
  return results[0];
1830
1875
  }
1831
1876
  /** Run inputs, spreading them across processes. Outcomes are returned in input order. */
1832
- run(moduleId, exportName, inputs) {
1833
- const result = this.lock.then(() => this.runUnlocked(moduleId, exportName, inputs));
1877
+ run(moduleId, exportName, inputs, options = {}) {
1878
+ const result = this.lock.then(() => this.runUnlocked(moduleId, exportName, inputs, options.timeoutScale));
1834
1879
  this.lock = result.catch(() => void 0);
1835
1880
  return result;
1836
1881
  }
1837
- async runUnlocked(moduleId, exportName, inputs) {
1882
+ async runUnlocked(moduleId, exportName, inputs, timeoutScale) {
1838
1883
  await this.start();
1839
1884
  const chunkSize = Math.max(16, Math.ceil(inputs.length / this.procs.length));
1840
1885
  const chunks = [];
1841
1886
  for (let i = 0; i < inputs.length; i += chunkSize) chunks.push(inputs.slice(i, i + chunkSize));
1842
1887
  const results = await Promise.all(
1843
- chunks.map((c, i) => this.procs[i].run({ moduleId, exportName, inputs: c }))
1888
+ chunks.map((c, i) => this.procs[i].run({ moduleId, exportName, inputs: c, timeoutScale }))
1844
1889
  );
1845
1890
  return results.flat();
1846
1891
  }
@@ -4200,6 +4245,18 @@ function numberArb(ctx) {
4200
4245
  );
4201
4246
  return weighted(typeDriven, ctx.mined.numbers, ctx);
4202
4247
  }
4248
+ function sizeArb(ctx) {
4249
+ const typeDriven = fc2.oneof(
4250
+ { arbitrary: fc2.integer({ min: 0, max: 10 }), weight: 40 },
4251
+ { arbitrary: fc2.integer({ min: 0, max: 100 }), weight: 25 },
4252
+ { arbitrary: fc2.integer({ min: 0, max: 1e3 }), weight: 8 },
4253
+ { arbitrary: fc2.constantFrom(-1, -2, -10), weight: 3 },
4254
+ { arbitrary: fc2.constantFrom(0.5, 1.5, 2.25), weight: 2 },
4255
+ { arbitrary: fc2.constantFrom(...HUGE_SIZES), weight: 1 }
4256
+ );
4257
+ const mined = ctx.mined.numbers.filter((n3) => Number.isInteger(n3) && n3 >= -10 && n3 <= 1e3);
4258
+ return weighted(typeDriven, mined, ctx);
4259
+ }
4203
4260
  function regexSamples(arbs) {
4204
4261
  let out = sampleCache.get(arbs);
4205
4262
  if (!out) {
@@ -4325,7 +4382,7 @@ function anythingArb(ctx) {
4325
4382
  function compile(spec, ctx) {
4326
4383
  switch (spec.kind) {
4327
4384
  case "number":
4328
- return numberArb(ctx);
4385
+ return spec.size ? sizeArb(ctx) : numberArb(ctx);
4329
4386
  case "bigint":
4330
4387
  return fc2.oneof(fc2.bigInt({ min: -1000n, max: 1000n }), fc2.bigInt());
4331
4388
  case "string":
@@ -4458,7 +4515,7 @@ function compileSignature(sig, options = {}) {
4458
4515
  if (!rest) return base;
4459
4516
  return fc2.tuple(base, fc2.array(rest, { maxLength: 4 })).map(([f, r]) => [...f, ...r]);
4460
4517
  }
4461
- var UTF16_EDGES, STRUCTURAL_FRAGMENTS, INTERESTING_CHARS, SPECIAL_DATES, regexCache, sampleCache, TYPED_ARRAYS;
4518
+ var UTF16_EDGES, STRUCTURAL_FRAGMENTS, INTERESTING_CHARS, SPECIAL_DATES, HUGE_SIZES, regexCache, sampleCache, TYPED_ARRAYS;
4462
4519
  var init_compile = __esm({
4463
4520
  "src/core/arbitraries/compile.ts"() {
4464
4521
  "use strict";
@@ -4525,6 +4582,7 @@ var init_compile = __esm({
4525
4582
  /* @__PURE__ */ new Date("1999-12-31T23:59:59.000Z"),
4526
4583
  /* @__PURE__ */ new Date(NaN)
4527
4584
  ];
4585
+ HUGE_SIZES = [2 ** 31 - 1, 2 ** 32, Number.MAX_SAFE_INTEGER, 1e15, Infinity, -Infinity, NaN];
4528
4586
  regexCache = /* @__PURE__ */ new WeakMap();
4529
4587
  sampleCache = /* @__PURE__ */ new WeakMap();
4530
4588
  TYPED_ARRAYS = {
@@ -4543,6 +4601,91 @@ var init_compile = __esm({
4543
4601
  }
4544
4602
  });
4545
4603
 
4604
+ // src/core/analyze/sizeParams.ts
4605
+ import { Node as Node4, SyntaxKind as SyntaxKind4 } from "ts-morph";
4606
+ function isLoopCondition(node) {
4607
+ for (let p = node.getParent(); p; p = p.getParent()) {
4608
+ if (Node4.isForStatement(p)) return p.getCondition() !== void 0 && isWithin2(node, p.getCondition());
4609
+ if (Node4.isWhileStatement(p) || Node4.isDoStatement(p)) return isWithin2(node, p.getExpression());
4610
+ if (Node4.isBlock(p) || Node4.isFunctionLikeDeclaration(p)) return false;
4611
+ }
4612
+ return false;
4613
+ }
4614
+ function isWithin2(node, container) {
4615
+ return node.getPos() >= container.getPos() && node.getEnd() <= container.getEnd();
4616
+ }
4617
+ function usedAsSize(id) {
4618
+ const parent = id.getParent();
4619
+ if (!parent) return false;
4620
+ if (Node4.isBinaryExpression(parent)) {
4621
+ const op = parent.getOperatorToken().getKind();
4622
+ const comparison = op === SyntaxKind4.LessThanToken || op === SyntaxKind4.LessThanEqualsToken || op === SyntaxKind4.GreaterThanToken || op === SyntaxKind4.GreaterThanEqualsToken;
4623
+ if (comparison && isLoopCondition(parent)) return true;
4624
+ }
4625
+ if (Node4.isElementAccessExpression(parent) && parent.getArgumentExpression() === id) return true;
4626
+ if (Node4.isPropertyAssignment(parent) && parent.getName() === "length" && parent.getInitializer() === id)
4627
+ return true;
4628
+ if (Node4.isShorthandPropertyAssignment(parent) && parent.getName() === "length") return true;
4629
+ if ((Node4.isCallExpression(parent) || Node4.isNewExpression(parent)) && parent.getArguments().includes(id)) {
4630
+ const callee = parent.getExpression();
4631
+ const name = Node4.isPropertyAccessExpression(callee) ? callee.getName() : callee.getText();
4632
+ if (name === "Array" || LENGTH_CALLS.has(name)) return true;
4633
+ }
4634
+ return false;
4635
+ }
4636
+ function sizeLikeParams(fns) {
4637
+ const out = /* @__PURE__ */ new Set();
4638
+ for (const fn of fns) {
4639
+ if (!(Node4.isFunctionDeclaration(fn) || Node4.isFunctionExpression(fn) || Node4.isArrowFunction(fn)))
4640
+ continue;
4641
+ const params = fn.getParameters().map((p) => p.getNameNode()).filter((n3) => Node4.isIdentifier(n3)).map((n3) => n3.getText());
4642
+ for (const name of params) {
4643
+ if (SIZE_NAME.test(name)) {
4644
+ out.add(name);
4645
+ continue;
4646
+ }
4647
+ const body = fn.getBody();
4648
+ if (!body) continue;
4649
+ const refs = body.getDescendantsOfKind(SyntaxKind4.Identifier).filter((id) => id.getText() === name).filter((id) => {
4650
+ const p = id.getParent();
4651
+ return !(Node4.isPropertyAccessExpression(p) && p.getNameNode() === id);
4652
+ });
4653
+ if (refs.some(usedAsSize)) {
4654
+ out.add(name);
4655
+ continue;
4656
+ }
4657
+ for (const decl of body.getDescendantsOfKind(SyntaxKind4.VariableDeclaration)) {
4658
+ const init = decl.getInitializer();
4659
+ const local = decl.getNameNode();
4660
+ if (!init || !Node4.isIdentifier(local) || !refs.some((r) => isWithin2(r, init))) continue;
4661
+ const localRefs = body.getDescendantsOfKind(SyntaxKind4.Identifier).filter((id) => id.getText() === local.getText() && id !== local);
4662
+ if (localRefs.some(usedAsSize)) {
4663
+ out.add(name);
4664
+ break;
4665
+ }
4666
+ }
4667
+ }
4668
+ }
4669
+ return out;
4670
+ }
4671
+ var SIZE_NAME, LENGTH_CALLS;
4672
+ var init_sizeParams = __esm({
4673
+ "src/core/analyze/sizeParams.ts"() {
4674
+ "use strict";
4675
+ SIZE_NAME = /^(n|k|count|size|length|len|times|limit|index|idx|width|height|depth|pages?|parts|chunks?|rows|cols|columns|steps|retries|attempts|digits|places|precision|decimals|people|items|level|levels)$|(Count|Size|Length|Index|Limit|Width|Height|Depth|Times)$/;
4676
+ LENGTH_CALLS = /* @__PURE__ */ new Set([
4677
+ "repeat",
4678
+ "padStart",
4679
+ "padEnd",
4680
+ "at",
4681
+ "slice",
4682
+ "substring",
4683
+ "substr",
4684
+ "splice"
4685
+ ]);
4686
+ }
4687
+ });
4688
+
4546
4689
  // src/core/compare/compare.ts
4547
4690
  function diffEnc(a, b, opts = {}, path = []) {
4548
4691
  if (a.t !== b.t) return path;
@@ -4839,6 +4982,10 @@ import { xoroshiro128plus } from "pure-rand/generator/xoroshiro128plus";
4839
4982
  function biasFor(runIndex) {
4840
4983
  return 2 + Math.floor(Math.log(runIndex + 1) / Math.log(10));
4841
4984
  }
4985
+ function witnessCost(input, r) {
4986
+ const out = r ? formatOutcome(r.base, 2e3, false).length + formatOutcome(r.head, 2e3, false).length : 0;
4987
+ return inputComplexity(input) + Math.max(0, out - 40) / 20;
4988
+ }
4842
4989
  async function explore(options) {
4843
4990
  const {
4844
4991
  arbitrary,
@@ -4851,6 +4998,8 @@ async function explore(options) {
4851
4998
  shrinkBudget = 500,
4852
4999
  maxWitnesses = 3,
4853
5000
  maxFailures = 20,
5001
+ maxEdgeFailures = 2,
5002
+ maxTimeoutChecks = 12,
4854
5003
  selfCheck = 50,
4855
5004
  humanizeBudget = 150
4856
5005
  } = options;
@@ -4868,7 +5017,13 @@ async function explore(options) {
4868
5017
  return t;
4869
5018
  };
4870
5019
  let outOfDomain = 0;
5020
+ let edgeFailures = 0;
5021
+ let skippedEdgeInputs = 0;
4871
5022
  const wanted = (input) => {
5023
+ if (options.realism && edgeFailures >= maxEdgeFailures && tierOf(input) === 0) {
5024
+ skippedEdgeInputs++;
5025
+ return false;
5026
+ }
4872
5027
  if (!options.inDomain || options.inDomain(input)) return true;
4873
5028
  if (options.strictDomain) return false;
4874
5029
  return outOfDomain++ % 4 === 0;
@@ -4887,8 +5042,30 @@ async function explore(options) {
4887
5042
  let failures = 0;
4888
5043
  let shrinkEvaluations = 0;
4889
5044
  let stoppedBy = "runs";
4890
- const countFailures = (r) => {
4891
- if ([r.base, r.head].some((o) => o.kind === "timeout" || o.kind === "crash")) failures++;
5045
+ const countFailures = (input, r) => {
5046
+ if (![r.base, r.head].some((o) => o.kind === "timeout" || o.kind === "crash")) return;
5047
+ failures++;
5048
+ if (options.realism && tierOf(input) === 0) edgeFailures++;
5049
+ };
5050
+ const realisticFailures = () => failures - edgeFailures;
5051
+ let timeoutChecks = 0;
5052
+ const timedOut = (r) => r.base.kind === "timeout" || r.head.kind === "timeout";
5053
+ const confirmTimeouts = async (inputs, results) => {
5054
+ const idx2 = results.map((r, i) => i).filter((i) => timedOut(results[i]) && !(options.realism && tierOf(inputs[i]) === 0)).slice(0, Math.max(0, maxTimeoutChecks - timeoutChecks));
5055
+ if (idx2.length === 0) return;
5056
+ timeoutChecks += idx2.length;
5057
+ const again = await evaluate(
5058
+ idx2.map((i) => inputs[i]),
5059
+ { timeoutScale: 4 }
5060
+ );
5061
+ idx2.forEach((i, j) => {
5062
+ const first2 = results[i];
5063
+ const second = again[j];
5064
+ results[i] = {
5065
+ base: first2.base.kind === "timeout" ? second.base : first2.base,
5066
+ head: first2.head.kind === "timeout" ? second.head : first2.head
5067
+ };
5068
+ });
4892
5069
  };
4893
5070
  const evalCached = async (inputs) => {
4894
5071
  const keys = inputs.map(stableKey);
@@ -4902,9 +5079,10 @@ async function explore(options) {
4902
5079
  });
4903
5080
  if (missing.length > 0) {
4904
5081
  const results = await evaluate(missing);
5082
+ await confirmTimeouts(missing, results);
4905
5083
  results.forEach((r, i) => {
4906
5084
  cache.set(missingKeys[i], r);
4907
- countFailures(r);
5085
+ countFailures(missing[i], r);
4908
5086
  });
4909
5087
  }
4910
5088
  return keys.map((k) => cache.get(k));
@@ -4979,12 +5157,14 @@ async function explore(options) {
4979
5157
  flakyClusters: 0,
4980
5158
  stoppedBy: "runs",
4981
5159
  shrinkEvaluations: 0,
4982
- failures
5160
+ failures,
5161
+ edgeFailures,
5162
+ skippedEdgeInputs
4983
5163
  };
4984
5164
  }
4985
5165
  }
4986
5166
  cache.set(stableKey(inputs[i]), a[i]);
4987
- countFailures(a[i]);
5167
+ countFailures(inputs[i], a[i]);
4988
5168
  record(first[i], a[i]);
4989
5169
  }
4990
5170
  inputsRun = inputs.length;
@@ -4997,7 +5177,7 @@ async function explore(options) {
4997
5177
  stoppedBy = "deadline";
4998
5178
  break;
4999
5179
  }
5000
- if (failures >= maxFailures) {
5180
+ if (realisticFailures() >= maxFailures) {
5001
5181
  stoppedBy = "failures";
5002
5182
  break;
5003
5183
  }
@@ -5023,9 +5203,13 @@ async function explore(options) {
5023
5203
  }
5024
5204
  staleBatches = 0;
5025
5205
  const results = await evaluate(batch.map((p) => p.value.value));
5206
+ await confirmTimeouts(
5207
+ batch.map((p) => p.value.value),
5208
+ results
5209
+ );
5026
5210
  results.forEach((r, i) => {
5027
5211
  cache.set(batch[i].key, r);
5028
- countFailures(r);
5212
+ countFailures(batch[i].value.value, r);
5029
5213
  record(batch[i].value, r);
5030
5214
  });
5031
5215
  inputsRun += batch.length;
@@ -5035,6 +5219,12 @@ async function explore(options) {
5035
5219
  for (const cluster of clusters.values()) {
5036
5220
  let cur = cluster.seed;
5037
5221
  let evals = 0;
5222
+ const w0 = cluster.witnesses[0];
5223
+ if (w0.base.kind === "timeout" || w0.head.kind === "timeout") {
5224
+ cluster.witnesses.length = 1;
5225
+ cluster.witnesses[0].minimal = true;
5226
+ continue;
5227
+ }
5038
5228
  if (exampleValues.has(cur) && !arbitrary.canShrinkWithoutContext(cur.value)) continue;
5039
5229
  let improved = true;
5040
5230
  while (improved && evals < shrinkBudget) {
@@ -5061,7 +5251,7 @@ async function explore(options) {
5061
5251
  break;
5062
5252
  }
5063
5253
  }
5064
- if (failures >= maxFailures * 2) break;
5254
+ if (realisticFailures() >= maxFailures * 2) break;
5065
5255
  }
5066
5256
  shrinkEvaluations += evals;
5067
5257
  const sameCluster = async (candidates) => {
@@ -5076,7 +5266,9 @@ async function explore(options) {
5076
5266
  finals.set(stableKey(h.input), h.input);
5077
5267
  finals.set(stableKey(start), start);
5078
5268
  }
5079
- const ranked = [...finals.values()].filter((input) => classify(input, cache.get(stableKey(input)))?.key === cluster.key).sort((a, b) => tierOf(b) - tierOf(a) || inputComplexity(a) - inputComplexity(b)).slice(0, maxWitnesses);
5269
+ const ranked = [...finals.values()].filter((input) => classify(input, cache.get(stableKey(input)))?.key === cluster.key).sort(
5270
+ (a, b) => tierOf(b) - tierOf(a) || witnessCost(a, cache.get(stableKey(a))) - witnessCost(b, cache.get(stableKey(b)))
5271
+ ).slice(0, maxWitnesses);
5080
5272
  cluster.witnesses = ranked.map((input, i) => {
5081
5273
  const r = cache.get(stableKey(input));
5082
5274
  const w = {
@@ -5094,7 +5286,7 @@ async function explore(options) {
5094
5286
  for (const cluster of clusters.values()) {
5095
5287
  for (const w of cluster.witnesses) w.realism ??= options.realism(w.input);
5096
5288
  cluster.witnesses.sort(
5097
- (a, b) => b.realism.tier - a.realism.tier || inputComplexity(a.input) - inputComplexity(b.input)
5289
+ (a, b) => b.realism.tier - a.realism.tier || witnessCost(a.input, { base: a.base, head: a.head }) - witnessCost(b.input, { base: b.base, head: b.head })
5098
5290
  );
5099
5291
  cluster.witnesses.forEach((w, i) => w.minimal = i === 0);
5100
5292
  }
@@ -5126,7 +5318,9 @@ async function explore(options) {
5126
5318
  flakyClusters,
5127
5319
  stoppedBy,
5128
5320
  shrinkEvaluations,
5129
- failures
5321
+ failures,
5322
+ edgeFailures,
5323
+ skippedEdgeInputs
5130
5324
  };
5131
5325
  }
5132
5326
  var size;
@@ -5228,6 +5422,11 @@ function printSpec(spec) {
5228
5422
  return spec.kind;
5229
5423
  }
5230
5424
  }
5425
+ function markSize(spec) {
5426
+ if (spec.kind === "number") return { kind: "number", size: true };
5427
+ if (spec.kind === "union") return { ...spec, options: spec.options.map(markSize) };
5428
+ return spec;
5429
+ }
5231
5430
  var BINARY_CTORS;
5232
5431
  var init_spec = __esm({
5233
5432
  "src/core/types/spec.ts"() {
@@ -5252,7 +5451,7 @@ var init_spec = __esm({
5252
5451
 
5253
5452
  // src/core/types/fromType.ts
5254
5453
  import {
5255
- Node as Node4,
5454
+ Node as Node5,
5256
5455
  ts as ts4
5257
5456
  } from "ts-morph";
5258
5457
  function typeId(type) {
@@ -5384,7 +5583,7 @@ function objectLike(type, ctx) {
5384
5583
  }
5385
5584
  function isClassInstance(type) {
5386
5585
  const decls = type.getSymbol()?.getDeclarations() ?? [];
5387
- return decls.some((d) => Node4.isClassDeclaration(d) || Node4.isClassExpression(d));
5586
+ return decls.some((d) => Node5.isClassDeclaration(d) || Node5.isClassExpression(d));
5388
5587
  }
5389
5588
  function unwrapPromise(type) {
5390
5589
  const name = symbolName(type);
@@ -5463,7 +5662,7 @@ function paramSpec(p, location, index) {
5463
5662
  if (optional && !rest) {
5464
5663
  spec = spec.kind === "union" ? spec.options.some((o) => o.kind === "undefined") ? spec : { kind: "union", options: [...spec.options, { kind: "undefined" }] } : spec.kind === "undefined" ? spec : { kind: "union", options: [spec, { kind: "undefined" }] };
5465
5664
  }
5466
- const name = Node4.isIdentifier(p.getNameNode()) ? p.getName() : `arg${index}`;
5665
+ const name = Node5.isIdentifier(p.getNameNode()) ? p.getName() : `arg${index}`;
5467
5666
  return { name, spec, optional, rest };
5468
5667
  }
5469
5668
  function signatureFromNode(fn) {
@@ -5477,7 +5676,7 @@ function signatureFromCallable(decl) {
5477
5676
  const checker = decl.getProject().getTypeChecker();
5478
5677
  const params = sig.getParameters().map((sym, i) => {
5479
5678
  const pdecl = sym.getValueDeclaration();
5480
- const isParam = pdecl !== void 0 && Node4.isParameterDeclaration(pdecl);
5679
+ const isParam = pdecl !== void 0 && Node5.isParameterDeclaration(pdecl);
5481
5680
  const rest = isParam && pdecl.isRestParameter();
5482
5681
  const optional = !rest && ((sym.getFlags() & ts4.SymbolFlags.Optional) !== 0 || isParam && (pdecl.isOptional() || pdecl.hasInitializer()));
5483
5682
  let type = checker.getTypeOfSymbolAtLocation(sym, decl);
@@ -5492,7 +5691,7 @@ function signatureFromCallable(decl) {
5492
5691
  return { params, async: unwrapPromise(sig.getReturnType()) !== void 0 };
5493
5692
  }
5494
5693
  function signatureOf(node) {
5495
- return Node4.isVariableDeclaration(node) ? signatureFromCallable(node) : signatureFromNode(node);
5694
+ return Node5.isVariableDeclaration(node) ? signatureFromCallable(node) : signatureFromNode(node);
5496
5695
  }
5497
5696
  var MAX_UNION_OPTIONS, MAX_PROPS, HANDLED_BUILTINS;
5498
5697
  var init_fromType = __esm({
@@ -5514,21 +5713,21 @@ var init_fromType = __esm({
5514
5713
  });
5515
5714
 
5516
5715
  // src/core/analyze/guards.ts
5517
- import { Node as Node5, SyntaxKind as SyntaxKind4 } from "ts-morph";
5716
+ import { Node as Node6, SyntaxKind as SyntaxKind5 } from "ts-morph";
5518
5717
  function compile2(node, params) {
5519
- if (Node5.isParenthesizedExpression(node)) return compile2(node.getExpression(), params);
5520
- if (Node5.isNumericLiteral(node)) {
5718
+ if (Node6.isParenthesizedExpression(node)) return compile2(node.getExpression(), params);
5719
+ if (Node6.isNumericLiteral(node)) {
5521
5720
  const v = node.getLiteralValue();
5522
5721
  return () => v;
5523
5722
  }
5524
- if (Node5.isStringLiteral(node) || Node5.isNoSubstitutionTemplateLiteral(node)) {
5723
+ if (Node6.isStringLiteral(node) || Node6.isNoSubstitutionTemplateLiteral(node)) {
5525
5724
  const v = node.getLiteralValue();
5526
5725
  return () => v;
5527
5726
  }
5528
- if (node.getKind() === SyntaxKind4.TrueKeyword) return () => true;
5529
- if (node.getKind() === SyntaxKind4.FalseKeyword) return () => false;
5530
- if (node.getKind() === SyntaxKind4.NullKeyword) return () => null;
5531
- if (Node5.isIdentifier(node)) {
5727
+ if (node.getKind() === SyntaxKind5.TrueKeyword) return () => true;
5728
+ if (node.getKind() === SyntaxKind5.FalseKeyword) return () => false;
5729
+ if (node.getKind() === SyntaxKind5.NullKeyword) return () => null;
5730
+ if (Node6.isIdentifier(node)) {
5532
5731
  const name = node.getText();
5533
5732
  if (name === "undefined") return () => void 0;
5534
5733
  if (name === "NaN") return () => NaN;
@@ -5536,7 +5735,7 @@ function compile2(node, params) {
5536
5735
  if (params.has(name)) return (env) => env.get(name);
5537
5736
  return void 0;
5538
5737
  }
5539
- if (Node5.isPropertyAccessExpression(node) && node.getName() === "length") {
5738
+ if (Node6.isPropertyAccessExpression(node) && node.getName() === "length") {
5540
5739
  const obj = compile2(node.getExpression(), params);
5541
5740
  if (!obj) return void 0;
5542
5741
  return (env) => {
@@ -5544,7 +5743,7 @@ function compile2(node, params) {
5544
5743
  return typeof v === "string" || Array.isArray(v) ? v.length : UNKNOWN;
5545
5744
  };
5546
5745
  }
5547
- if (Node5.isTypeOfExpression(node)) {
5746
+ if (Node6.isTypeOfExpression(node)) {
5548
5747
  const e = compile2(node.getExpression(), params);
5549
5748
  if (!e) return void 0;
5550
5749
  return (env) => {
@@ -5552,16 +5751,16 @@ function compile2(node, params) {
5552
5751
  return v === UNKNOWN ? UNKNOWN : v === null ? "object" : typeof v;
5553
5752
  };
5554
5753
  }
5555
- if (Node5.isPrefixUnaryExpression(node)) {
5754
+ if (Node6.isPrefixUnaryExpression(node)) {
5556
5755
  const e = compile2(node.getOperand(), params);
5557
5756
  if (!e) return void 0;
5558
5757
  const op = node.getOperatorToken();
5559
- if (op === SyntaxKind4.ExclamationToken) return (env) => e(env) === UNKNOWN ? UNKNOWN : !e(env);
5560
- if (op === SyntaxKind4.MinusToken)
5758
+ if (op === SyntaxKind5.ExclamationToken) return (env) => e(env) === UNKNOWN ? UNKNOWN : !e(env);
5759
+ if (op === SyntaxKind5.MinusToken)
5561
5760
  return (env) => typeof e(env) === "number" ? -e(env) : UNKNOWN;
5562
5761
  return void 0;
5563
5762
  }
5564
- if (Node5.isCallExpression(node)) {
5763
+ if (Node6.isCallExpression(node)) {
5565
5764
  const callee = node.getExpression().getText().replace(/\s+/g, "");
5566
5765
  const fns = {
5567
5766
  "Number.isInteger": Number.isInteger,
@@ -5582,7 +5781,7 @@ function compile2(node, params) {
5582
5781
  return v === UNKNOWN ? UNKNOWN : fn(v);
5583
5782
  };
5584
5783
  }
5585
- if (Node5.isBinaryExpression(node)) {
5784
+ if (Node6.isBinaryExpression(node)) {
5586
5785
  const l = compile2(node.getLeft(), params);
5587
5786
  const r = compile2(node.getRight(), params);
5588
5787
  if (!l || !r) return void 0;
@@ -5593,29 +5792,29 @@ function compile2(node, params) {
5593
5792
  return a === UNKNOWN || b === UNKNOWN ? UNKNOWN : f(a, b);
5594
5793
  };
5595
5794
  switch (op) {
5596
- case SyntaxKind4.LessThanToken:
5795
+ case SyntaxKind5.LessThanToken:
5597
5796
  return cmp((a, b) => a < b);
5598
- case SyntaxKind4.LessThanEqualsToken:
5797
+ case SyntaxKind5.LessThanEqualsToken:
5599
5798
  return cmp((a, b) => a <= b);
5600
- case SyntaxKind4.GreaterThanToken:
5799
+ case SyntaxKind5.GreaterThanToken:
5601
5800
  return cmp((a, b) => a > b);
5602
- case SyntaxKind4.GreaterThanEqualsToken:
5801
+ case SyntaxKind5.GreaterThanEqualsToken:
5603
5802
  return cmp((a, b) => a >= b);
5604
- case SyntaxKind4.EqualsEqualsEqualsToken:
5803
+ case SyntaxKind5.EqualsEqualsEqualsToken:
5605
5804
  return cmp((a, b) => a === b);
5606
- case SyntaxKind4.ExclamationEqualsEqualsToken:
5805
+ case SyntaxKind5.ExclamationEqualsEqualsToken:
5607
5806
  return cmp((a, b) => a !== b);
5608
- case SyntaxKind4.EqualsEqualsToken:
5807
+ case SyntaxKind5.EqualsEqualsToken:
5609
5808
  return cmp((a, b) => a == b);
5610
- case SyntaxKind4.ExclamationEqualsToken:
5809
+ case SyntaxKind5.ExclamationEqualsToken:
5611
5810
  return cmp((a, b) => a != b);
5612
- case SyntaxKind4.AmpersandAmpersandToken:
5811
+ case SyntaxKind5.AmpersandAmpersandToken:
5613
5812
  return (env) => {
5614
5813
  const a = l(env);
5615
5814
  if (a === UNKNOWN) return UNKNOWN;
5616
5815
  return a ? r(env) : a;
5617
5816
  };
5618
- case SyntaxKind4.BarBarToken:
5817
+ case SyntaxKind5.BarBarToken:
5619
5818
  return (env) => {
5620
5819
  const a = l(env);
5621
5820
  if (a === UNKNOWN) return UNKNOWN;
@@ -5628,30 +5827,30 @@ function compile2(node, params) {
5628
5827
  return void 0;
5629
5828
  }
5630
5829
  function isExit(stmt) {
5631
- if (Node5.isThrowStatement(stmt) || Node5.isReturnStatement(stmt)) return true;
5632
- if (Node5.isBlock(stmt)) {
5830
+ if (Node6.isThrowStatement(stmt) || Node6.isReturnStatement(stmt)) return true;
5831
+ if (Node6.isBlock(stmt)) {
5633
5832
  const s = stmt.getStatements();
5634
5833
  return s.length >= 1 && isExit(s[s.length - 1]);
5635
5834
  }
5636
5835
  return false;
5637
5836
  }
5638
5837
  function inferGuards(fn) {
5639
- if (!(Node5.isFunctionDeclaration(fn) || Node5.isFunctionExpression(fn) || Node5.isArrowFunction(fn)))
5838
+ if (!(Node6.isFunctionDeclaration(fn) || Node6.isFunctionExpression(fn) || Node6.isArrowFunction(fn)))
5640
5839
  return void 0;
5641
5840
  const body = fn.getBody();
5642
- if (!body || !Node5.isBlock(body)) return void 0;
5841
+ if (!body || !Node6.isBlock(body)) return void 0;
5643
5842
  const paramDecls = fn.getParameters();
5644
- const names = paramDecls.map((p) => Node5.isIdentifier(p.getNameNode()) ? p.getName() : void 0);
5843
+ const names = paramDecls.map((p) => Node6.isIdentifier(p.getNameNode()) ? p.getName() : void 0);
5645
5844
  const params = new Set(names.filter((n3) => !!n3));
5646
5845
  const checks = [];
5647
5846
  for (const stmt of body.getStatements()) {
5648
- if (Node5.isIfStatement(stmt) && !stmt.getElseStatement() && isExit(stmt.getThenStatement())) {
5847
+ if (Node6.isIfStatement(stmt) && !stmt.getElseStatement() && isExit(stmt.getThenStatement())) {
5649
5848
  const expr = compile2(stmt.getExpression(), params);
5650
5849
  if (expr) checks.push({ text: stmt.getExpression().getText(), expr });
5651
5850
  continue;
5652
5851
  }
5653
- if (Node5.isExpressionStatement(stmt) && Node5.isCallExpression(stmt.getExpression())) continue;
5654
- if (Node5.isVariableStatement(stmt) && checks.length === 0) continue;
5852
+ if (Node6.isExpressionStatement(stmt) && Node6.isCallExpression(stmt.getExpression())) continue;
5853
+ if (Node6.isVariableStatement(stmt) && checks.length === 0) continue;
5655
5854
  break;
5656
5855
  }
5657
5856
  if (checks.length === 0) return void 0;
@@ -5754,7 +5953,7 @@ var init_accepts = __esm({
5754
5953
  });
5755
5954
 
5756
5955
  // src/core/verify/verifyFunction.ts
5757
- import { Node as Node6 } from "ts-morph";
5956
+ import { Node as Node7 } from "ts-morph";
5758
5957
  function locateExport(sf, exportName) {
5759
5958
  const index = indexModule(sf);
5760
5959
  const top = index.exports.get(exportName);
@@ -5848,11 +6047,16 @@ async function verifyFunction(session, target, options) {
5848
6047
  values: usage.numbers.length + usage.strings.length
5849
6048
  };
5850
6049
  }
5851
- const guards = Node6.isVariableDeclaration(baseLoc.node) ? void 0 : inferGuards(baseLoc.node);
6050
+ const guards = Node7.isVariableDeclaration(baseLoc.node) ? void 0 : inferGuards(baseLoc.node);
5852
6051
  if (guards) base.guards = guards.conditions;
5853
6052
  const realismCtx = realismContext(usage);
5854
6053
  base.mined = { numbers: mined.numbers.length, strings: mined.strings.length, thresholds: mined.thresholds };
5855
- const arbitrary = options.arbitrary ?? compileSignature(headSig, { mined });
6054
+ const sizeNames = sizeLikeParams([baseLoc.node, headLoc.node]);
6055
+ const genSig = sizeNames.size === 0 ? headSig : {
6056
+ ...headSig,
6057
+ params: headSig.params.map((p) => sizeNames.has(p.name) ? { ...p, spec: markSize(p.spec) } : p)
6058
+ };
6059
+ const arbitrary = options.arbitrary ?? compileSignature(genSig, { mined });
5856
6060
  if (!arbitrary) return skip("could not build an input generator for the signature");
5857
6061
  let examples = [...usage?.tuples ?? [], ...options.examples ?? []];
5858
6062
  if (options.where) examples = examples.filter((e) => safeWhere(options.where, e));
@@ -5893,10 +6097,10 @@ async function verifyFunction(session, target, options) {
5893
6097
  if (!m.load.exports.includes(target.exportName))
5894
6098
  return skip(`export \`${target.exportName}\` not found at runtime (${label})`);
5895
6099
  }
5896
- const evaluate = async (inputs) => {
6100
+ const evaluate = async (inputs, opts) => {
5897
6101
  const [b, h] = await Promise.all([
5898
- session.pools.base.run(baseMod.moduleId, target.exportName, inputs),
5899
- session.pools.head.run(headMod.moduleId, target.exportName, inputs)
6102
+ session.pools.base.run(baseMod.moduleId, target.exportName, inputs, opts),
6103
+ session.pools.head.run(headMod.moduleId, target.exportName, inputs, opts)
5900
6104
  ]);
5901
6105
  return b.map((o, i) => ({ base: o, head: h[i] }));
5902
6106
  };
@@ -5921,6 +6125,8 @@ async function verifyFunction(session, target, options) {
5921
6125
  flakyClusters: result.flakyClusters,
5922
6126
  stoppedBy: result.stoppedBy,
5923
6127
  failures: result.failures,
6128
+ edgeFailures: result.edgeFailures,
6129
+ skippedEdgeInputs: result.skippedEdgeInputs,
5924
6130
  shrinkEvaluations: result.shrinkEvaluations,
5925
6131
  durationMs: Date.now() - started
5926
6132
  };
@@ -5949,6 +6155,7 @@ var init_verifyFunction = __esm({
5949
6155
  init_compile();
5950
6156
  init_locate();
5951
6157
  init_regex();
6158
+ init_sizeParams();
5952
6159
  init_toplevel();
5953
6160
  init_explore();
5954
6161
  init_fromType();
@@ -6671,7 +6878,7 @@ function exitCodeFor(report, failOn) {
6671
6878
  if (failOn === "any") return report.summary.behaviors > 0 ? 1 : 0;
6672
6879
  return report.summary.unclaimedRealistic > 0 ? 1 : 0;
6673
6880
  }
6674
- var list = (v) => {
6881
+ var list2 = (v) => {
6675
6882
  if (v === void 0) return void 0;
6676
6883
  const arr = Array.isArray(v) ? v : [v];
6677
6884
  return arr.flatMap((x) => String(x).split(",")).map((s) => s.trim()).filter(Boolean);
@@ -6774,9 +6981,9 @@ async function runCli(flags) {
6774
6981
  timeoutMs: Number(flags.timeout ?? config.timeoutMs ?? DEFAULT_TIMEOUT_MS),
6775
6982
  ...flags.budget !== void 0 ? { timeBudgetMs: Number(flags.budget) * 1e3 } : {},
6776
6983
  freeze: flags.freeze !== false && config.freeze !== false,
6777
- ...list(flags.include) ?? config.include ? { include: list(flags.include) ?? config.include } : {},
6778
- ...list(flags.exclude) ?? config.exclude ? { exclude: [...list(flags.exclude) ?? [], ...config.exclude ?? []] } : {},
6779
- ...list(flags.only) ? { only: list(flags.only) } : {},
6984
+ ...list2(flags.include) ?? config.include ? { include: list2(flags.include) ?? config.include } : {},
6985
+ ...list2(flags.exclude) ?? config.exclude ? { exclude: [...list2(flags.exclude) ?? [], ...config.exclude ?? []] } : {},
6986
+ ...list2(flags.only) ? { only: list2(flags.only) } : {},
6780
6987
  ...config.compare ? { compare: config.compare } : {},
6781
6988
  ...config.functions ? { functions: config.functions } : {},
6782
6989
  mergeBase: flags.mergeBase !== false,