@fairfox/polly 0.7.1 → 0.7.4

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 (41) hide show
  1. package/dist/src/background/index.d.ts +1 -1
  2. package/dist/src/background/index.js +10 -3
  3. package/dist/src/background/index.js.map +9 -9
  4. package/dist/src/background/message-router.js +10 -3
  5. package/dist/src/background/message-router.js.map +8 -8
  6. package/dist/src/index.d.ts +9 -9
  7. package/dist/src/index.js +74 -67
  8. package/dist/src/index.js.map +12 -12
  9. package/dist/src/shared/adapters/chrome/context-menus.chrome.d.ts +1 -1
  10. package/dist/src/shared/adapters/chrome/tabs.chrome.d.ts +2 -2
  11. package/dist/src/shared/adapters/context-menus.adapter.d.ts +1 -1
  12. package/dist/src/shared/adapters/index.d.ts +4 -4
  13. package/dist/src/shared/adapters/index.js +9 -2
  14. package/dist/src/shared/adapters/index.js.map +6 -6
  15. package/dist/src/shared/adapters/tabs.adapter.d.ts +2 -2
  16. package/dist/src/shared/lib/context-helpers.js +10 -3
  17. package/dist/src/shared/lib/context-helpers.js.map +8 -8
  18. package/dist/src/shared/lib/message-bus.js +10 -3
  19. package/dist/src/shared/lib/message-bus.js.map +7 -7
  20. package/dist/src/shared/lib/state.js +10 -3
  21. package/dist/src/shared/lib/state.js.map +8 -8
  22. package/dist/src/shared/state/app-state.js +10 -3
  23. package/dist/src/shared/state/app-state.js.map +8 -8
  24. package/dist/tools/init/src/cli.js +17 -2
  25. package/dist/tools/init/src/cli.js.map +4 -4
  26. package/dist/tools/init/templates/pwa/package.json.template +3 -3
  27. package/dist/tools/teach/src/cli.js +2712 -2442
  28. package/dist/tools/teach/src/cli.js.map +11 -11
  29. package/dist/tools/teach/src/index.js +1379 -1379
  30. package/dist/tools/teach/src/index.js.map +10 -10
  31. package/dist/tools/test/src/adapters/index.d.ts +8 -8
  32. package/dist/tools/test/src/adapters/index.js +3 -2
  33. package/dist/tools/test/src/adapters/index.js.map +6 -6
  34. package/dist/tools/test/src/index.d.ts +3 -3
  35. package/dist/tools/test/src/index.js +3 -2
  36. package/dist/tools/test/src/index.js.map +6 -6
  37. package/dist/tools/verify/src/cli.js +190 -68
  38. package/dist/tools/verify/src/cli.js.map +8 -8
  39. package/dist/tools/visualize/src/cli.js +18 -3
  40. package/dist/tools/visualize/src/cli.js.map +4 -4
  41. package/package.json +27 -16
@@ -1,6 +1,21 @@
1
1
  #!/usr/bin/env bun
2
2
  import { createRequire } from "node:module";
3
+ var __create = Object.create;
4
+ var __getProtoOf = Object.getPrototypeOf;
3
5
  var __defProp = Object.defineProperty;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __toESM = (mod, isNodeMode, target) => {
9
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
10
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
+ for (let key of __getOwnPropNames(mod))
12
+ if (!__hasOwnProp.call(to, key))
13
+ __defProp(to, key, {
14
+ get: () => mod[key],
15
+ enumerable: true
16
+ });
17
+ return to;
18
+ };
4
19
  var __export = (target, all) => {
5
20
  for (var name in all)
6
21
  __defProp(target, name, {
@@ -687,6 +702,17 @@ class TLAGenerator {
687
702
  return isFirst;
688
703
  }
689
704
  addStateType(config, _analysis) {
705
+ this.defineValueTypes();
706
+ this.line("\\* Application state type definition");
707
+ this.line("State == [");
708
+ this.indent++;
709
+ const stateFields = this.collectStateFields(config, _analysis);
710
+ this.writeStateFields(stateFields);
711
+ this.indent--;
712
+ this.line("]");
713
+ this.line("");
714
+ }
715
+ defineValueTypes() {
690
716
  this.line("\\* Generic value type for sequences and maps");
691
717
  this.line("\\* Bounded to allow model checking");
692
718
  this.line('Value == {"v1", "v2", "v3"}');
@@ -695,9 +721,8 @@ class TLAGenerator {
695
721
  this.line("\\* Bounded to allow model checking");
696
722
  this.line('Keys == {"k1", "k2", "k3"}');
697
723
  this.line("");
698
- this.line("\\* Application state type definition");
699
- this.line("State == [");
700
- this.indent++;
724
+ }
725
+ collectStateFields(config, _analysis) {
701
726
  const stateFields = [];
702
727
  for (const [fieldPath, fieldConfig] of Object.entries(config.state)) {
703
728
  if (typeof fieldConfig !== "object" || fieldConfig === null)
@@ -707,24 +732,26 @@ class TLAGenerator {
707
732
  stateFields.push(`${fieldName}: ${tlaType}`);
708
733
  }
709
734
  for (const fieldAnalysis of _analysis.fields) {
710
- if (!fieldAnalysis.path || typeof fieldAnalysis.path !== "string") {
735
+ if (!fieldAnalysis.path || typeof fieldAnalysis.path !== "string")
711
736
  continue;
712
- }
713
737
  const fieldName = this.sanitizeFieldName(fieldAnalysis.path);
714
- if (stateFields.some((f) => f.startsWith(`${fieldName}:`))) {
738
+ if (stateFields.some((f) => f.startsWith(`${fieldName}:`)))
715
739
  continue;
716
- }
717
740
  const tlaType = this.inferTLATypeFromAnalysis(fieldAnalysis);
718
741
  stateFields.push(`${fieldName}: ${tlaType}`);
719
742
  }
720
- for (let i = 0;i < stateFields.length; i++) {
721
- const field = stateFields[i];
722
- const suffix = i < stateFields.length - 1 ? "," : "";
743
+ return stateFields;
744
+ }
745
+ writeStateFields(fields) {
746
+ if (fields.length === 0) {
747
+ this.line("dummy: BOOLEAN \\* Placeholder for empty state");
748
+ return;
749
+ }
750
+ for (let i = 0;i < fields.length; i++) {
751
+ const field = fields[i];
752
+ const suffix = i < fields.length - 1 ? "," : "";
723
753
  this.line(`${field}${suffix}`);
724
754
  }
725
- this.indent--;
726
- this.line("]");
727
- this.line("");
728
755
  }
729
756
  addMessageTypes(_config, analysis) {
730
757
  if (analysis.messageTypes.length === 0) {
@@ -765,6 +792,20 @@ class TLAGenerator {
765
792
  this.line("\\* Initial application state");
766
793
  this.line("InitialState == [");
767
794
  this.indent++;
795
+ const fields = this.collectInitialStateFields(config, _analysis);
796
+ this.writeInitialStateFields(fields);
797
+ this.indent--;
798
+ this.line("]");
799
+ this.line("");
800
+ this.line("\\* Initial state (extends MessageRouter)");
801
+ this.line("UserInit ==");
802
+ this.indent++;
803
+ this.line("/\\ Init \\* MessageRouter's init");
804
+ this.line("/\\ contextStates = [c \\in Contexts |-> InitialState]");
805
+ this.indent--;
806
+ this.line("");
807
+ }
808
+ collectInitialStateFields(config, _analysis) {
768
809
  const fields = [];
769
810
  for (const [fieldPath, fieldConfig] of Object.entries(config.state)) {
770
811
  if (typeof fieldConfig !== "object" || fieldConfig === null)
@@ -774,31 +815,26 @@ class TLAGenerator {
774
815
  fields.push(`${fieldName} |-> ${initialValue}`);
775
816
  }
776
817
  for (const fieldAnalysis of _analysis.fields) {
777
- if (!fieldAnalysis.path || typeof fieldAnalysis.path !== "string") {
818
+ if (!fieldAnalysis.path || typeof fieldAnalysis.path !== "string")
778
819
  continue;
779
- }
780
820
  const fieldName = this.sanitizeFieldName(fieldAnalysis.path);
781
- if (fields.some((f) => f.startsWith(`${fieldName} |->`))) {
821
+ if (fields.some((f) => f.startsWith(`${fieldName} |->`)))
782
822
  continue;
783
- }
784
823
  const initialValue = this.getInitialValueFromAnalysis(fieldAnalysis);
785
824
  fields.push(`${fieldName} |-> ${initialValue}`);
786
825
  }
826
+ return fields;
827
+ }
828
+ writeInitialStateFields(fields) {
829
+ if (fields.length === 0) {
830
+ this.line("dummy |-> FALSE \\* Placeholder for empty state");
831
+ return;
832
+ }
787
833
  for (let i = 0;i < fields.length; i++) {
788
834
  const field = fields[i];
789
835
  const suffix = i < fields.length - 1 ? "," : "";
790
836
  this.line(`${field}${suffix}`);
791
837
  }
792
- this.indent--;
793
- this.line("]");
794
- this.line("");
795
- this.line("\\* Initial state (extends MessageRouter)");
796
- this.line("UserInit ==");
797
- this.indent++;
798
- this.line("/\\ Init \\* MessageRouter's init");
799
- this.line("/\\ contextStates = [c \\in Contexts |-> InitialState]");
800
- this.indent--;
801
- this.line("");
802
838
  }
803
839
  addActions(config, analysis) {
804
840
  this.line("\\* =============================================================================");
@@ -1024,10 +1060,10 @@ class TLAGenerator {
1024
1060
  const _indexMap = new Map;
1025
1061
  result = result.replace(/(\w+(?:\.\w+)*)\[(\d+)\]|\]\[(\d+)\]/g, (_match, identPart, index1, index2) => {
1026
1062
  if (identPart) {
1027
- const newIndex2 = Number.parseInt(index1) + 1;
1063
+ const newIndex2 = Number.parseInt(index1, 10) + 1;
1028
1064
  return `${identPart}[${newIndex2}]`;
1029
1065
  }
1030
- const newIndex = Number.parseInt(index2) + 1;
1066
+ const newIndex = Number.parseInt(index2, 10) + 1;
1031
1067
  return `][${newIndex}]`;
1032
1068
  });
1033
1069
  result = result.replace(/(\w+(?:\.\w+)*)\.some\(\(?(\w+)\)?\s*=>\s*([^)]+)\)/g, (_match, arrayRef, param, condition) => {
@@ -1056,9 +1092,9 @@ class TLAGenerator {
1056
1092
  return `\\E i \\in 1..Len(${strRef}) : SubSeq(${strRef}, i, i+${substring.length}-1) = "${substring}"`;
1057
1093
  });
1058
1094
  result = result.replace(/(\w+(?:\.\w+)*)\.slice\((-?\d+)(?:,\s*(-?\d+))?\)\.length/g, (_match, strRef, start, end) => {
1059
- const startNum = Number.parseInt(start);
1095
+ const startNum = Number.parseInt(start, 10);
1060
1096
  if (end !== undefined) {
1061
- const endNum = Number.parseInt(end);
1097
+ const endNum = Number.parseInt(end, 10);
1062
1098
  if (startNum < 0 && endNum < 0) {
1063
1099
  return `Len(SubSeq(${strRef}, Len(${strRef}) - ${Math.abs(startNum)} + 1, Len(${strRef}) - ${Math.abs(endNum)}))`;
1064
1100
  }
@@ -1076,9 +1112,9 @@ class TLAGenerator {
1076
1112
  return `Len(SubSeq(${strRef}, ${startNum + 1}, Len(${strRef})))`;
1077
1113
  });
1078
1114
  result = result.replace(/(\w+(?:\.\w+)*)\.substring\((\d+)(?:,\s*(\d+))?\)\.length/g, (_match, strRef, start, end) => {
1079
- const startNum = Number.parseInt(start);
1115
+ const startNum = Number.parseInt(start, 10);
1080
1116
  if (end !== undefined) {
1081
- const endNum = Number.parseInt(end);
1117
+ const endNum = Number.parseInt(end, 10);
1082
1118
  if (startNum > endNum) {
1083
1119
  return `Len(SubSeq(${strRef}, ${endNum + 1}, ${startNum}))`;
1084
1120
  }
@@ -1087,15 +1123,15 @@ class TLAGenerator {
1087
1123
  return `Len(SubSeq(${strRef}, ${startNum + 1}, Len(${strRef})))`;
1088
1124
  });
1089
1125
  result = result.replace(/(\w+(?:\.\w+)*)\.slice\((-?\d+)\)(?!,)/g, (_match, strRef, start) => {
1090
- const startNum = Number.parseInt(start);
1126
+ const startNum = Number.parseInt(start, 10);
1091
1127
  if (startNum < 0) {
1092
1128
  return `SubSeq(${strRef}, Len(${strRef}) - ${Math.abs(startNum)} + 1, Len(${strRef}))`;
1093
1129
  }
1094
1130
  return `SubSeq(${strRef}, ${startNum + 1}, Len(${strRef}))`;
1095
1131
  });
1096
1132
  result = result.replace(/(\w+(?:\.\w+)*)\.slice\((-?\d+),\s*(-?\d+)\)/g, (_match, strRef, start, end) => {
1097
- const startNum = Number.parseInt(start);
1098
- const endNum = Number.parseInt(end);
1133
+ const startNum = Number.parseInt(start, 10);
1134
+ const endNum = Number.parseInt(end, 10);
1099
1135
  if (startNum < 0 && endNum < 0) {
1100
1136
  return `SubSeq(${strRef}, Len(${strRef}) - ${Math.abs(startNum)} + 1, Len(${strRef}) - ${Math.abs(endNum)})`;
1101
1137
  }
@@ -1108,12 +1144,12 @@ class TLAGenerator {
1108
1144
  return `SubSeq(${strRef}, ${startNum + 1}, ${endNum})`;
1109
1145
  });
1110
1146
  result = result.replace(/(\w+(?:\.\w+)*)\.substring\((\d+)\)(?!,)/g, (_match, strRef, start) => {
1111
- const startNum = Number.parseInt(start);
1147
+ const startNum = Number.parseInt(start, 10);
1112
1148
  return `SubSeq(${strRef}, ${startNum + 1}, Len(${strRef}))`;
1113
1149
  });
1114
1150
  result = result.replace(/(\w+(?:\.\w+)*)\.substring\((\d+),\s*(\d+)\)/g, (_match, strRef, start, end) => {
1115
- const startNum = Number.parseInt(start);
1116
- const endNum = Number.parseInt(end);
1151
+ const startNum = Number.parseInt(start, 10);
1152
+ const endNum = Number.parseInt(end, 10);
1117
1153
  if (startNum > endNum) {
1118
1154
  return `SubSeq(${strRef}, ${endNum + 1}, ${startNum})`;
1119
1155
  }
@@ -1189,7 +1225,7 @@ class TLAGenerator {
1189
1225
  result = result.replace(/(\w+(?:\.\w+)*)\?\.(\w+)(?!\?\.)/g, (_match, obj, prop) => `IF ${obj} # NULL THEN ${obj}.${prop} ELSE NULL`);
1190
1226
  result = result.replace(/\(([^)]+)\)\?\.(\w+)/g, (_match, expr2, prop) => `IF (${expr2}) # NULL THEN (${expr2}).${prop} ELSE NULL`);
1191
1227
  result = result.replace(/(\w+(?:\.\w+)*)\?\.\[(\d+)\]/g, (_match, obj, index) => {
1192
- const tlaIndex = Number.parseInt(index) + 1;
1228
+ const tlaIndex = Number.parseInt(index, 10) + 1;
1193
1229
  return `IF ${obj} # NULL THEN ${obj}[${tlaIndex}] ELSE NULL`;
1194
1230
  });
1195
1231
  result = result.replace(/(\w+(?:\.\w+)*)\?\.\[['"](\w+)['"]\]/g, (_match, obj, prop) => `IF ${obj} # NULL THEN ${obj}.${prop} ELSE NULL`);
@@ -1670,8 +1706,8 @@ class DockerRunner {
1670
1706
  return {
1671
1707
  success: true,
1672
1708
  stats: {
1673
- statesGenerated: statesMatch?.[1] ? Number.parseInt(statesMatch[1]) : 0,
1674
- distinctStates: distinctMatch?.[1] ? Number.parseInt(distinctMatch[1]) : 0
1709
+ statesGenerated: statesMatch?.[1] ? Number.parseInt(statesMatch[1], 10) : 0,
1710
+ distinctStates: distinctMatch?.[1] ? Number.parseInt(distinctMatch[1], 10) : 0
1675
1711
  },
1676
1712
  output
1677
1713
  };
@@ -1718,10 +1754,11 @@ class DockerRunner {
1718
1754
  proc.stderr.on("data", (data) => {
1719
1755
  stderr += data.toString();
1720
1756
  });
1721
- const timeout = options?.timeout ? setTimeout(() => {
1757
+ const timeoutValue = options?.timeout ?? 0;
1758
+ const timeout = timeoutValue > 0 ? setTimeout(() => {
1722
1759
  proc.kill();
1723
- reject(new Error(`Command timed out after ${options.timeout}ms`));
1724
- }, options.timeout) : null;
1760
+ reject(new Error(`Command timed out after ${Math.floor(timeoutValue / 1000)}s. TLC was still making progress. Consider increasing the timeout or using preset: 'thorough' for no timeout.`));
1761
+ }, timeoutValue) : null;
1725
1762
  proc.on("close", (exitCode) => {
1726
1763
  if (timeout)
1727
1764
  clearTimeout(timeout);
@@ -2114,6 +2151,22 @@ class ConfigGenerator {
2114
2151
  this.line("// • 'off' - Skip verification");
2115
2152
  this.line("//");
2116
2153
  this.line("onRelease: 'error',");
2154
+ this.line("");
2155
+ this.line("// Verification options (optional)");
2156
+ this.line("// ─────────────────────");
2157
+ this.line("//");
2158
+ this.line("// Presets provide quick configuration:");
2159
+ this.line("// • 'quick': 1 minute timeout, 1 worker");
2160
+ this.line("// • 'balanced': 5 minutes timeout, 2 workers (default)");
2161
+ this.line("// • 'thorough': No timeout, 4 workers");
2162
+ this.line("//");
2163
+ this.line("// Or customize with verification options:");
2164
+ this.line("// verification: {");
2165
+ this.line("// timeout: 300, // Timeout in seconds (0 = no timeout)");
2166
+ this.line("// workers: 2, // Number of TLC workers");
2167
+ this.line("// }");
2168
+ this.line("//");
2169
+ this.line("// preset: 'balanced',");
2117
2170
  }
2118
2171
  formatTypeName(type) {
2119
2172
  let typeName;
@@ -2226,6 +2279,9 @@ class ConfigValidator {
2226
2279
  const lineNumber = source.substring(0, position).split(`
2227
2280
  `).length;
2228
2281
  const line = lines[lineNumber - 1];
2282
+ if (line?.trim().startsWith("//")) {
2283
+ continue;
2284
+ }
2229
2285
  const fieldMatch = line?.match(/"([^"]+)":\s*{/);
2230
2286
  const fieldName = fieldMatch ? fieldMatch[1] : "unknown";
2231
2287
  locations.push({
@@ -2235,21 +2291,23 @@ class ConfigValidator {
2235
2291
  context: fieldName ?? "unknown"
2236
2292
  });
2237
2293
  }
2238
- this.issues.push({
2239
- type: "incomplete",
2240
- severity: "error",
2241
- message: `Found ${matches.length} incomplete configuration marker(s)`,
2242
- suggestion: "Replace all /* CONFIGURE */ markers with actual values"
2243
- });
2244
- for (const loc of locations) {
2294
+ if (locations.length > 0) {
2245
2295
  this.issues.push({
2246
2296
  type: "incomplete",
2247
2297
  severity: "error",
2248
- field: loc.context,
2249
- location: { line: loc.line, column: loc.column },
2250
- message: `Incomplete configuration at line ${loc.line}`,
2251
- suggestion: `Fill in value for "${loc.context}"`
2298
+ message: `Found ${locations.length} incomplete configuration marker(s)`,
2299
+ suggestion: "Replace all /* CONFIGURE */ markers with actual values"
2252
2300
  });
2301
+ for (const loc of locations) {
2302
+ this.issues.push({
2303
+ type: "incomplete",
2304
+ severity: "error",
2305
+ field: loc.context,
2306
+ location: { line: loc.line, column: loc.column },
2307
+ message: `Incomplete configuration at line ${loc.line}`,
2308
+ suggestion: `Fill in value for "${loc.context}"`
2309
+ });
2310
+ }
2253
2311
  }
2254
2312
  }
2255
2313
  }
@@ -2257,12 +2315,23 @@ class ConfigValidator {
2257
2315
  const reviewRegex = /\/\*\s*REVIEW\s*\*\//g;
2258
2316
  const matches = [...source.matchAll(reviewRegex)];
2259
2317
  if (matches.length > 0) {
2260
- this.issues.push({
2261
- type: "incomplete",
2262
- severity: "warning",
2263
- message: `Found ${matches.length} value(s) that should be reviewed`,
2264
- suggestion: "Review auto-generated values marked with /* REVIEW */"
2318
+ const lines = source.split(`
2319
+ `);
2320
+ const validMatches = [...matches].filter((match) => {
2321
+ const position = match.index ?? 0;
2322
+ const lineNumber = source.substring(0, position).split(`
2323
+ `).length;
2324
+ const line = lines[lineNumber - 1];
2325
+ return !line?.trim().startsWith("//");
2265
2326
  });
2327
+ if (validMatches.length > 0) {
2328
+ this.issues.push({
2329
+ type: "incomplete",
2330
+ severity: "warning",
2331
+ message: `Found ${validMatches.length} value(s) that should be reviewed`,
2332
+ suggestion: "Review auto-generated values marked with /* REVIEW */"
2333
+ });
2334
+ }
2266
2335
  }
2267
2336
  }
2268
2337
  loadConfig(configPath) {
@@ -3051,7 +3120,7 @@ class HandlerExtractor {
3051
3120
  const index = indexExpr ? indexExpr.getText() : "0";
3052
3121
  const value = this.extractValue(right);
3053
3122
  if (value !== undefined) {
3054
- const tlaIndex = this.isNumericLiteral(index) ? (Number.parseInt(index) + 1).toString() : `${index} + 1`;
3123
+ const tlaIndex = this.isNumericLiteral(index) ? (Number.parseInt(index, 10) + 1).toString() : `${index} + 1`;
3055
3124
  assignments.push({
3056
3125
  field: `${field}[${tlaIndex}]`,
3057
3126
  value
@@ -4327,10 +4396,55 @@ async function verifyCommand() {
4327
4396
  console.log();
4328
4397
  try {
4329
4398
  await runFullVerification(configPath);
4330
- } catch (_error) {
4399
+ } catch (error) {
4400
+ console.error(color(`
4401
+ ❌ Verification error:`, COLORS.red));
4402
+ if (error instanceof Error) {
4403
+ console.error(color(error.message, COLORS.red));
4404
+ if (process.env.POLLY_DEBUG) {
4405
+ console.error(color(`
4406
+ Stack trace:`, COLORS.gray));
4407
+ console.error(error.stack);
4408
+ }
4409
+ } else {
4410
+ console.error(String(error));
4411
+ }
4412
+ console.error();
4331
4413
  process.exit(1);
4332
4414
  }
4333
4415
  }
4416
+ function getTimeout(config) {
4417
+ if (config.verification?.timeout !== undefined) {
4418
+ return config.verification.timeout;
4419
+ }
4420
+ const preset = config.preset || "balanced";
4421
+ switch (preset) {
4422
+ case "quick":
4423
+ return 60;
4424
+ case "balanced":
4425
+ return 300;
4426
+ case "thorough":
4427
+ return 0;
4428
+ default:
4429
+ return 300;
4430
+ }
4431
+ }
4432
+ function getWorkers(config) {
4433
+ if (config.verification?.workers !== undefined) {
4434
+ return config.verification.workers;
4435
+ }
4436
+ const preset = config.preset || "balanced";
4437
+ switch (preset) {
4438
+ case "quick":
4439
+ return 1;
4440
+ case "balanced":
4441
+ return 2;
4442
+ case "thorough":
4443
+ return 4;
4444
+ default:
4445
+ return 2;
4446
+ }
4447
+ }
4334
4448
  async function runFullVerification(configPath) {
4335
4449
  const config = await loadVerificationConfig(configPath);
4336
4450
  const analysis = await runCodebaseAnalysis();
@@ -4340,19 +4454,27 @@ async function runFullVerification(configPath) {
4340
4454
  console.log(color(` ${specPath}`, COLORS.gray));
4341
4455
  console.log();
4342
4456
  const docker = await setupDocker();
4457
+ const timeoutSeconds = getTimeout(config);
4458
+ const workers = getWorkers(config);
4343
4459
  console.log(color("⚙️ Running TLC model checker...", COLORS.blue));
4344
- console.log(color(" This may take a minute...", COLORS.gray));
4460
+ if (timeoutSeconds === 0) {
4461
+ console.log(color(" No timeout set - will run until completion", COLORS.gray));
4462
+ } else {
4463
+ const timeoutMinutes = Math.floor(timeoutSeconds / 60);
4464
+ const timeoutLabel = timeoutMinutes > 0 ? `${timeoutMinutes} minute${timeoutMinutes > 1 ? "s" : ""}` : `${timeoutSeconds} seconds`;
4465
+ console.log(color(` Timeout: ${timeoutLabel}`, COLORS.gray));
4466
+ }
4345
4467
  console.log();
4346
4468
  const result = await docker.runTLC(specPath, {
4347
- workers: 2,
4348
- timeout: 120000
4469
+ workers,
4470
+ timeout: timeoutSeconds > 0 ? timeoutSeconds * 1000 : undefined
4349
4471
  });
4350
4472
  displayVerificationResults(result, specDir);
4351
4473
  }
4352
4474
  async function loadVerificationConfig(configPath) {
4353
4475
  const resolvedPath = path4.resolve(configPath);
4354
4476
  const configModule = await import(`file://${resolvedPath}?t=${Date.now()}`);
4355
- return configModule.default;
4477
+ return configModule.verificationConfig || configModule.default;
4356
4478
  }
4357
4479
  async function runCodebaseAnalysis() {
4358
4480
  console.log(color("\uD83D\uDCCA Analyzing codebase...", COLORS.blue));
@@ -4526,4 +4648,4 @@ main().catch((error) => {
4526
4648
  process.exit(1);
4527
4649
  });
4528
4650
 
4529
- //# debugId=3B4BC06E615961E764756E2164756E21
4651
+ //# debugId=487C3279544257BF64756E2164756E21