@fairfox/polly 0.90.0 → 0.91.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.
@@ -246,6 +246,21 @@ var init_expression_validator = __esm(() => {
246
246
  });
247
247
 
248
248
  // tools/verify/src/codegen/model-constants.ts
249
+ function sanitizeContextName(name) {
250
+ return name.replace(/[^A-Za-z0-9_]/g, "_");
251
+ }
252
+ function hasDeclaredContexts(config) {
253
+ const declared = config?.contexts;
254
+ return Array.isArray(declared) && declared.length > 0;
255
+ }
256
+ function resolveContexts(config) {
257
+ if (!hasDeclaredContexts(config))
258
+ return [...DEFAULT_CONTEXTS];
259
+ return (config?.contexts).map(sanitizeContextName);
260
+ }
261
+ function targetSetCount(contexts) {
262
+ return 2 ** contexts.length - 1;
263
+ }
249
264
  function hasProjectConstant(messages) {
250
265
  return messages.maxWorkers !== undefined || messages.maxRenderers !== undefined || messages.maxContexts !== undefined || messages.maxClients !== undefined;
251
266
  }
@@ -262,14 +277,13 @@ function generatedTabValues(messages) {
262
277
  function generatedTabCount(messages) {
263
278
  return generatedTabValues(messages).length;
264
279
  }
265
- function sendBranchingFactor(handlerCount, tabCount) {
266
- return CONTEXT_COUNT * TARGET_SET_COUNT * tabCount * handlerCount;
280
+ function sendBranchingFactor(handlerCount, tabCount, contexts) {
281
+ return contexts.length * targetSetCount(contexts) * tabCount * handlerCount;
267
282
  }
268
- var GENERATED_CONTEXTS, CONTEXT_COUNT, TARGET_SET_COUNT;
283
+ var DEFAULT_CONTEXTS, CONTEXT_NAME_PATTERN;
269
284
  var init_model_constants = __esm(() => {
270
- GENERATED_CONTEXTS = ["background", "content", "popup"];
271
- CONTEXT_COUNT = GENERATED_CONTEXTS.length;
272
- TARGET_SET_COUNT = 2 ** CONTEXT_COUNT - 1;
285
+ DEFAULT_CONTEXTS = ["background", "content", "popup"];
286
+ CONTEXT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
273
287
  });
274
288
 
275
289
  // tools/verify/src/runner/memory.ts
@@ -1041,7 +1055,7 @@ var init_tla = __esm(() => {
1041
1055
  lines.push("CONSTANTS");
1042
1056
  }
1043
1057
  addBasicConstants(lines, config) {
1044
- lines.push(` Contexts = {${GENERATED_CONTEXTS.join(", ")}}`);
1058
+ lines.push(` Contexts = {${resolveContexts(config).join(", ")}}`);
1045
1059
  lines.push(` MaxMessages = ${config.messages.maxInFlight || 3}`);
1046
1060
  lines.push(" NULL = NULL");
1047
1061
  if (config.messages.perMessageBounds) {
@@ -1062,7 +1076,6 @@ var init_tla = __esm(() => {
1062
1076
  hasProjectConstant = true;
1063
1077
  }
1064
1078
  if ("maxContexts" in messages && messages.maxContexts !== undefined) {
1065
- lines.push(` MaxContexts = ${messages.maxContexts}`);
1066
1079
  hasProjectConstant = true;
1067
1080
  }
1068
1081
  if ("maxClients" in messages && messages.maxClients !== undefined && !hasProjectConstant) {
@@ -3965,6 +3978,9 @@ function getTabSetInput(config) {
3965
3978
  }
3966
3979
  return {};
3967
3980
  }
3981
+ function getContextSetInput(config) {
3982
+ return config;
3983
+ }
3968
3984
  function getFeasibility(states) {
3969
3985
  if (states < 1e5)
3970
3986
  return "trivial";
@@ -3989,7 +4005,7 @@ function feasibilityLabel(f) {
3989
4005
  var OMITTED_VARIABLES = "ports, status, deliveredTo, time and payload";
3990
4006
  function dominantTerm(e) {
3991
4007
  const log10 = (n) => n > 0 ? Math.log10(n) : 0;
3992
- const topology = e.contextCount * TARGET_SET_COUNT * e.tabCount;
4008
+ const topology = e.contextCount * e.targetSets * e.tabCount;
3993
4009
  const terms = [
3994
4010
  {
3995
4011
  label: `state fields (${e.fieldProduct} combinations across ${e.contextCount} contexts)`,
@@ -4000,7 +4016,7 @@ function dominantTerm(e) {
4000
4016
  decades: e.maxInFlight * log10(e.handlerCount)
4001
4017
  },
4002
4018
  {
4003
- label: `send topology (${e.contextCount} sources x ${TARGET_SET_COUNT} target sets x ${e.tabCount} tabs)`,
4019
+ label: `send topology (${e.contextCount} sources x ${e.targetSets} target sets x ${e.tabCount} tabs)`,
4004
4020
  decades: e.maxInFlight * log10(topology)
4005
4021
  }
4006
4022
  ];
@@ -4027,9 +4043,12 @@ function estimateForScope(config, scope) {
4027
4043
  const { handlerCount, maxInFlight } = scope;
4028
4044
  const tabSetInput = getTabSetInput(config);
4029
4045
  const tabCount = generatedTabCount(tabSetInput);
4030
- const contextCount = CONTEXT_COUNT;
4046
+ const contextSetInput = getContextSetInput(config);
4047
+ const contexts = resolveContexts(contextSetInput);
4048
+ const contextsDeclared = hasDeclaredContexts(contextSetInput);
4049
+ const contextCount = contexts.length;
4031
4050
  const totalStateSpace = fieldProduct ** contextCount;
4032
- const sendBranching = sendBranchingFactor(handlerCount, tabCount);
4051
+ const sendBranching = sendBranchingFactor(handlerCount, tabCount, contexts);
4033
4052
  const interleavingFactor = sendBranching ** maxInFlight;
4034
4053
  const estimatedStates = totalStateSpace * interleavingFactor;
4035
4054
  const feasibility = getFeasibility(estimatedStates);
@@ -4041,6 +4060,7 @@ function estimateForScope(config, scope) {
4041
4060
  fieldProduct,
4042
4061
  handlerCount,
4043
4062
  contextCount,
4063
+ targetSets: targetSetCount(contexts),
4044
4064
  tabCount,
4045
4065
  maxInFlight
4046
4066
  });
@@ -4048,6 +4068,9 @@ function estimateForScope(config, scope) {
4048
4068
  if (maxInFlight > 1) {
4049
4069
  suggestions.push(`maxInFlight ${maxInFlight} → ${maxInFlight - 1} divides the estimate by ${sendBranching.toLocaleString()}x (one fewer send to branch over)`);
4050
4070
  }
4071
+ if (!contextsDeclared) {
4072
+ suggestions.push(`Contexts is the default {${contexts.join(", ")}} — no \`contexts\` key is declared. ` + `Declaring the ones this project has divides state replication by fieldProduct^(${contextCount} - n) ` + "and send branching by the drop in |Contexts| * (2^|Contexts| - 1) (polly#185)");
4073
+ }
4051
4074
  if (handlerCount > 15) {
4052
4075
  suggestions.push(`${handlerCount} handlers enter the estimate as ${handlerCount}^${maxInFlight} — splitting into subsystems is the cheapest cut`);
4053
4076
  }
@@ -4063,6 +4086,8 @@ function estimateForScope(config, scope) {
4063
4086
  handlerCount,
4064
4087
  maxInFlight,
4065
4088
  contextCount,
4089
+ contexts,
4090
+ contextsDeclared,
4066
4091
  tabCount,
4067
4092
  sendBranching,
4068
4093
  totalStateSpace,
@@ -4104,6 +4129,7 @@ class ConfigGenerator {
4104
4129
  this.addHeader();
4105
4130
  this.addImports();
4106
4131
  this.addExport();
4132
+ this.addContextsConfig(analysis);
4107
4133
  this.addStateConfig(analysis.fields, analysis.resources);
4108
4134
  this.addMessagesConfig();
4109
4135
  this.addBehaviorConfig();
@@ -4339,6 +4365,53 @@ class ConfigGenerator {
4339
4365
  }
4340
4366
  return "{ min: /* CONFIGURE */ null, max: /* CONFIGURE */ null }";
4341
4367
  }
4368
+ addContextsConfig(analysis) {
4369
+ const inferred = [];
4370
+ for (const handler of analysis.handlers ?? []) {
4371
+ const node = handler.node;
4372
+ if (node === undefined || node === "unknown")
4373
+ continue;
4374
+ if (!inferred.includes(node))
4375
+ inferred.push(node);
4376
+ }
4377
+ this.line("// ─────────────────────────────────────────────────────────");
4378
+ this.line("// Contexts — the processes/actors messages are routed between");
4379
+ this.line("// ─────────────────────────────────────────────────────────");
4380
+ this.line("// This is the cheapest term in the state space to cut. The model");
4381
+ this.line("// replicates state across the set and quantifies every send over");
4382
+ this.line("// |Contexts| x (2^|Contexts| - 1) source/target pairs.");
4383
+ this.line("//");
4384
+ this.line("// Measured on a two-handler model, one message in flight, one tab:");
4385
+ this.line("// • 3 contexts: 38,464 distinct states");
4386
+ this.line("// • 2 contexts: 4,896 distinct states");
4387
+ this.line("// • 1 context: 368 distinct states");
4388
+ this.line("//");
4389
+ const source = inferred.length > 0 ? inferred : this.projectTypeContexts();
4390
+ if (source.length > 0) {
4391
+ this.line(inferred.length > 0 ? "// ✓ Auto-configured from the file paths of the handlers" : `// ✓ Auto-configured from the project type (${this.projectType})`);
4392
+ this.line(`contexts: /* REVIEW */ [${source.map((c) => `'${c}'`).join(", ")}],`);
4393
+ } else {
4394
+ this.line("// No context could be inferred from the handler file paths.");
4395
+ this.line("// Omitting the key models the browser-extension default:");
4396
+ this.line("// ['background', 'content', 'popup']");
4397
+ this.line("// contexts: /* CONFIGURE */ ['server'],");
4398
+ }
4399
+ this.line("");
4400
+ }
4401
+ projectTypeContexts() {
4402
+ switch (this.projectType) {
4403
+ case "websocket-app":
4404
+ return ["server", "client"];
4405
+ case "pwa":
4406
+ return ["ServiceWorker", "Window"];
4407
+ case "electron":
4408
+ return ["main", "renderer"];
4409
+ case "chrome-extension":
4410
+ return ["background", "content", "popup"];
4411
+ default:
4412
+ return [];
4413
+ }
4414
+ }
4342
4415
  addMessagesConfig() {
4343
4416
  this.line("messages: {");
4344
4417
  this.indent++;
@@ -4408,13 +4481,6 @@ class ConfigGenerator {
4408
4481
  this.line("maxTabs: 1,");
4409
4482
  break;
4410
4483
  case "generic":
4411
- this.line("// Maximum contexts/actors to model.");
4412
- this.line("//");
4413
- this.line("// Recommended:");
4414
- this.line("// • 2-3: Simple message passing");
4415
- this.line("// • 4-5: Complex coordination");
4416
- this.line("//");
4417
- this.line("maxContexts: 3,");
4418
4484
  break;
4419
4485
  }
4420
4486
  this.line("");
@@ -4546,7 +4612,11 @@ function generateConfig(analysis, projectType = "chrome-extension") {
4546
4612
  return generator.generate(analysis, projectType);
4547
4613
  }
4548
4614
 
4615
+ // tools/verify/src/cli.ts
4616
+ init_model_constants();
4617
+
4549
4618
  // tools/verify/src/config/parser.ts
4619
+ init_model_constants();
4550
4620
  init_memory();
4551
4621
  import * as fs from "node:fs";
4552
4622
  import * as path from "node:path";
@@ -4629,6 +4699,45 @@ function validateCoupledFields(coupledFields, stateConfig) {
4629
4699
  }
4630
4700
 
4631
4701
  // tools/verify/src/config/parser.ts
4702
+ var RESERVED_CONTEXT_NAMES = new Set([
4703
+ "Contexts",
4704
+ "MaxMessages",
4705
+ "NULL",
4706
+ "Tabs",
4707
+ "TimeoutLimit",
4708
+ "MaxWorkers",
4709
+ "MaxRenderers",
4710
+ "MaxClients",
4711
+ "NoTarget",
4712
+ "MeshDocs",
4713
+ "ASSUME",
4714
+ "BOOLEAN",
4715
+ "CASE",
4716
+ "CHOOSE",
4717
+ "CONSTANT",
4718
+ "CONSTANTS",
4719
+ "DOMAIN",
4720
+ "ELSE",
4721
+ "ENABLED",
4722
+ "EXCEPT",
4723
+ "EXTENDS",
4724
+ "FALSE",
4725
+ "IF",
4726
+ "IN",
4727
+ "INSTANCE",
4728
+ "LET",
4729
+ "MODULE",
4730
+ "OTHER",
4731
+ "SUBSET",
4732
+ "THEN",
4733
+ "TRUE",
4734
+ "UNCHANGED",
4735
+ "UNION",
4736
+ "VARIABLE",
4737
+ "VARIABLES",
4738
+ "WITH"
4739
+ ]);
4740
+
4632
4741
  class ConfigValidator {
4633
4742
  issues = [];
4634
4743
  validate(configPath) {
@@ -4742,6 +4851,7 @@ class ConfigValidator {
4742
4851
  this.findNullPlaceholders(config.messages, "messages");
4743
4852
  this.validateBounds(config);
4744
4853
  this.validateTier1Optimizations(config.messages);
4854
+ this.validateContexts(config);
4745
4855
  if (config.verification) {
4746
4856
  this.validateVerificationOptions(config.verification);
4747
4857
  }
@@ -5023,6 +5133,115 @@ class ConfigValidator {
5023
5133
  }
5024
5134
  this.validateMemory(verification.memory);
5025
5135
  }
5136
+ validateContexts(config) {
5137
+ this.warnOnDeadMaxContexts(config);
5138
+ const contexts = config.contexts;
5139
+ if (contexts === undefined)
5140
+ return;
5141
+ if (!Array.isArray(contexts)) {
5142
+ this.issues.push({
5143
+ type: "invalid_value",
5144
+ severity: "error",
5145
+ field: "contexts",
5146
+ message: "contexts must be an array of context names",
5147
+ suggestion: `Use an array, e.g. ["server"], or omit the key for the default {${DEFAULT_CONTEXTS.join(", ")}}`
5148
+ });
5149
+ return;
5150
+ }
5151
+ if (contexts.length === 0) {
5152
+ this.issues.push({
5153
+ type: "invalid_value",
5154
+ severity: "error",
5155
+ field: "contexts",
5156
+ message: "contexts is empty; the model needs at least one context",
5157
+ suggestion: `Name at least one context, e.g. ["server"], or omit the key for the default {${DEFAULT_CONTEXTS.join(", ")}}`
5158
+ });
5159
+ return;
5160
+ }
5161
+ const seen = new Map;
5162
+ for (const name of contexts) {
5163
+ this.validateContextName(name, seen);
5164
+ }
5165
+ this.warnOnSingleContextMesh(config, contexts.length);
5166
+ }
5167
+ validateContextName(name, seen) {
5168
+ if (typeof name !== "string") {
5169
+ this.issues.push({
5170
+ type: "invalid_value",
5171
+ severity: "error",
5172
+ field: "contexts",
5173
+ message: `Context name ${JSON.stringify(name)} is not a string`,
5174
+ suggestion: "Every entry must be a string naming one context"
5175
+ });
5176
+ return;
5177
+ }
5178
+ const emitted = sanitizeContextName(name);
5179
+ if (!CONTEXT_NAME_PATTERN.test(emitted)) {
5180
+ this.issues.push({
5181
+ type: "invalid_value",
5182
+ severity: "error",
5183
+ field: "contexts",
5184
+ message: `Context "${name}" is not a TLA+ model value (emits as "${emitted}")`,
5185
+ suggestion: "Start with a letter or underscore, then letters, digits or underscores"
5186
+ });
5187
+ return;
5188
+ }
5189
+ if (RESERVED_CONTEXT_NAMES.has(emitted)) {
5190
+ this.issues.push({
5191
+ type: "invalid_value",
5192
+ severity: "error",
5193
+ field: "contexts",
5194
+ message: `Context "${name}" collides with a TLA+ keyword or a constant the .cfg already declares`,
5195
+ suggestion: `Pick a name outside {${[...RESERVED_CONTEXT_NAMES].sort().join(", ")}}`
5196
+ });
5197
+ return;
5198
+ }
5199
+ const collidesWith = seen.get(emitted);
5200
+ if (collidesWith !== undefined) {
5201
+ this.issues.push({
5202
+ type: "invalid_value",
5203
+ severity: "error",
5204
+ field: "contexts",
5205
+ message: collidesWith === name ? `Context "${name}" is declared twice` : `Contexts "${collidesWith}" and "${name}" both emit as "${emitted}"`,
5206
+ suggestion: "Each context must emit a distinct TLA+ model value"
5207
+ });
5208
+ return;
5209
+ }
5210
+ seen.set(emitted, name);
5211
+ if (emitted !== name) {
5212
+ this.issues.push({
5213
+ type: "invalid_value",
5214
+ severity: "warning",
5215
+ field: "contexts",
5216
+ message: `Context "${name}" is emitted as the model value "${emitted}"`,
5217
+ suggestion: "Name it that way in the config so the spec and the config read alike"
5218
+ });
5219
+ }
5220
+ }
5221
+ warnOnDeadMaxContexts(config) {
5222
+ if (config.messages?.maxContexts === undefined)
5223
+ return;
5224
+ this.issues.push({
5225
+ type: "invalid_value",
5226
+ severity: "warning",
5227
+ field: "messages.maxContexts",
5228
+ message: "messages.maxContexts does not size the Contexts set and never did",
5229
+ suggestion: 'Declare the set instead, e.g. contexts: ["server", "client"]'
5230
+ });
5231
+ }
5232
+ warnOnSingleContextMesh(config, contextCount) {
5233
+ if (contextCount > 1)
5234
+ return;
5235
+ if (!config.mesh || Object.keys(config.mesh).length === 0)
5236
+ return;
5237
+ this.issues.push({
5238
+ type: "invalid_value",
5239
+ severity: "warning",
5240
+ field: "contexts",
5241
+ message: "one context with a `mesh` block: PropagateMeshOp needs two distinct contexts, so mesh propagation is never enabled",
5242
+ suggestion: "Declare at least two contexts, or drop the mesh block from this model"
5243
+ });
5244
+ }
5026
5245
  validateMemory(memory) {
5027
5246
  if (memory === undefined)
5028
5247
  return;
@@ -8822,7 +9041,8 @@ function displayEstimate(estimate) {
8822
9041
  console.log(` Field combinations: ${color(String(estimate.fieldProduct), COLORS.green)}`);
8823
9042
  console.log(` Handlers: ${estimate.handlerCount}`);
8824
9043
  console.log(` Max in-flight: ${estimate.maxInFlight}`);
8825
- console.log(` Contexts: ${estimate.contextCount} (fixed by the generated .cfg)`);
9044
+ const contextSource = estimate.contextsDeclared ? "declared" : "the default — no `contexts` key";
9045
+ console.log(` Contexts: ${estimate.contextCount} — ${estimate.contexts.join(", ")} (${contextSource})`);
8826
9046
  console.log(` Tabs: ${estimate.tabCount}`);
8827
9047
  console.log(` State across contexts: ${estimate.fieldProduct}^${estimate.contextCount} = ${estimate.totalStateSpace.toLocaleString()}`);
8828
9048
  console.log(` Send branching: ${estimate.sendBranching.toLocaleString()} per message (^${estimate.maxInFlight} = ${estimate.interleavingFactor.toLocaleString()})`);
@@ -9086,6 +9306,55 @@ async function runCoupledFieldsLint(config, analysis) {
9086
9306
  console.log(color(" the relationship with a `capabilities` invariant.", COLORS.yellow));
9087
9307
  console.log();
9088
9308
  }
9309
+ function describeContextSet(config) {
9310
+ const contexts = resolveContexts(config);
9311
+ const source = hasDeclaredContexts(config) ? "declared" : "default";
9312
+ return `${contexts.join(", ")} (${contexts.length}, ${source})`;
9313
+ }
9314
+ function inferredContexts(analysis) {
9315
+ const seen = [];
9316
+ for (const handler of analysis.handlers) {
9317
+ const node = handler.node;
9318
+ if (node === undefined || node === "unknown")
9319
+ continue;
9320
+ if (!seen.includes(node))
9321
+ seen.push(node);
9322
+ }
9323
+ return seen;
9324
+ }
9325
+ function displayContextDiagnostics(config, analysis) {
9326
+ const declared = hasDeclaredContexts(config);
9327
+ const contexts = new Set(resolveContexts(config));
9328
+ const inferred = inferredContexts(analysis);
9329
+ if (!declared) {
9330
+ console.log(color(`ℹ️ No \`contexts\` key — modelling the default {${DEFAULT_CONTEXTS.join(", ")}}`, COLORS.gray));
9331
+ if (inferred.length > 0) {
9332
+ console.log(color(` polly infers from the handler paths: ${inferred.join(", ")}`, COLORS.gray));
9333
+ console.log(color(` Declaring \`contexts: [${inferred.map((c) => `"${c}"`).join(", ")}]\` shrinks the model to the contexts you have.`, COLORS.gray));
9334
+ }
9335
+ console.log();
9336
+ return;
9337
+ }
9338
+ const outside = analysis.handlers.filter((h) => {
9339
+ const node = h.node;
9340
+ return node !== undefined && node !== "unknown" && !contexts.has(sanitizeContextName(node));
9341
+ });
9342
+ if (outside.length === 0)
9343
+ return;
9344
+ console.log(color(`⚠️ ${outside.length} handler(s) run in a context \`contexts\` does not declare:`, COLORS.yellow));
9345
+ for (const h of outside.slice(0, 10)) {
9346
+ const node = h.node;
9347
+ console.log(color(` • ${h.messageType} → ${node} (${h.location.file})`, COLORS.yellow));
9348
+ }
9349
+ if (outside.length > 10) {
9350
+ console.log(color(` ... and ${outside.length - 10} more`, COLORS.yellow));
9351
+ }
9352
+ console.log();
9353
+ console.log(color(` The model quantifies sends over {${[...contexts].join(", ")}} only, so these handlers`, COLORS.yellow));
9354
+ console.log(color(" are modelled from a source they are not in. Add the missing contexts, or correct the", COLORS.yellow));
9355
+ console.log(color(" file paths polly infers them from.", COLORS.yellow));
9356
+ console.log();
9357
+ }
9089
9358
  async function runFullVerification(configPath) {
9090
9359
  const config = await loadVerificationConfig(configPath);
9091
9360
  const analysis = await runCodebaseAnalysis();
@@ -9100,6 +9369,7 @@ async function runFullVerification(configPath) {
9100
9369
  const meshFindingCount = displayMeshOrPeerSignalWarnings(typedAnalysis, declaredMeshDocs);
9101
9370
  await runCoupledFieldsLint(typedConfig, typedAnalysis);
9102
9371
  await runModelCoverage(typedConfig, typedAnalysis, meshFindingCount);
9372
+ displayContextDiagnostics(typedConfig, typedAnalysis);
9103
9373
  if (typedConfig.subsystems && Object.keys(typedConfig.subsystems).length > 0) {
9104
9374
  await runSubsystemVerification(typedConfig, typedAnalysis);
9105
9375
  if (isWitnessMode()) {
@@ -9138,6 +9408,7 @@ async function runMonolithicVerification(config, analysis) {
9138
9408
  console.log(color(` Max depth: ${maxDepth}`, COLORS.gray));
9139
9409
  }
9140
9410
  console.log(color(` Memory: ${memory ?? DEFAULT_TLC_MEMORY}`, COLORS.gray));
9411
+ console.log(color(` Contexts: ${describeContextSet(typedConfig)}`, COLORS.gray));
9141
9412
  console.log();
9142
9413
  const result = await docker.runTLC(specPath, {
9143
9414
  workers,
@@ -9213,6 +9484,8 @@ async function runSubsystemVerification(config, analysis) {
9213
9484
  const workers = getWorkers(config);
9214
9485
  const maxDepth = getMaxDepth(config);
9215
9486
  const memory = getMemory(config);
9487
+ console.log(color(`⚙️ Contexts: ${describeContextSet(config)}`, COLORS.gray));
9488
+ console.log();
9216
9489
  await Promise.resolve().then(() => init_tla());
9217
9490
  const results = [];
9218
9491
  const customTLAPaths = getCustomTLAPaths(config);
@@ -9832,4 +10105,4 @@ main().catch((error) => {
9832
10105
  process.exit(1);
9833
10106
  });
9834
10107
 
9835
- //# debugId=10A3CEC0EDCA40C864756E2164756E21
10108
+ //# debugId=3AB21B8DB351312E64756E2164756E21