@patterkit/cli 0.2.7 → 0.3.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.
Files changed (2) hide show
  1. package/dist/cli.js +1649 -1281
  2. package/package.json +3 -3
package/dist/cli.js CHANGED
@@ -3609,7 +3609,7 @@ var require_worksheet = __commonJS({
3609
3609
  // =========================================================================
3610
3610
  // Worksheet Protection
3611
3611
  protect(password, options) {
3612
- return new Promise((resolve6) => {
3612
+ return new Promise((resolve7) => {
3613
3613
  this.sheetProtection = {
3614
3614
  sheet: true
3615
3615
  };
@@ -3633,7 +3633,7 @@ var require_worksheet = __commonJS({
3633
3633
  delete this.sheetProtection.spinCount;
3634
3634
  }
3635
3635
  }
3636
- resolve6();
3636
+ resolve7();
3637
3637
  });
3638
3638
  }
3639
3639
  unprotect() {
@@ -4353,7 +4353,7 @@ var require_BufferList = __commonJS({
4353
4353
  this.head = this.tail = null;
4354
4354
  this.length = 0;
4355
4355
  };
4356
- BufferList.prototype.join = function join7(s) {
4356
+ BufferList.prototype.join = function join8(s) {
4357
4357
  if (this.length === 0) return "";
4358
4358
  var p = this.head;
4359
4359
  var ret2 = "" + p.data;
@@ -6330,8 +6330,8 @@ var require_lib2 = __commonJS({
6330
6330
  return this;
6331
6331
  }
6332
6332
  var p = this.constructor;
6333
- return this.then(resolve7, reject3);
6334
- function resolve7(value) {
6333
+ return this.then(resolve8, reject3);
6334
+ function resolve8(value) {
6335
6335
  function yes() {
6336
6336
  return value;
6337
6337
  }
@@ -6484,8 +6484,8 @@ var require_lib2 = __commonJS({
6484
6484
  }
6485
6485
  return out;
6486
6486
  }
6487
- Promise2.resolve = resolve6;
6488
- function resolve6(value) {
6487
+ Promise2.resolve = resolve7;
6488
+ function resolve7(value) {
6489
6489
  if (value instanceof this) {
6490
6490
  return value;
6491
6491
  }
@@ -7017,10 +7017,10 @@ var require_utils = __commonJS({
7017
7017
  var promise = external.Promise.resolve(inputData).then(function(data) {
7018
7018
  var isBlob = support.blob && (data instanceof Blob || ["[object File]", "[object Blob]"].indexOf(Object.prototype.toString.call(data)) !== -1);
7019
7019
  if (isBlob && typeof FileReader !== "undefined") {
7020
- return new external.Promise(function(resolve6, reject2) {
7020
+ return new external.Promise(function(resolve7, reject2) {
7021
7021
  var reader = new FileReader();
7022
7022
  reader.onload = function(e) {
7023
- resolve6(e.target.result);
7023
+ resolve7(e.target.result);
7024
7024
  };
7025
7025
  reader.onerror = function(e) {
7026
7026
  reject2(e.target.error);
@@ -7575,7 +7575,7 @@ var require_StreamHelper = __commonJS({
7575
7575
  }
7576
7576
  }
7577
7577
  function accumulate(helper, updateCallback) {
7578
- return new external.Promise(function(resolve6, reject2) {
7578
+ return new external.Promise(function(resolve7, reject2) {
7579
7579
  var dataArray = [];
7580
7580
  var chunkType = helper._internalType, resultType = helper._outputType, mimeType = helper._mimeType;
7581
7581
  helper.on("data", function(data, meta) {
@@ -7589,7 +7589,7 @@ var require_StreamHelper = __commonJS({
7589
7589
  }).on("end", function() {
7590
7590
  try {
7591
7591
  var result = transformZipOutput(resultType, concat2(chunkType, dataArray), mimeType);
7592
- resolve6(result);
7592
+ resolve7(result);
7593
7593
  } catch (e) {
7594
7594
  reject2(e);
7595
7595
  }
@@ -13702,7 +13702,7 @@ var require_load = __commonJS({
13702
13702
  var Crc32Probe = require_Crc32Probe();
13703
13703
  var nodejsUtils = require_nodejsUtils();
13704
13704
  function checkEntryCRC32(zipEntry) {
13705
- return new external.Promise(function(resolve6, reject2) {
13705
+ return new external.Promise(function(resolve7, reject2) {
13706
13706
  var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe());
13707
13707
  worker.on("error", function(e) {
13708
13708
  reject2(e);
@@ -13710,7 +13710,7 @@ var require_load = __commonJS({
13710
13710
  if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) {
13711
13711
  reject2(new Error("Corrupted zip : CRC32 mismatch"));
13712
13712
  } else {
13713
- resolve6();
13713
+ resolve7();
13714
13714
  }
13715
13715
  }).resume();
13716
13716
  });
@@ -13939,7 +13939,7 @@ var require_buffer_list = __commonJS({
13939
13939
  }
13940
13940
  }, {
13941
13941
  key: "join",
13942
- value: function join7(s) {
13942
+ value: function join8(s) {
13943
13943
  if (this.length === 0) return "";
13944
13944
  var p = this.head;
13945
13945
  var ret2 = "" + p.data;
@@ -14967,14 +14967,14 @@ var require_async_iterator = __commonJS({
14967
14967
  };
14968
14968
  }
14969
14969
  function readAndResolve(iter) {
14970
- var resolve6 = iter[kLastResolve];
14971
- if (resolve6 !== null) {
14970
+ var resolve7 = iter[kLastResolve];
14971
+ if (resolve7 !== null) {
14972
14972
  var data = iter[kStream].read();
14973
14973
  if (data !== null) {
14974
14974
  iter[kLastPromise] = null;
14975
14975
  iter[kLastResolve] = null;
14976
14976
  iter[kLastReject] = null;
14977
- resolve6(createIterResult(data, false));
14977
+ resolve7(createIterResult(data, false));
14978
14978
  }
14979
14979
  }
14980
14980
  }
@@ -14982,13 +14982,13 @@ var require_async_iterator = __commonJS({
14982
14982
  process.nextTick(readAndResolve, iter);
14983
14983
  }
14984
14984
  function wrapForNext(lastPromise, iter) {
14985
- return function(resolve6, reject2) {
14985
+ return function(resolve7, reject2) {
14986
14986
  lastPromise.then(function() {
14987
14987
  if (iter[kEnded]) {
14988
- resolve6(createIterResult(void 0, true));
14988
+ resolve7(createIterResult(void 0, true));
14989
14989
  return;
14990
14990
  }
14991
- iter[kHandlePromise](resolve6, reject2);
14991
+ iter[kHandlePromise](resolve7, reject2);
14992
14992
  }, reject2);
14993
14993
  };
14994
14994
  }
@@ -15008,12 +15008,12 @@ var require_async_iterator = __commonJS({
15008
15008
  return Promise.resolve(createIterResult(void 0, true));
15009
15009
  }
15010
15010
  if (this[kStream].destroyed) {
15011
- return new Promise(function(resolve6, reject2) {
15011
+ return new Promise(function(resolve7, reject2) {
15012
15012
  process.nextTick(function() {
15013
15013
  if (_this[kError]) {
15014
15014
  reject2(_this[kError]);
15015
15015
  } else {
15016
- resolve6(createIterResult(void 0, true));
15016
+ resolve7(createIterResult(void 0, true));
15017
15017
  }
15018
15018
  });
15019
15019
  });
@@ -15036,13 +15036,13 @@ var require_async_iterator = __commonJS({
15036
15036
  return this;
15037
15037
  }), _defineProperty2(_Object$setPrototypeO, "return", function _return() {
15038
15038
  var _this2 = this;
15039
- return new Promise(function(resolve6, reject2) {
15039
+ return new Promise(function(resolve7, reject2) {
15040
15040
  _this2[kStream].destroy(null, function(err) {
15041
15041
  if (err) {
15042
15042
  reject2(err);
15043
15043
  return;
15044
15044
  }
15045
- resolve6(createIterResult(void 0, true));
15045
+ resolve7(createIterResult(void 0, true));
15046
15046
  });
15047
15047
  });
15048
15048
  }), _Object$setPrototypeO), AsyncIteratorPrototype);
@@ -15064,15 +15064,15 @@ var require_async_iterator = __commonJS({
15064
15064
  value: stream2._readableState.endEmitted,
15065
15065
  writable: true
15066
15066
  }), _defineProperty2(_Object$create, kHandlePromise, {
15067
- value: function value(resolve6, reject2) {
15067
+ value: function value(resolve7, reject2) {
15068
15068
  var data = iterator[kStream].read();
15069
15069
  if (data) {
15070
15070
  iterator[kLastPromise] = null;
15071
15071
  iterator[kLastResolve] = null;
15072
15072
  iterator[kLastReject] = null;
15073
- resolve6(createIterResult(data, false));
15073
+ resolve7(createIterResult(data, false));
15074
15074
  } else {
15075
- iterator[kLastResolve] = resolve6;
15075
+ iterator[kLastResolve] = resolve7;
15076
15076
  iterator[kLastReject] = reject2;
15077
15077
  }
15078
15078
  },
@@ -15091,12 +15091,12 @@ var require_async_iterator = __commonJS({
15091
15091
  iterator[kError] = err;
15092
15092
  return;
15093
15093
  }
15094
- var resolve6 = iterator[kLastResolve];
15095
- if (resolve6 !== null) {
15094
+ var resolve7 = iterator[kLastResolve];
15095
+ if (resolve7 !== null) {
15096
15096
  iterator[kLastPromise] = null;
15097
15097
  iterator[kLastResolve] = null;
15098
15098
  iterator[kLastReject] = null;
15099
- resolve6(createIterResult(void 0, true));
15099
+ resolve7(createIterResult(void 0, true));
15100
15100
  }
15101
15101
  iterator[kEnded] = true;
15102
15102
  });
@@ -15111,7 +15111,7 @@ var require_async_iterator = __commonJS({
15111
15111
  var require_from = __commonJS({
15112
15112
  "../../node_modules/readable-stream/lib/internal/streams/from.js"(exports2, module2) {
15113
15113
  "use strict";
15114
- function asyncGeneratorStep2(gen, resolve6, reject2, _next, _throw, key2, arg) {
15114
+ function asyncGeneratorStep2(gen, resolve7, reject2, _next, _throw, key2, arg) {
15115
15115
  try {
15116
15116
  var info = gen[key2](arg);
15117
15117
  var value = info.value;
@@ -15120,7 +15120,7 @@ var require_from = __commonJS({
15120
15120
  return;
15121
15121
  }
15122
15122
  if (info.done) {
15123
- resolve6(value);
15123
+ resolve7(value);
15124
15124
  } else {
15125
15125
  Promise.resolve(value).then(_next, _throw);
15126
15126
  }
@@ -15128,13 +15128,13 @@ var require_from = __commonJS({
15128
15128
  function _asyncToGenerator2(fn) {
15129
15129
  return function() {
15130
15130
  var self2 = this, args = arguments;
15131
- return new Promise(function(resolve6, reject2) {
15131
+ return new Promise(function(resolve7, reject2) {
15132
15132
  var gen = fn.apply(self2, args);
15133
15133
  function _next(value) {
15134
- asyncGeneratorStep2(gen, resolve6, reject2, _next, _throw, "next", value);
15134
+ asyncGeneratorStep2(gen, resolve7, reject2, _next, _throw, "next", value);
15135
15135
  }
15136
15136
  function _throw(err) {
15137
- asyncGeneratorStep2(gen, resolve6, reject2, _next, _throw, "throw", err);
15137
+ asyncGeneratorStep2(gen, resolve7, reject2, _next, _throw, "throw", err);
15138
15138
  }
15139
15139
  _next(void 0);
15140
15140
  });
@@ -16223,14 +16223,14 @@ var require_utils2 = __commonJS({
16223
16223
  nop() {
16224
16224
  },
16225
16225
  promiseImmediate(value) {
16226
- return new Promise((resolve6) => {
16226
+ return new Promise((resolve7) => {
16227
16227
  if (global.setImmediate) {
16228
16228
  setImmediate(() => {
16229
- resolve6(value);
16229
+ resolve7(value);
16230
16230
  });
16231
16231
  } else {
16232
16232
  setTimeout(() => {
16233
- resolve6(value);
16233
+ resolve7(value);
16234
16234
  }, 1);
16235
16235
  }
16236
16236
  });
@@ -16330,9 +16330,9 @@ var require_utils2 = __commonJS({
16330
16330
  },
16331
16331
  fs: {
16332
16332
  exists(path) {
16333
- return new Promise((resolve6) => {
16333
+ return new Promise((resolve7) => {
16334
16334
  fs4.access(path, fs4.constants.F_OK, (err) => {
16335
- resolve6(!err);
16335
+ resolve7(!err);
16336
16336
  });
16337
16337
  });
16338
16338
  }
@@ -16557,9 +16557,9 @@ var require_stream_buf = __commonJS({
16557
16557
  },
16558
16558
  async _pipe(chunk) {
16559
16559
  const write2 = function(pipe) {
16560
- return new Promise((resolve6) => {
16560
+ return new Promise((resolve7) => {
16561
16561
  pipe.write(chunk.toBuffer(), () => {
16562
- resolve6();
16562
+ resolve7();
16563
16563
  });
16564
16564
  });
16565
16565
  };
@@ -28569,12 +28569,12 @@ var require_xlsx = __commonJS({
28569
28569
  var VmlNotesXform = require_vml_notes_xform();
28570
28570
  var theme1Xml = require_theme1();
28571
28571
  function fsReadFileAsync(filename, options) {
28572
- return new Promise((resolve6, reject2) => {
28572
+ return new Promise((resolve7, reject2) => {
28573
28573
  fs4.readFile(filename, options, (error, data) => {
28574
28574
  if (error) {
28575
28575
  reject2(error);
28576
28576
  } else {
28577
- resolve6(data);
28577
+ resolve7(data);
28578
28578
  }
28579
28579
  });
28580
28580
  });
@@ -28701,7 +28701,7 @@ var require_xlsx = __commonJS({
28701
28701
  if (lastDot >= 1) {
28702
28702
  const extension = filename.substr(lastDot + 1);
28703
28703
  const name = filename.substr(0, lastDot);
28704
- await new Promise((resolve6, reject2) => {
28704
+ await new Promise((resolve7, reject2) => {
28705
28705
  const streamBuf = new StreamBuf();
28706
28706
  streamBuf.on("finish", () => {
28707
28707
  model.mediaIndex[filename] = model.media.length;
@@ -28713,7 +28713,7 @@ var require_xlsx = __commonJS({
28713
28713
  buffer: streamBuf.toBuffer()
28714
28714
  };
28715
28715
  model.media.push(medium);
28716
- resolve6();
28716
+ resolve7();
28717
28717
  });
28718
28718
  entry.on("error", (error) => {
28719
28719
  reject2(error);
@@ -28738,13 +28738,13 @@ var require_xlsx = __commonJS({
28738
28738
  model.vmlDrawings[`../drawings/${name}.vml`] = vmlDrawing;
28739
28739
  }
28740
28740
  async _processThemeEntry(entry, model, name) {
28741
- await new Promise((resolve6, reject2) => {
28741
+ await new Promise((resolve7, reject2) => {
28742
28742
  const stream2 = new StreamBuf();
28743
28743
  entry.on("error", reject2);
28744
28744
  stream2.on("error", reject2);
28745
28745
  stream2.on("finish", () => {
28746
28746
  model.themes[name] = stream2.read().toString();
28747
- resolve6();
28747
+ resolve7();
28748
28748
  });
28749
28749
  entry.pipe(stream2);
28750
28750
  });
@@ -29052,9 +29052,9 @@ var require_xlsx = __commonJS({
29052
29052
  });
29053
29053
  }
29054
29054
  _finalize(zip) {
29055
- return new Promise((resolve6, reject2) => {
29055
+ return new Promise((resolve7, reject2) => {
29056
29056
  zip.on("finish", () => {
29057
- resolve6(this);
29057
+ resolve7(this);
29058
29058
  });
29059
29059
  zip.on("error", reject2);
29060
29060
  zip.finalize();
@@ -29114,9 +29114,9 @@ var require_xlsx = __commonJS({
29114
29114
  }
29115
29115
  writeFile(filename, options) {
29116
29116
  const stream2 = fs4.createWriteStream(filename);
29117
- return new Promise((resolve6, reject2) => {
29117
+ return new Promise((resolve7, reject2) => {
29118
29118
  stream2.on("finish", () => {
29119
- resolve6();
29119
+ resolve7();
29120
29120
  });
29121
29121
  stream2.on("error", (error) => {
29122
29122
  reject2(error);
@@ -33253,7 +33253,7 @@ var require_csv = __commonJS({
33253
33253
  }
33254
33254
  read(stream2, options) {
33255
33255
  options = options || {};
33256
- return new Promise((resolve6, reject2) => {
33256
+ return new Promise((resolve7, reject2) => {
33257
33257
  const worksheet = this.workbook.addWorksheet(options.sheetName);
33258
33258
  const dateFormats = options.dateFormats || [
33259
33259
  "YYYY-MM-DD[T]HH:mm:ssZ",
@@ -33293,7 +33293,7 @@ var require_csv = __commonJS({
33293
33293
  }).on("end", () => {
33294
33294
  csvStream.emit("worksheet", worksheet);
33295
33295
  });
33296
- csvStream.on("worksheet", resolve6).on("error", reject2);
33296
+ csvStream.on("worksheet", resolve7).on("error", reject2);
33297
33297
  stream2.pipe(csvStream);
33298
33298
  });
33299
33299
  }
@@ -33306,12 +33306,12 @@ var require_csv = __commonJS({
33306
33306
  );
33307
33307
  }
33308
33308
  write(stream2, options) {
33309
- return new Promise((resolve6, reject2) => {
33309
+ return new Promise((resolve7, reject2) => {
33310
33310
  options = options || {};
33311
33311
  const worksheet = this.workbook.getWorksheet(options.sheetName || options.sheetId);
33312
33312
  const csvStream = fastCsv.format(options.formatterOptions);
33313
33313
  stream2.on("finish", () => {
33314
- resolve6();
33314
+ resolve7();
33315
33315
  });
33316
33316
  csvStream.on("error", reject2);
33317
33317
  csvStream.pipe(stream2);
@@ -34534,9 +34534,9 @@ var require_readdir_glob = __commonJS({
34534
34534
  var fs4 = __require("fs");
34535
34535
  var { EventEmitter } = __require("events");
34536
34536
  var { Minimatch } = require_minimatch();
34537
- var { resolve: resolve6 } = __require("path");
34537
+ var { resolve: resolve7 } = __require("path");
34538
34538
  function readdir(dir2, strict) {
34539
- return new Promise((resolve7, reject2) => {
34539
+ return new Promise((resolve8, reject2) => {
34540
34540
  fs4.readdir(dir2, { withFileTypes: true }, (err, files) => {
34541
34541
  if (err) {
34542
34542
  switch (err.code) {
@@ -34544,7 +34544,7 @@ var require_readdir_glob = __commonJS({
34544
34544
  if (strict) {
34545
34545
  reject2(err);
34546
34546
  } else {
34547
- resolve7([]);
34547
+ resolve8([]);
34548
34548
  }
34549
34549
  break;
34550
34550
  case "ENOTSUP":
@@ -34554,7 +34554,7 @@ var require_readdir_glob = __commonJS({
34554
34554
  case "ENAMETOOLONG":
34555
34555
  // Filename too long
34556
34556
  case "UNKNOWN":
34557
- resolve7([]);
34557
+ resolve8([]);
34558
34558
  break;
34559
34559
  case "ELOOP":
34560
34560
  // Too many levels of symbolic links
@@ -34563,30 +34563,30 @@ var require_readdir_glob = __commonJS({
34563
34563
  break;
34564
34564
  }
34565
34565
  } else {
34566
- resolve7(files);
34566
+ resolve8(files);
34567
34567
  }
34568
34568
  });
34569
34569
  });
34570
34570
  }
34571
34571
  function stat(file, followSymlinks) {
34572
- return new Promise((resolve7, reject2) => {
34572
+ return new Promise((resolve8, reject2) => {
34573
34573
  const statFunc = followSymlinks ? fs4.stat : fs4.lstat;
34574
34574
  statFunc(file, (err, stats) => {
34575
34575
  if (err) {
34576
34576
  switch (err.code) {
34577
34577
  case "ENOENT":
34578
34578
  if (followSymlinks) {
34579
- resolve7(stat(file, false));
34579
+ resolve8(stat(file, false));
34580
34580
  } else {
34581
- resolve7(null);
34581
+ resolve8(null);
34582
34582
  }
34583
34583
  break;
34584
34584
  default:
34585
- resolve7(null);
34585
+ resolve8(null);
34586
34586
  break;
34587
34587
  }
34588
34588
  } else {
34589
- resolve7(stats);
34589
+ resolve8(stats);
34590
34590
  }
34591
34591
  });
34592
34592
  });
@@ -34600,8 +34600,8 @@ var require_readdir_glob = __commonJS({
34600
34600
  useStat = true;
34601
34601
  }
34602
34602
  const filename = dir2 + "/" + name;
34603
- const relative2 = filename.slice(1);
34604
- const absolute = path + "/" + relative2;
34603
+ const relative3 = filename.slice(1);
34604
+ const absolute = path + "/" + relative3;
34605
34605
  let stats = null;
34606
34606
  if (useStat || followSymlinks) {
34607
34607
  stats = await stat(absolute, followSymlinks);
@@ -34613,12 +34613,12 @@ var require_readdir_glob = __commonJS({
34613
34613
  stats = { isDirectory: () => false };
34614
34614
  }
34615
34615
  if (stats.isDirectory()) {
34616
- if (!shouldSkip(relative2)) {
34617
- yield { relative: relative2, absolute, stats };
34616
+ if (!shouldSkip(relative3)) {
34617
+ yield { relative: relative3, absolute, stats };
34618
34618
  yield* exploreWalkAsync(filename, path, followSymlinks, useStat, shouldSkip, false);
34619
34619
  }
34620
34620
  } else {
34621
- yield { relative: relative2, absolute, stats };
34621
+ yield { relative: relative3, absolute, stats };
34622
34622
  }
34623
34623
  }
34624
34624
  }
@@ -34676,7 +34676,7 @@ var require_readdir_glob = __commonJS({
34676
34676
  (skip) => new Minimatch(skip, { dot: true })
34677
34677
  );
34678
34678
  }
34679
- this.iterator = explore(resolve6(cwd || "."), this.options.follow, this.options.stat, this._shouldSkipDirectory.bind(this));
34679
+ this.iterator = explore(resolve7(cwd || "."), this.options.follow, this.options.stat, this._shouldSkipDirectory.bind(this));
34680
34680
  this.paused = false;
34681
34681
  this.inactive = false;
34682
34682
  this.aborted = false;
@@ -34688,11 +34688,11 @@ var require_readdir_glob = __commonJS({
34688
34688
  }
34689
34689
  setTimeout(() => this._next(), 0);
34690
34690
  }
34691
- _shouldSkipDirectory(relative2) {
34692
- return this.skipMatchers.some((m) => m.match(relative2));
34691
+ _shouldSkipDirectory(relative3) {
34692
+ return this.skipMatchers.some((m) => m.match(relative3));
34693
34693
  }
34694
- _fileMatches(relative2, isDirectory) {
34695
- const file = relative2 + (isDirectory ? "/" : "");
34694
+ _fileMatches(relative3, isDirectory) {
34695
+ const file = relative3 + (isDirectory ? "/" : "");
34696
34696
  return (this.matchers.length === 0 || this.matchers.some((m) => m.match(file))) && !this.ignoreMatchers.some((m) => m.match(file)) && (!this.options.nodir || !isDirectory);
34697
34697
  }
34698
34698
  _next() {
@@ -34701,16 +34701,16 @@ var require_readdir_glob = __commonJS({
34701
34701
  if (!obj2.done) {
34702
34702
  const isDirectory = obj2.value.stats.isDirectory();
34703
34703
  if (this._fileMatches(obj2.value.relative, isDirectory)) {
34704
- let relative2 = obj2.value.relative;
34704
+ let relative3 = obj2.value.relative;
34705
34705
  let absolute = obj2.value.absolute;
34706
34706
  if (this.options.mark && isDirectory) {
34707
- relative2 += "/";
34707
+ relative3 += "/";
34708
34708
  absolute += "/";
34709
34709
  }
34710
34710
  if (this.options.stat) {
34711
- this.emit("match", { relative: relative2, absolute, stat: obj2.value.stats });
34711
+ this.emit("match", { relative: relative3, absolute, stat: obj2.value.stats });
34712
34712
  } else {
34713
- this.emit("match", { relative: relative2, absolute });
34713
+ this.emit("match", { relative: relative3, absolute });
34714
34714
  }
34715
34715
  }
34716
34716
  this._next(this.iterator);
@@ -34930,10 +34930,10 @@ function awaitify(asyncFn, arity) {
34930
34930
  if (typeof args[arity - 1] === "function") {
34931
34931
  return asyncFn.apply(this, args);
34932
34932
  }
34933
- return new Promise((resolve6, reject2) => {
34933
+ return new Promise((resolve7, reject2) => {
34934
34934
  args[arity - 1] = (err, ...cbArgs) => {
34935
34935
  if (err) return reject2(err);
34936
- resolve6(cbArgs.length > 1 ? cbArgs : cbArgs[0]);
34936
+ resolve7(cbArgs.length > 1 ? cbArgs : cbArgs[0]);
34937
34937
  };
34938
34938
  asyncFn.apply(this, args);
34939
34939
  });
@@ -35115,13 +35115,13 @@ function mapSeries(coll, iteratee, callback) {
35115
35115
  return _asyncMap(eachOfSeries$1, coll, iteratee, callback);
35116
35116
  }
35117
35117
  function promiseCallback() {
35118
- let resolve6, reject2;
35118
+ let resolve7, reject2;
35119
35119
  function callback(err, ...args) {
35120
35120
  if (err) return reject2(err);
35121
- resolve6(args.length > 1 ? args : args[0]);
35121
+ resolve7(args.length > 1 ? args : args[0]);
35122
35122
  }
35123
35123
  callback[PROMISE_SYMBOL] = new Promise((res, rej) => {
35124
- resolve6 = res, reject2 = rej;
35124
+ resolve7 = res, reject2 = rej;
35125
35125
  });
35126
35126
  return callback;
35127
35127
  }
@@ -35394,8 +35394,8 @@ function queue$1(worker, concurrency, payload) {
35394
35394
  });
35395
35395
  }
35396
35396
  if (rejectOnError || !callback) {
35397
- return new Promise((resolve6, reject2) => {
35398
- res = resolve6;
35397
+ return new Promise((resolve7, reject2) => {
35398
+ res = resolve7;
35399
35399
  rej = reject2;
35400
35400
  });
35401
35401
  }
@@ -35434,10 +35434,10 @@ function queue$1(worker, concurrency, payload) {
35434
35434
  }
35435
35435
  const eventMethod = (name) => (handler) => {
35436
35436
  if (!handler) {
35437
- return new Promise((resolve6, reject2) => {
35437
+ return new Promise((resolve7, reject2) => {
35438
35438
  once2(name, (err, data) => {
35439
35439
  if (err) return reject2(err);
35440
- resolve6(data);
35440
+ resolve7(data);
35441
35441
  });
35442
35442
  });
35443
35443
  }
@@ -37440,7 +37440,7 @@ var require_BufferList2 = __commonJS({
37440
37440
  this.head = this.tail = null;
37441
37441
  this.length = 0;
37442
37442
  };
37443
- BufferList.prototype.join = function join7(s) {
37443
+ BufferList.prototype.join = function join8(s) {
37444
37444
  if (this.length === 0) return "";
37445
37445
  var p = this.head;
37446
37446
  var ret2 = "" + p.data;
@@ -39205,7 +39205,7 @@ var require_BufferList3 = __commonJS({
39205
39205
  this.head = this.tail = null;
39206
39206
  this.length = 0;
39207
39207
  };
39208
- BufferList.prototype.join = function join7(s) {
39208
+ BufferList.prototype.join = function join8(s) {
39209
39209
  if (this.length === 0) return "";
39210
39210
  var p = this.head;
39211
39211
  var ret2 = "" + p.data;
@@ -41624,7 +41624,7 @@ var require_old = __commonJS({
41624
41624
  function maybeCallback(cb) {
41625
41625
  return typeof cb === "function" ? cb : rethrow();
41626
41626
  }
41627
- var normalize2 = pathModule.normalize;
41627
+ var normalize3 = pathModule.normalize;
41628
41628
  if (isWindows) {
41629
41629
  nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
41630
41630
  } else {
@@ -42813,7 +42813,7 @@ var require_common2 = __commonJS({
42813
42813
  var fs4 = __require("fs");
42814
42814
  var path = __require("path");
42815
42815
  var minimatch = require_minimatch2();
42816
- var isAbsolute3 = require_path_is_absolute();
42816
+ var isAbsolute4 = require_path_is_absolute();
42817
42817
  var Minimatch = minimatch.Minimatch;
42818
42818
  function alphasort(a, b) {
42819
42819
  return a.localeCompare(b, "en");
@@ -42883,7 +42883,7 @@ var require_common2 = __commonJS({
42883
42883
  self2.root = path.resolve(self2.root);
42884
42884
  if (process.platform === "win32")
42885
42885
  self2.root = self2.root.replace(/\\/g, "/");
42886
- self2.cwdAbs = isAbsolute3(self2.cwd) ? self2.cwd : makeAbs(self2, self2.cwd);
42886
+ self2.cwdAbs = isAbsolute4(self2.cwd) ? self2.cwd : makeAbs(self2, self2.cwd);
42887
42887
  if (process.platform === "win32")
42888
42888
  self2.cwdAbs = self2.cwdAbs.replace(/\\/g, "/");
42889
42889
  self2.nomount = !!options.nomount;
@@ -42963,7 +42963,7 @@ var require_common2 = __commonJS({
42963
42963
  var abs = f;
42964
42964
  if (f.charAt(0) === "/") {
42965
42965
  abs = path.join(self2.root, f);
42966
- } else if (isAbsolute3(f) || f === "") {
42966
+ } else if (isAbsolute4(f) || f === "") {
42967
42967
  abs = f;
42968
42968
  } else if (self2.changedCwd) {
42969
42969
  abs = path.resolve(self2.cwd, f);
@@ -43004,7 +43004,7 @@ var require_sync = __commonJS({
43004
43004
  var util2 = __require("util");
43005
43005
  var path = __require("path");
43006
43006
  var assert = __require("assert");
43007
- var isAbsolute3 = require_path_is_absolute();
43007
+ var isAbsolute4 = require_path_is_absolute();
43008
43008
  var common = require_common2();
43009
43009
  var setopts = common.setopts;
43010
43010
  var ownProp = common.ownProp;
@@ -43077,10 +43077,10 @@ var require_sync = __commonJS({
43077
43077
  var read2;
43078
43078
  if (prefix === null)
43079
43079
  read2 = ".";
43080
- else if (isAbsolute3(prefix) || isAbsolute3(pattern2.map(function(p) {
43080
+ else if (isAbsolute4(prefix) || isAbsolute4(pattern2.map(function(p) {
43081
43081
  return typeof p === "string" ? p : "[*]";
43082
43082
  }).join("/"))) {
43083
- if (!prefix || !isAbsolute3(prefix))
43083
+ if (!prefix || !isAbsolute4(prefix))
43084
43084
  prefix = "/" + prefix;
43085
43085
  read2 = prefix;
43086
43086
  } else
@@ -43279,7 +43279,7 @@ var require_sync = __commonJS({
43279
43279
  this.matches[index2] = /* @__PURE__ */ Object.create(null);
43280
43280
  if (!exists)
43281
43281
  return;
43282
- if (prefix && isAbsolute3(prefix) && !this.nomount) {
43282
+ if (prefix && isAbsolute4(prefix) && !this.nomount) {
43283
43283
  var trail = /[\/\\]$/.test(prefix);
43284
43284
  if (prefix.charAt(0) === "/") {
43285
43285
  prefix = path.join(this.root, prefix);
@@ -43482,7 +43482,7 @@ var require_glob = __commonJS({
43482
43482
  var EE = __require("events").EventEmitter;
43483
43483
  var path = __require("path");
43484
43484
  var assert = __require("assert");
43485
- var isAbsolute3 = require_path_is_absolute();
43485
+ var isAbsolute4 = require_path_is_absolute();
43486
43486
  var globSync = require_sync();
43487
43487
  var common = require_common2();
43488
43488
  var setopts = common.setopts;
@@ -43703,10 +43703,10 @@ var require_glob = __commonJS({
43703
43703
  var read2;
43704
43704
  if (prefix === null)
43705
43705
  read2 = ".";
43706
- else if (isAbsolute3(prefix) || isAbsolute3(pattern2.map(function(p) {
43706
+ else if (isAbsolute4(prefix) || isAbsolute4(pattern2.map(function(p) {
43707
43707
  return typeof p === "string" ? p : "[*]";
43708
43708
  }).join("/"))) {
43709
- if (!prefix || !isAbsolute3(prefix))
43709
+ if (!prefix || !isAbsolute4(prefix))
43710
43710
  prefix = "/" + prefix;
43711
43711
  read2 = prefix;
43712
43712
  } else
@@ -43791,7 +43791,7 @@ var require_glob = __commonJS({
43791
43791
  this._emitQueue.push([index2, e]);
43792
43792
  return;
43793
43793
  }
43794
- var abs = isAbsolute3(e) ? e : this._makeAbs(e);
43794
+ var abs = isAbsolute4(e) ? e : this._makeAbs(e);
43795
43795
  if (this.mark)
43796
43796
  e = this._mark(e);
43797
43797
  if (this.absolute)
@@ -43948,7 +43948,7 @@ var require_glob = __commonJS({
43948
43948
  this.matches[index2] = /* @__PURE__ */ Object.create(null);
43949
43949
  if (!exists)
43950
43950
  return cb();
43951
- if (prefix && isAbsolute3(prefix) && !this.nomount) {
43951
+ if (prefix && isAbsolute4(prefix) && !this.nomount) {
43952
43952
  var trail = /[\/\\]$/.test(prefix);
43953
43953
  if (prefix.charAt(0) === "/") {
43954
43954
  prefix = path.join(this.root, prefix);
@@ -44793,11 +44793,11 @@ var require_core = __commonJS({
44793
44793
  this._finalize();
44794
44794
  }
44795
44795
  var self2 = this;
44796
- return new Promise(function(resolve6, reject2) {
44796
+ return new Promise(function(resolve7, reject2) {
44797
44797
  var errored;
44798
44798
  self2._module.on("end", function() {
44799
44799
  if (!errored) {
44800
- resolve6();
44800
+ resolve7();
44801
44801
  }
44802
44802
  });
44803
44803
  self2._module.on("error", function(err) {
@@ -48568,7 +48568,7 @@ var require_worksheet_writer = __commonJS({
48568
48568
  // =========================================================================
48569
48569
  // Worksheet Protection
48570
48570
  protect(password, options) {
48571
- return new Promise((resolve6) => {
48571
+ return new Promise((resolve7) => {
48572
48572
  this.sheetProtection = {
48573
48573
  sheet: true
48574
48574
  };
@@ -48592,7 +48592,7 @@ var require_worksheet_writer = __commonJS({
48592
48592
  delete this.sheetProtection.spinCount;
48593
48593
  }
48594
48594
  }
48595
- resolve6();
48595
+ resolve7();
48596
48596
  });
48597
48597
  }
48598
48598
  unprotect() {
@@ -48811,9 +48811,9 @@ var require_workbook_writer = __commonJS({
48811
48811
  _commitWorksheets() {
48812
48812
  const commitWorksheet = function(worksheet) {
48813
48813
  if (!worksheet.committed) {
48814
- return new Promise((resolve6) => {
48814
+ return new Promise((resolve7) => {
48815
48815
  worksheet.stream.on("zipped", () => {
48816
- resolve6();
48816
+ resolve7();
48817
48817
  });
48818
48818
  worksheet.commit();
48819
48819
  });
@@ -48901,19 +48901,19 @@ var require_workbook_writer = __commonJS({
48901
48901
  return void 0;
48902
48902
  }
48903
48903
  addStyles() {
48904
- return new Promise((resolve6) => {
48904
+ return new Promise((resolve7) => {
48905
48905
  this.zip.append(this.styles.xml, { name: "xl/styles.xml" });
48906
- resolve6();
48906
+ resolve7();
48907
48907
  });
48908
48908
  }
48909
48909
  addThemes() {
48910
- return new Promise((resolve6) => {
48910
+ return new Promise((resolve7) => {
48911
48911
  this.zip.append(theme1Xml, { name: "xl/theme/theme1.xml" });
48912
- resolve6();
48912
+ resolve7();
48913
48913
  });
48914
48914
  }
48915
48915
  addOfficeRels() {
48916
- return new Promise((resolve6) => {
48916
+ return new Promise((resolve7) => {
48917
48917
  const xform = new RelationshipsXform();
48918
48918
  const xml = xform.toXml([
48919
48919
  { Id: "rId1", Type: RelType.OfficeDocument, Target: "xl/workbook.xml" },
@@ -48921,11 +48921,11 @@ var require_workbook_writer = __commonJS({
48921
48921
  { Id: "rId3", Type: RelType.ExtenderProperties, Target: "docProps/app.xml" }
48922
48922
  ]);
48923
48923
  this.zip.append(xml, { name: "/_rels/.rels" });
48924
- resolve6();
48924
+ resolve7();
48925
48925
  });
48926
48926
  }
48927
48927
  addContentTypes() {
48928
- return new Promise((resolve6) => {
48928
+ return new Promise((resolve7) => {
48929
48929
  const model = {
48930
48930
  worksheets: this._worksheets.filter(Boolean),
48931
48931
  sharedStrings: this.sharedStrings,
@@ -48935,7 +48935,7 @@ var require_workbook_writer = __commonJS({
48935
48935
  const xform = new ContentTypesXform();
48936
48936
  const xml = xform.toXml(model);
48937
48937
  this.zip.append(xml, { name: "[Content_Types].xml" });
48938
- resolve6();
48938
+ resolve7();
48939
48939
  });
48940
48940
  }
48941
48941
  addMedia() {
@@ -48960,31 +48960,31 @@ var require_workbook_writer = __commonJS({
48960
48960
  );
48961
48961
  }
48962
48962
  addApp() {
48963
- return new Promise((resolve6) => {
48963
+ return new Promise((resolve7) => {
48964
48964
  const model = {
48965
48965
  worksheets: this._worksheets.filter(Boolean)
48966
48966
  };
48967
48967
  const xform = new AppXform();
48968
48968
  const xml = xform.toXml(model);
48969
48969
  this.zip.append(xml, { name: "docProps/app.xml" });
48970
- resolve6();
48970
+ resolve7();
48971
48971
  });
48972
48972
  }
48973
48973
  addCore() {
48974
- return new Promise((resolve6) => {
48974
+ return new Promise((resolve7) => {
48975
48975
  const coreXform = new CoreXform();
48976
48976
  const xml = coreXform.toXml(this);
48977
48977
  this.zip.append(xml, { name: "docProps/core.xml" });
48978
- resolve6();
48978
+ resolve7();
48979
48979
  });
48980
48980
  }
48981
48981
  addSharedStrings() {
48982
48982
  if (this.sharedStrings.count) {
48983
- return new Promise((resolve6) => {
48983
+ return new Promise((resolve7) => {
48984
48984
  const sharedStringsXform = new SharedStringsXform();
48985
48985
  const xml = sharedStringsXform.toXml(this.sharedStrings);
48986
48986
  this.zip.append(xml, { name: "/xl/sharedStrings.xml" });
48987
- resolve6();
48987
+ resolve7();
48988
48988
  });
48989
48989
  }
48990
48990
  return Promise.resolve();
@@ -49012,11 +49012,11 @@ var require_workbook_writer = __commonJS({
49012
49012
  });
49013
49013
  }
49014
49014
  });
49015
- return new Promise((resolve6) => {
49015
+ return new Promise((resolve7) => {
49016
49016
  const xform = new RelationshipsXform();
49017
49017
  const xml = xform.toXml(relationships);
49018
49018
  this.zip.append(xml, { name: "/xl/_rels/workbook.xml.rels" });
49019
- resolve6();
49019
+ resolve7();
49020
49020
  });
49021
49021
  }
49022
49022
  addWorkbook() {
@@ -49028,18 +49028,18 @@ var require_workbook_writer = __commonJS({
49028
49028
  properties: {},
49029
49029
  calcProperties: {}
49030
49030
  };
49031
- return new Promise((resolve6) => {
49031
+ return new Promise((resolve7) => {
49032
49032
  const xform = new WorkbookXform();
49033
49033
  xform.prepare(model);
49034
49034
  zip.append(xform.toXml(model), { name: "/xl/workbook.xml" });
49035
- resolve6();
49035
+ resolve7();
49036
49036
  });
49037
49037
  }
49038
49038
  _finalize() {
49039
- return new Promise((resolve6, reject2) => {
49039
+ return new Promise((resolve7, reject2) => {
49040
49040
  this.stream.on("error", reject2);
49041
49041
  this.stream.on("finish", () => {
49042
- resolve6(this);
49042
+ resolve7(this);
49043
49043
  });
49044
49044
  this.zip.on("error", reject2);
49045
49045
  this.zip.finalize();
@@ -50973,13 +50973,13 @@ var require_thenables = __commonJS({
50973
50973
  promise._captureStackTrace();
50974
50974
  if (context) context._popContext();
50975
50975
  var synchronous = true;
50976
- var result = util2.tryCatch(then).call(x, resolve6, reject2);
50976
+ var result = util2.tryCatch(then).call(x, resolve7, reject2);
50977
50977
  synchronous = false;
50978
50978
  if (promise && result === errorObj2) {
50979
50979
  promise._rejectCallback(result.e, true, true);
50980
50980
  promise = null;
50981
50981
  }
50982
- function resolve6(value) {
50982
+ function resolve7(value) {
50983
50983
  if (!promise) return;
50984
50984
  promise._resolveCallback(value);
50985
50985
  promise = null;
@@ -51514,9 +51514,9 @@ var require_debuggability = __commonJS({
51514
51514
  return false;
51515
51515
  }
51516
51516
  Promise2.prototype._fireEvent = defaultFireEvent;
51517
- Promise2.prototype._execute = function(executor, resolve6, reject2) {
51517
+ Promise2.prototype._execute = function(executor, resolve7, reject2) {
51518
51518
  try {
51519
- executor(resolve6, reject2);
51519
+ executor(resolve7, reject2);
51520
51520
  } catch (e) {
51521
51521
  return e;
51522
51522
  }
@@ -51539,10 +51539,10 @@ var require_debuggability = __commonJS({
51539
51539
  ;
51540
51540
  ;
51541
51541
  };
51542
- function cancellationExecute(executor, resolve6, reject2) {
51542
+ function cancellationExecute(executor, resolve7, reject2) {
51543
51543
  var promise = this;
51544
51544
  try {
51545
- executor(resolve6, reject2, function(onCancel) {
51545
+ executor(resolve7, reject2, function(onCancel) {
51546
51546
  if (typeof onCancel !== "function") {
51547
51547
  throw new TypeError("onCancel must be a function, got: " + util2.toString(onCancel));
51548
51548
  }
@@ -55249,7 +55249,7 @@ var require_BufferList5 = __commonJS({
55249
55249
  this.head = this.tail = null;
55250
55250
  this.length = 0;
55251
55251
  };
55252
- BufferList.prototype.join = function join7(s) {
55252
+ BufferList.prototype.join = function join8(s) {
55253
55253
  if (this.length === 0) return "";
55254
55254
  var p = this.head;
55255
55255
  var ret2 = "" + p.data;
@@ -56796,7 +56796,7 @@ var require_PullStream = __commonJS({
56796
56796
  };
56797
56797
  var rejectHandler;
56798
56798
  var pullStreamRejectHandler;
56799
- return new Promise2(function(resolve6, reject2) {
56799
+ return new Promise2(function(resolve7, reject2) {
56800
56800
  rejectHandler = reject2;
56801
56801
  pullStreamRejectHandler = function(e) {
56802
56802
  self2.__emittedError = e;
@@ -56806,7 +56806,7 @@ var require_PullStream = __commonJS({
56806
56806
  return reject2(new Error("FILE_ENDED"));
56807
56807
  self2.once("error", pullStreamRejectHandler);
56808
56808
  self2.stream(eof, includeEof).on("error", reject2).pipe(concatStream).on("finish", function() {
56809
- resolve6(buffer2);
56809
+ resolve7(buffer2);
56810
56810
  }).on("error", reject2);
56811
56811
  }).finally(function() {
56812
56812
  self2.removeListener("error", rejectHandler);
@@ -56851,10 +56851,10 @@ var require_BufferStream = __commonJS({
56851
56851
  if (!Stream.Writable || !Stream.Writable.prototype.destroy)
56852
56852
  Stream = require_readable5();
56853
56853
  module2.exports = function(entry) {
56854
- return new Promise2(function(resolve6, reject2) {
56854
+ return new Promise2(function(resolve7, reject2) {
56855
56855
  var chunks = [];
56856
56856
  var bufferStream = Stream.Transform().on("finish", function() {
56857
- resolve6(Buffer2.concat(chunks));
56857
+ resolve7(Buffer2.concat(chunks));
56858
56858
  }).on("error", reject2);
56859
56859
  bufferStream._transform = function(d, e, cb) {
56860
56860
  chunks.push(d);
@@ -56996,8 +56996,8 @@ var require_parse = __commonJS({
56996
56996
  __autodraining = true;
56997
56997
  var draining2 = entry.pipe(NoopStream());
56998
56998
  draining2.promise = function() {
56999
- return new Promise2(function(resolve6, reject2) {
57000
- draining2.on("finish", resolve6);
56999
+ return new Promise2(function(resolve7, reject2) {
57000
+ draining2.on("finish", resolve7);
57001
57001
  draining2.on("error", reject2);
57002
57002
  });
57003
57003
  };
@@ -57052,11 +57052,11 @@ var require_parse = __commonJS({
57052
57052
  eof = Buffer2.alloc(4);
57053
57053
  eof.writeUInt32LE(134695760, 0);
57054
57054
  }
57055
- return new Promise2(function(resolve6, reject2) {
57055
+ return new Promise2(function(resolve7, reject2) {
57056
57056
  self2.stream(eof).pipe(inflater).on("error", function(err) {
57057
57057
  self2.emit("error", err);
57058
57058
  }).pipe(entry).on("finish", function() {
57059
- return fileSizeKnown ? self2._readRecord().then(resolve6).catch(reject2) : self2._processDataDescriptor(entry).then(resolve6).catch(reject2);
57059
+ return fileSizeKnown ? self2._readRecord().then(resolve7).catch(reject2) : self2._processDataDescriptor(entry).then(resolve7).catch(reject2);
57060
57060
  });
57061
57061
  });
57062
57062
  });
@@ -57098,8 +57098,8 @@ var require_parse = __commonJS({
57098
57098
  };
57099
57099
  Parse.prototype.promise = function() {
57100
57100
  var self2 = this;
57101
- return new Promise2(function(resolve6, reject2) {
57102
- self2.on("finish", resolve6);
57101
+ return new Promise2(function(resolve7, reject2) {
57102
+ self2.on("finish", resolve7);
57103
57103
  self2.on("error", reject2);
57104
57104
  });
57105
57105
  };
@@ -57161,7 +57161,7 @@ var require_BufferList6 = __commonJS({
57161
57161
  this.head = this.tail = null;
57162
57162
  this.length = 0;
57163
57163
  };
57164
- BufferList.prototype.join = function join7(s) {
57164
+ BufferList.prototype.join = function join8(s) {
57165
57165
  if (this.length === 0) return "";
57166
57166
  var p = this.head;
57167
57167
  var ret2 = "" + p.data;
@@ -60610,8 +60610,8 @@ var require_extract2 = __commonJS({
60610
60610
  extract.emit("close");
60611
60611
  });
60612
60612
  extract.promise = function() {
60613
- return new Promise2(function(resolve6, reject2) {
60614
- extract.on("close", resolve6);
60613
+ return new Promise2(function(resolve7, reject2) {
60614
+ extract.on("close", resolve7);
60615
60615
  extract.on("error", reject2);
60616
60616
  });
60617
60617
  };
@@ -62122,8 +62122,8 @@ var require_directory = __commonJS({
62122
62122
  return;
62123
62123
  }
62124
62124
  var writer = opts.getWriter ? opts.getWriter({ path: extractPath }) : Writer({ path: extractPath });
62125
- return new Promise2(function(resolve6, reject2) {
62126
- entry.stream(opts.password).on("error", reject2).pipe(writer).on("close", resolve6).on("error", reject2);
62125
+ return new Promise2(function(resolve7, reject2) {
62126
+ entry.stream(opts.password).on("error", reject2).pipe(writer).on("close", resolve7).on("error", reject2);
62127
62127
  });
62128
62128
  }, { concurrency: opts.concurrency > 1 ? opts.concurrency : 1 });
62129
62129
  });
@@ -62190,12 +62190,12 @@ var require_Open = __commonJS({
62190
62190
  return fs4.createReadStream(filename, { start: offset, end: length && offset + length });
62191
62191
  },
62192
62192
  size: function() {
62193
- return new Promise2(function(resolve6, reject2) {
62193
+ return new Promise2(function(resolve7, reject2) {
62194
62194
  fs4.stat(filename, function(err, d) {
62195
62195
  if (err)
62196
62196
  reject2(err);
62197
62197
  else
62198
- resolve6(d.size);
62198
+ resolve7(d.size);
62199
62199
  });
62200
62200
  });
62201
62201
  }
@@ -62216,14 +62216,14 @@ var require_Open = __commonJS({
62216
62216
  return request(options2);
62217
62217
  },
62218
62218
  size: function() {
62219
- return new Promise2(function(resolve6, reject2) {
62219
+ return new Promise2(function(resolve7, reject2) {
62220
62220
  var req = request(params);
62221
62221
  req.on("response", function(d) {
62222
62222
  req.abort();
62223
62223
  if (!d.headers["content-length"])
62224
62224
  reject2(new Error("Missing content length header"));
62225
62225
  else
62226
- resolve6(d.headers["content-length"]);
62226
+ resolve7(d.headers["content-length"]);
62227
62227
  }).on("error", reject2);
62228
62228
  });
62229
62229
  }
@@ -62233,12 +62233,12 @@ var require_Open = __commonJS({
62233
62233
  s3: function(client, params, options) {
62234
62234
  var source2 = {
62235
62235
  size: function() {
62236
- return new Promise2(function(resolve6, reject2) {
62236
+ return new Promise2(function(resolve7, reject2) {
62237
62237
  client.headObject(params, function(err, d) {
62238
62238
  if (err)
62239
62239
  reject2(err);
62240
62240
  else
62241
- resolve6(d.ContentLength);
62241
+ resolve7(d.ContentLength);
62242
62242
  });
62243
62243
  });
62244
62244
  },
@@ -62656,7 +62656,7 @@ var require_iterate_stream = __commonJS({
62656
62656
  const contents = [];
62657
62657
  stream2.on("data", (data) => contents.push(data));
62658
62658
  let resolveStreamEndedPromise;
62659
- const streamEndedPromise = new Promise((resolve6) => resolveStreamEndedPromise = resolve6);
62659
+ const streamEndedPromise = new Promise((resolve7) => resolveStreamEndedPromise = resolve7);
62660
62660
  let ended = false;
62661
62661
  stream2.on("end", () => {
62662
62662
  ended = true;
@@ -62681,13 +62681,13 @@ var require_iterate_stream = __commonJS({
62681
62681
  resolveStreamEndedPromise();
62682
62682
  };
62683
62683
  function once2(eventEmitter, type) {
62684
- return new Promise((resolve6) => {
62684
+ return new Promise((resolve7) => {
62685
62685
  let fired = false;
62686
62686
  const handler = () => {
62687
62687
  if (!fired) {
62688
62688
  fired = true;
62689
62689
  eventEmitter.removeListener(type, handler);
62690
- resolve6();
62690
+ resolve7();
62691
62691
  }
62692
62692
  };
62693
62693
  eventEmitter.addListener(type, handler);
@@ -63214,7 +63214,7 @@ var require_workbook_reader = __commonJS({
63214
63214
  if (this.sharedStrings && this.workbookRels) {
63215
63215
  yield* this._parseWorksheet(iterateStream(entry), sheetNo);
63216
63216
  } else {
63217
- await new Promise((resolve6, reject2) => {
63217
+ await new Promise((resolve7, reject2) => {
63218
63218
  tmp.file((err, path, fd, tempFileCleanupCallback) => {
63219
63219
  if (err) {
63220
63220
  return reject2(err);
@@ -63224,7 +63224,7 @@ var require_workbook_reader = __commonJS({
63224
63224
  tempStream.on("error", reject2);
63225
63225
  entry.pipe(tempStream);
63226
63226
  return tempStream.on("finish", () => {
63227
- return resolve6();
63227
+ return resolve7();
63228
63228
  });
63229
63229
  });
63230
63230
  });
@@ -64603,9 +64603,9 @@ var require_clone2 = __commonJS({
64603
64603
  } else if (_instanceof(parent3, nativeSet)) {
64604
64604
  child = new nativeSet();
64605
64605
  } else if (_instanceof(parent3, nativePromise)) {
64606
- child = new nativePromise(function(resolve6, reject2) {
64606
+ child = new nativePromise(function(resolve7, reject2) {
64607
64607
  parent3.then(function(value) {
64608
- resolve6(_clone(value, depth2 - 1));
64608
+ resolve7(_clone(value, depth2 - 1));
64609
64609
  }, function(err) {
64610
64610
  reject2(_clone(err, depth2 - 1));
64611
64611
  });
@@ -190984,126 +190984,6 @@ var init_script_fonts = __esm({
190984
190984
  import { readFileSync as readFileSync7, existsSync as existsSync5 } from "fs";
190985
190985
  import { spawnSync as spawnSync2 } from "child_process";
190986
190986
 
190987
- // ../core/src/ids.ts
190988
- var ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
190989
- function newId(prefix = "", length = 8) {
190990
- const limit = 256 - 256 % ALPHABET.length;
190991
- let token2 = "";
190992
- while (token2.length < length) {
190993
- const bytes = new Uint8Array(length * 2);
190994
- globalThis.crypto.getRandomValues(bytes);
190995
- for (const b of bytes) {
190996
- if (b >= limit) continue;
190997
- token2 += ALPHABET[b % ALPHABET.length];
190998
- if (token2.length === length) break;
190999
- }
191000
- }
191001
- return prefix ? `${prefix}_${token2}` : token2;
191002
- }
191003
-
191004
- // ../core/src/handle.ts
191005
- function slug(name) {
191006
- const s = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
191007
- return s || "_";
191008
- }
191009
- function fnv32(input) {
191010
- let h = 2166136261;
191011
- for (let i = 0; i < input.length; i++) {
191012
- h ^= input.charCodeAt(i);
191013
- h = Math.imul(h, 16777619);
191014
- }
191015
- return h >>> 0;
191016
- }
191017
- function hash32(input) {
191018
- return fnv32(input).toString(36).padStart(7, "0");
191019
- }
191020
-
191021
- // ../model/src/index.ts
191022
- function walkNodes(nodes, visit) {
191023
- for (const node of nodes) {
191024
- visit(node);
191025
- const children = node.children;
191026
- if (children) walkNodes(children, visit);
191027
- }
191028
- }
191029
- function isContentlessBeat(beat, hasText) {
191030
- if (beat.kind === "gameEvent") return false;
191031
- if (hasText) return false;
191032
- if (beat.gameData && Object.keys(beat.gameData).length > 0) return false;
191033
- if (beat.tags && beat.tags.length > 0) return false;
191034
- return beat.kind === "text" || !beat.character && !beat.direction;
191035
- }
191036
- function gameIdify(text) {
191037
- return text.toLowerCase().replace(/['’]/g, "").replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
191038
- }
191039
- function isValidGameId(gameId) {
191040
- return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(gameId);
191041
- }
191042
- var RESERVED_PROPERTY_NAMES = ["true", "false", "and", "or", "not"];
191043
- function propertyNameify(text) {
191044
- const trimmed = text.trim();
191045
- const deliberateLeading = trimmed.startsWith("_");
191046
- let out = trimmed.toLowerCase().replace(/['\u2019]/g, "").replace(/[^a-z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
191047
- if (out === "") return "";
191048
- if (deliberateLeading || /^[0-9]/.test(out)) out = `_${out}`;
191049
- if (RESERVED_PROPERTY_NAMES.includes(out)) out = `${out}_`;
191050
- return out;
191051
- }
191052
- function isValidPropertyName(name) {
191053
- return /^[a-z_][a-z0-9_]*$/.test(name) && !RESERVED_PROPERTY_NAMES.includes(name);
191054
- }
191055
- function isCaseOnlyPropertyName(name) {
191056
- return !isValidPropertyName(name) && isValidPropertyName(name.toLowerCase());
191057
- }
191058
- function effectiveGameId(entity) {
191059
- const g = entity.gameId?.trim();
191060
- return g ? g : gameIdify(entity.name);
191061
- }
191062
- var DEFAULT_WRITING_STATUSES = [
191063
- { name: "stub", colour: 0 },
191064
- // red
191065
- { name: "draft 1", colour: 1 },
191066
- // rust
191067
- { name: "draft 2", colour: 2 },
191068
- // ochre
191069
- { name: "edited", readyToRecord: true, colour: 4 },
191070
- // green
191071
- { name: "final", readyToShip: true, colour: 9 }
191072
- // purple (violet)
191073
- ];
191074
- var DEFAULT_RECORDING_STATUSES = [
191075
- { name: "missing", colour: 0 },
191076
- // red
191077
- { name: "scratch", colour: 2 },
191078
- // ochre
191079
- { name: "recorded", colour: 4 },
191080
- // green
191081
- { name: "final", colour: 9 }
191082
- // purple
191083
- ];
191084
- var RERECORD_STATUS = "rerecord";
191085
- function deriveRecordingFolders(audioRoot, statuses) {
191086
- const root2 = audioRoot?.trim();
191087
- return statuses.map((s, i) => {
191088
- if (i === 0 || !root2) return { name: s.name };
191089
- return { name: s.name, folder: `${root2}/${gameIdify(s.name)}` };
191090
- });
191091
- }
191092
- var DEFAULT_DOCUMENTATION_CLASSES = [
191093
- { name: "everyone", deliver: "*" },
191094
- // every export, and (like all) the editor
191095
- { name: "vo", deliver: ["vo"] },
191096
- // voice-recording scripts
191097
- { name: "loc", deliver: ["loc"] }
191098
- // localisation handoff
191099
- ];
191100
- var PROJECT_LOCALE_SCENE = "@project";
191101
- function castStringKey(name) {
191102
- return `cast:${name}`;
191103
- }
191104
- var DEFAULT_CAPTION_DELIMITERS = { open: "[", close: "]" };
191105
- var DEFAULT_CAPTION_CHARACTER = "SFX";
191106
-
191107
190987
  // ../../node_modules/json5/dist/index.mjs
191108
190988
  var Space_Separator = /[\u1680\u2000-\u200A\u202F\u205F\u3000]/;
191109
190989
  var ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/;
@@ -192189,11 +192069,1080 @@ var JSON5 = {
192189
192069
  var lib = JSON5;
192190
192070
  var dist_default = lib;
192191
192071
 
192192
- // ../core/src/serialize.ts
192072
+ // ../../node_modules/@wildwinter/toolkit/dist/index.js
192073
+ var ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
192074
+ function newId(prefix = "", length = 8) {
192075
+ const limit = 256 - 256 % ALPHABET.length;
192076
+ let token2 = "";
192077
+ while (token2.length < length) {
192078
+ const bytes = new Uint8Array(length * 2);
192079
+ globalThis.crypto.getRandomValues(bytes);
192080
+ for (const b of bytes) {
192081
+ if (b >= limit) continue;
192082
+ token2 += ALPHABET[b % ALPHABET.length];
192083
+ if (token2.length === length) break;
192084
+ }
192085
+ }
192086
+ return prefix ? `${prefix}_${token2}` : token2;
192087
+ }
192088
+ function fnv32(input) {
192089
+ let h = 2166136261;
192090
+ for (let i = 0; i < input.length; i++) {
192091
+ h ^= input.charCodeAt(i);
192092
+ h = Math.imul(h, 16777619);
192093
+ }
192094
+ return h >>> 0;
192095
+ }
192193
192096
  function parseSource(text) {
192194
192097
  const body = text.charCodeAt(0) === 65279 ? text.slice(1) : text;
192195
192098
  return dist_default.parse(body);
192196
192099
  }
192100
+
192101
+ // ../core/src/handle.ts
192102
+ function slug(name) {
192103
+ const s = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
192104
+ return s || "_";
192105
+ }
192106
+ function hash32(input) {
192107
+ return fnv32(input).toString(36).padStart(7, "0");
192108
+ }
192109
+
192110
+ // ../../../expr/packages/expr/src/parser.ts
192111
+ var ParseError = class extends Error {
192112
+ constructor(message, pos2, source2) {
192113
+ super(`Parse error at position ${pos2}: ${message}
192114
+ ${source2}
192115
+ ${" ".repeat(pos2)}^`);
192116
+ this.pos = pos2;
192117
+ this.source = source2;
192118
+ this.name = "ParseError";
192119
+ }
192120
+ pos;
192121
+ source;
192122
+ };
192123
+ var KEYWORDS = {
192124
+ true: "BOOL",
192125
+ false: "BOOL",
192126
+ and: "AND",
192127
+ or: "OR",
192128
+ not: "NOT"
192129
+ };
192130
+ var KEYWORD_NAMES = Object.freeze(Object.keys(KEYWORDS));
192131
+ function tokenise(src) {
192132
+ const tokens = [];
192133
+ let i = 0;
192134
+ while (i < src.length) {
192135
+ if (/\s/.test(src[i])) {
192136
+ i++;
192137
+ continue;
192138
+ }
192139
+ const pos2 = i;
192140
+ if (src[i] === "@") {
192141
+ const m = src.slice(i).match(/^@([a-z_][a-z0-9_]*)/);
192142
+ if (!m) throw new ParseError(`unexpected character '@'`, pos2, src);
192143
+ tokens.push({ kind: "VAR", value: m[1], pos: pos2 });
192144
+ i += m[0].length;
192145
+ continue;
192146
+ }
192147
+ if (src[i] === '"' || src[i] === "'") {
192148
+ const quote = src[i];
192149
+ let s = "";
192150
+ i++;
192151
+ while (i < src.length && src[i] !== quote) {
192152
+ if (src[i] === "\\" && i + 1 < src.length) {
192153
+ i++;
192154
+ const esc2 = { n: "\n", t: " ", r: "\r", "\\": "\\", "'": "'", '"': '"' };
192155
+ s += esc2[src[i]] ?? src[i];
192156
+ } else {
192157
+ s += src[i];
192158
+ }
192159
+ i++;
192160
+ }
192161
+ if (i >= src.length) throw new ParseError("unterminated string literal", pos2, src);
192162
+ i++;
192163
+ tokens.push({ kind: "STR", value: s, pos: pos2 });
192164
+ continue;
192165
+ }
192166
+ if (/[0-9]/.test(src[i])) {
192167
+ const m = src.slice(i).match(/^[0-9]+(\.[0-9]+)?/);
192168
+ tokens.push({ kind: "NUM", value: m[0], pos: pos2 });
192169
+ i += m[0].length;
192170
+ continue;
192171
+ }
192172
+ const two = src.slice(i, i + 2);
192173
+ if (two === "==") {
192174
+ tokens.push({ kind: "EQ", value: "==", pos: pos2 });
192175
+ i += 2;
192176
+ continue;
192177
+ }
192178
+ if (two === "!=") {
192179
+ tokens.push({ kind: "NEQ", value: "!=", pos: pos2 });
192180
+ i += 2;
192181
+ continue;
192182
+ }
192183
+ if (two === "<>") {
192184
+ tokens.push({ kind: "NEQ", value: "<>", pos: pos2 });
192185
+ i += 2;
192186
+ continue;
192187
+ }
192188
+ if (src[i] === "=" && src[i + 1] !== "=") {
192189
+ tokens.push({ kind: "EQ", value: "=", pos: pos2 });
192190
+ i++;
192191
+ continue;
192192
+ }
192193
+ if (two === ">=") {
192194
+ tokens.push({ kind: "GTE", value: ">=", pos: pos2 });
192195
+ i += 2;
192196
+ continue;
192197
+ }
192198
+ if (two === "<=") {
192199
+ tokens.push({ kind: "LTE", value: "<=", pos: pos2 });
192200
+ i += 2;
192201
+ continue;
192202
+ }
192203
+ if (two === "&&") {
192204
+ tokens.push({ kind: "AND", value: "&&", pos: pos2 });
192205
+ i += 2;
192206
+ continue;
192207
+ }
192208
+ if (two === "||") {
192209
+ tokens.push({ kind: "OR", value: "||", pos: pos2 });
192210
+ i += 2;
192211
+ continue;
192212
+ }
192213
+ const ch = src[i];
192214
+ if (ch === ">") {
192215
+ tokens.push({ kind: "GT", value: ">", pos: pos2 });
192216
+ i++;
192217
+ continue;
192218
+ }
192219
+ if (ch === "<") {
192220
+ tokens.push({ kind: "LT", value: "<", pos: pos2 });
192221
+ i++;
192222
+ continue;
192223
+ }
192224
+ if (ch === "+") {
192225
+ tokens.push({ kind: "PLUS", value: "+", pos: pos2 });
192226
+ i++;
192227
+ continue;
192228
+ }
192229
+ if (ch === "-") {
192230
+ tokens.push({ kind: "MINUS", value: "-", pos: pos2 });
192231
+ i++;
192232
+ continue;
192233
+ }
192234
+ if (ch === "*") {
192235
+ tokens.push({ kind: "STAR", value: "*", pos: pos2 });
192236
+ i++;
192237
+ continue;
192238
+ }
192239
+ if (ch === "/") {
192240
+ tokens.push({ kind: "SLASH", value: "/", pos: pos2 });
192241
+ i++;
192242
+ continue;
192243
+ }
192244
+ if (ch === "(") {
192245
+ tokens.push({ kind: "LPAREN", value: "(", pos: pos2 });
192246
+ i++;
192247
+ continue;
192248
+ }
192249
+ if (ch === ")") {
192250
+ tokens.push({ kind: "RPAREN", value: ")", pos: pos2 });
192251
+ i++;
192252
+ continue;
192253
+ }
192254
+ if (ch === ",") {
192255
+ tokens.push({ kind: "COMMA", value: ",", pos: pos2 });
192256
+ i++;
192257
+ continue;
192258
+ }
192259
+ if (ch === ".") {
192260
+ tokens.push({ kind: "DOT", value: ".", pos: pos2 });
192261
+ i++;
192262
+ continue;
192263
+ }
192264
+ if (ch === "!") {
192265
+ tokens.push({ kind: "NOT", value: "!", pos: pos2 });
192266
+ i++;
192267
+ continue;
192268
+ }
192269
+ if (/[a-zA-Z_]/.test(ch)) {
192270
+ const m = src.slice(i).match(/^[a-zA-Z_][a-zA-Z0-9_]*/);
192271
+ const word = m[0];
192272
+ const kw = KEYWORDS[word];
192273
+ tokens.push({ kind: kw ?? "IDENT", value: word, pos: pos2 });
192274
+ i += word.length;
192275
+ continue;
192276
+ }
192277
+ throw new ParseError(`unexpected character '${ch}'`, pos2, src);
192278
+ }
192279
+ tokens.push({ kind: "EOF", value: "", pos: i });
192280
+ return tokens;
192281
+ }
192282
+ var Parser = class {
192283
+ constructor(tokens, src, dialect) {
192284
+ this.tokens = tokens;
192285
+ this.src = src;
192286
+ this.scopes = new Set(dialect.scopes.map((s) => s.token));
192287
+ this.defaultScope = dialect.defaultScope;
192288
+ this.flagDeltaFns = new Set(
192289
+ Object.entries(dialect.functions).filter(([, def]) => def.flagDeltaArgs).map(([name]) => name)
192290
+ );
192291
+ }
192292
+ tokens;
192293
+ src;
192294
+ pos = 0;
192295
+ scopes;
192296
+ defaultScope;
192297
+ flagDeltaFns;
192298
+ peek() {
192299
+ return this.tokens[this.pos];
192300
+ }
192301
+ advance() {
192302
+ return this.tokens[this.pos++];
192303
+ }
192304
+ check(kind) {
192305
+ return this.peek().kind === kind;
192306
+ }
192307
+ expect(kind) {
192308
+ if (!this.check(kind)) {
192309
+ const tok = this.peek();
192310
+ throw new ParseError(`expected ${kind}, got '${tok.value}'`, tok.pos, this.src);
192311
+ }
192312
+ return this.advance();
192313
+ }
192314
+ parse() {
192315
+ const node = this.parseOr();
192316
+ if (!this.check("EOF")) {
192317
+ const tok = this.peek();
192318
+ throw new ParseError(`unexpected token '${tok.value}'`, tok.pos, this.src);
192319
+ }
192320
+ return node;
192321
+ }
192322
+ parseOr() {
192323
+ let left = this.parseAnd();
192324
+ while (this.check("OR")) {
192325
+ this.advance();
192326
+ const right = this.parseAnd();
192327
+ left = { kind: "binary", op: "or", left, right };
192328
+ }
192329
+ return left;
192330
+ }
192331
+ parseAnd() {
192332
+ let left = this.parseNot();
192333
+ while (this.check("AND")) {
192334
+ this.advance();
192335
+ const right = this.parseNot();
192336
+ left = { kind: "binary", op: "and", left, right };
192337
+ }
192338
+ return left;
192339
+ }
192340
+ parseNot() {
192341
+ if (this.check("NOT")) {
192342
+ this.advance();
192343
+ const operand = this.parseNot();
192344
+ return { kind: "unary", op: "not", operand };
192345
+ }
192346
+ return this.parseComparison();
192347
+ }
192348
+ parseComparison() {
192349
+ const left = this.parseAdditive();
192350
+ const opMap = {
192351
+ EQ: "==",
192352
+ NEQ: "!=",
192353
+ GT: ">",
192354
+ GTE: ">=",
192355
+ LT: "<",
192356
+ LTE: "<="
192357
+ };
192358
+ const op = opMap[this.peek().kind];
192359
+ if (op !== void 0) {
192360
+ this.advance();
192361
+ const right = this.parseAdditive();
192362
+ return { kind: "binary", op, left, right };
192363
+ }
192364
+ return left;
192365
+ }
192366
+ parseAdditive() {
192367
+ let left = this.parseMultiplicative();
192368
+ while (this.check("PLUS") || this.check("MINUS")) {
192369
+ const op = this.advance().kind === "PLUS" ? "+" : "-";
192370
+ const right = this.parseMultiplicative();
192371
+ left = { kind: "binary", op, left, right };
192372
+ }
192373
+ return left;
192374
+ }
192375
+ parseMultiplicative() {
192376
+ let left = this.parseUnaryMinus();
192377
+ while (this.check("STAR") || this.check("SLASH")) {
192378
+ const op = this.advance().kind === "STAR" ? "*" : "/";
192379
+ const right = this.parseUnaryMinus();
192380
+ left = { kind: "binary", op, left, right };
192381
+ }
192382
+ return left;
192383
+ }
192384
+ parseUnaryMinus() {
192385
+ if (this.check("MINUS")) {
192386
+ this.advance();
192387
+ const operand = this.parseUnaryMinus();
192388
+ if (operand.kind === "number") return { kind: "number", value: -operand.value };
192389
+ return { kind: "unary", op: "neg", operand };
192390
+ }
192391
+ return this.parsePrimary();
192392
+ }
192393
+ // Scope-qualified property ref: <scope>.<name> (after a VAR or IDENT token).
192394
+ maybeScopedVar(name) {
192395
+ if (this.scopes.has(name) && this.check("DOT")) {
192396
+ this.advance();
192397
+ const propTok = this.peek();
192398
+ if (propTok.kind !== "IDENT") {
192399
+ throw new ParseError(
192400
+ `expected a property name after '${name}.', got '${propTok.value}'`,
192401
+ propTok.pos,
192402
+ this.src
192403
+ );
192404
+ }
192405
+ this.advance();
192406
+ return { kind: "scopedvar", scope: name, name: propTok.value.toLowerCase() };
192407
+ }
192408
+ return null;
192409
+ }
192410
+ parsePrimary() {
192411
+ const tok = this.peek();
192412
+ if (tok.kind === "BOOL") {
192413
+ this.advance();
192414
+ return { kind: "bool", value: tok.value === "true" };
192415
+ }
192416
+ if (tok.kind === "NUM") {
192417
+ this.advance();
192418
+ return { kind: "number", value: Number(tok.value) };
192419
+ }
192420
+ if (tok.kind === "STR") {
192421
+ this.advance();
192422
+ return { kind: "string", value: tok.value };
192423
+ }
192424
+ if (tok.kind === "VAR") {
192425
+ const name = tok.value;
192426
+ this.advance();
192427
+ const scoped = this.maybeScopedVar(name);
192428
+ if (scoped) return scoped;
192429
+ return { kind: "scopedvar", scope: this.defaultScope, name: name.toLowerCase() };
192430
+ }
192431
+ if (tok.kind === "IDENT") {
192432
+ const name = tok.value;
192433
+ this.advance();
192434
+ const scoped = this.maybeScopedVar(name);
192435
+ if (scoped) return scoped;
192436
+ if (this.check("LPAREN")) {
192437
+ this.advance();
192438
+ const args = [];
192439
+ if (!this.check("RPAREN")) {
192440
+ args.push(this.parseOr());
192441
+ while (this.check("COMMA")) {
192442
+ this.advance();
192443
+ const wantsFlagDelta = this.flagDeltaFns.has(name) && args.length >= 1;
192444
+ if (wantsFlagDelta) {
192445
+ const sign2 = this.check("PLUS") ? "+" : this.check("MINUS") ? "-" : null;
192446
+ if (sign2 === null) {
192447
+ const t = this.peek();
192448
+ throw new ParseError(
192449
+ `${name}: expected +flagName or -flagName, got '${t.value}'`,
192450
+ t.pos,
192451
+ this.src
192452
+ );
192453
+ }
192454
+ this.advance();
192455
+ const flagTok = this.peek();
192456
+ if (flagTok.kind !== "IDENT") {
192457
+ throw new ParseError(
192458
+ `${name}: expected a flag name after '${sign2}', got '${flagTok.value}'`,
192459
+ flagTok.pos,
192460
+ this.src
192461
+ );
192462
+ }
192463
+ this.advance();
192464
+ args.push({ kind: "flagdelta", sign: sign2, name: flagTok.value });
192465
+ } else {
192466
+ args.push(this.parseOr());
192467
+ }
192468
+ }
192469
+ }
192470
+ this.expect("RPAREN");
192471
+ return { kind: "call", name, args };
192472
+ }
192473
+ return { kind: "string", value: name };
192474
+ }
192475
+ if (tok.kind === "LPAREN") {
192476
+ this.advance();
192477
+ const inner = this.parseOr();
192478
+ this.expect("RPAREN");
192479
+ return inner;
192480
+ }
192481
+ if (tok.kind === "EOF") {
192482
+ throw new ParseError("expression is incomplete - expected a value", tok.pos, this.src);
192483
+ }
192484
+ throw new ParseError(`unexpected token '${tok.value}'`, tok.pos, this.src);
192485
+ }
192486
+ };
192487
+ function parse3(source2, dialect) {
192488
+ const tokens = tokenise(source2);
192489
+ return new Parser(tokens, source2, dialect).parse();
192490
+ }
192491
+
192492
+ // ../../../expr/packages/expr/src/ast.ts
192493
+ function serialiseAst(node) {
192494
+ switch (node.kind) {
192495
+ case "bool":
192496
+ return ["b", node.value];
192497
+ case "number":
192498
+ return ["n", node.value];
192499
+ case "string":
192500
+ return ["s", node.value];
192501
+ case "scopedvar":
192502
+ return ["sv", node.scope, node.name];
192503
+ case "unary":
192504
+ return ["u", node.op, serialiseAst(node.operand)];
192505
+ case "binary":
192506
+ return ["bin", node.op, serialiseAst(node.left), serialiseAst(node.right)];
192507
+ case "call":
192508
+ return ["call", node.name, ...node.args.map(serialiseAst)];
192509
+ case "flagdelta":
192510
+ return ["fd", node.sign, node.name];
192511
+ }
192512
+ }
192513
+ function deserialiseAst(node) {
192514
+ switch (node[0]) {
192515
+ case "b":
192516
+ return { kind: "bool", value: node[1] };
192517
+ case "n":
192518
+ return { kind: "number", value: node[1] };
192519
+ case "s":
192520
+ return { kind: "string", value: node[1] };
192521
+ case "sv":
192522
+ return { kind: "scopedvar", scope: node[1], name: node[2] };
192523
+ case "u":
192524
+ return { kind: "unary", op: node[1], operand: deserialiseAst(node[2]) };
192525
+ case "bin":
192526
+ return { kind: "binary", op: node[1], left: deserialiseAst(node[2]), right: deserialiseAst(node[3]) };
192527
+ case "call": {
192528
+ const args = node.slice(2).map(deserialiseAst);
192529
+ return { kind: "call", name: node[1], args };
192530
+ }
192531
+ case "fd":
192532
+ return { kind: "flagdelta", sign: node[1], name: node[2] };
192533
+ }
192534
+ }
192535
+
192536
+ // ../../../expr/packages/expr/src/evaluate.ts
192537
+ var EvalError2 = class extends Error {
192538
+ constructor(message) {
192539
+ super(message);
192540
+ this.name = "EvalError";
192541
+ }
192542
+ };
192543
+ function evaluate(node, ctx, dialect) {
192544
+ const missingPolicy = new Map(
192545
+ dialect.scopes.map((s) => [s.token, s.missing ?? "false"])
192546
+ );
192547
+ const rec = (n) => {
192548
+ switch (n.kind) {
192549
+ case "bool":
192550
+ return n.value;
192551
+ case "number":
192552
+ return n.value;
192553
+ case "string":
192554
+ return n.value;
192555
+ case "scopedvar": {
192556
+ const scope = ctx.scopes[n.scope];
192557
+ if (scope === void 0) {
192558
+ return false;
192559
+ }
192560
+ const val = typeof scope.get === "function" ? scope.get(n.name) : scope[n.name];
192561
+ if (val === void 0) {
192562
+ if (missingPolicy.get(n.scope) === "throw") {
192563
+ throw new EvalError2(`@${n.scope}.${n.name} is not declared on the current ${n.scope}.`);
192564
+ }
192565
+ return false;
192566
+ }
192567
+ return val;
192568
+ }
192569
+ case "call": {
192570
+ if (n.name === "advance" && !dialect.functions[n.name]) {
192571
+ const arg = n.args[0];
192572
+ if (n.args.length !== 1 || arg === void 0) {
192573
+ throw new EvalError2(`advance() takes exactly 1 argument, got ${n.args.length}`);
192574
+ }
192575
+ const ladder = ladderOf(arg, ctx);
192576
+ if (ladder === void 0) {
192577
+ throw new EvalError2("advance() needs a quality reference (@scope.name of a quality property)");
192578
+ }
192579
+ const current = stageIndex(rec(arg), ladder, "advance");
192580
+ return ladder[Math.min(current + 1, ladder.length - 1)];
192581
+ }
192582
+ const def = dialect.functions[n.name];
192583
+ if (!def) throw new EvalError2(`unknown function '${n.name}'`);
192584
+ return def.eval(n.args, { evaluate: rec, ctx });
192585
+ }
192586
+ case "flagdelta":
192587
+ throw new EvalError2("flagdelta node is only valid as an argument to a flag-delta function");
192588
+ case "unary": {
192589
+ if (n.op === "not") {
192590
+ const val2 = rec(n.operand);
192591
+ if (typeof val2 !== "boolean") throw new EvalError2(`'not' requires a boolean operand, got ${typeof val2}`);
192592
+ return !val2;
192593
+ }
192594
+ const val = rec(n.operand);
192595
+ if (typeof val !== "number") throw new EvalError2(`unary '-' requires a numeric operand, got ${typeof val}`);
192596
+ return -val;
192597
+ }
192598
+ case "binary": {
192599
+ if (n.op === "and") {
192600
+ const l2 = rec(n.left);
192601
+ if (typeof l2 !== "boolean") throw new EvalError2(`'and' requires boolean operands, left is ${typeof l2}`);
192602
+ if (!l2) return false;
192603
+ const r = rec(n.right);
192604
+ if (typeof r !== "boolean") throw new EvalError2(`'and' requires boolean operands, right is ${typeof r}`);
192605
+ return r;
192606
+ }
192607
+ if (n.op === "or") {
192608
+ const l2 = rec(n.left);
192609
+ if (typeof l2 !== "boolean") throw new EvalError2(`'or' requires boolean operands, left is ${typeof l2}`);
192610
+ if (l2) return true;
192611
+ const r = rec(n.right);
192612
+ if (typeof r !== "boolean") throw new EvalError2(`'or' requires boolean operands, right is ${typeof r}`);
192613
+ return r;
192614
+ }
192615
+ const left = rec(n.left);
192616
+ const right = rec(n.right);
192617
+ const lLadder = ladderOf(n.left, ctx);
192618
+ const rLadder = ladderOf(n.right, ctx);
192619
+ const ladder = lLadder ?? rLadder;
192620
+ if (ladder !== void 0) {
192621
+ if (lLadder && rLadder && !sameLadder(lLadder, rLadder)) {
192622
+ if (n.op === ">" || n.op === ">=" || n.op === "<" || n.op === "<=") {
192623
+ throw new EvalError2(`'${n.op}' compares two different qualities, whose stage orders are unrelated`);
192624
+ }
192625
+ }
192626
+ switch (n.op) {
192627
+ case ">":
192628
+ return stageIndex(left, ladder, ">") > stageIndex(right, ladder, ">");
192629
+ case ">=":
192630
+ return stageIndex(left, ladder, ">=") >= stageIndex(right, ladder, ">=");
192631
+ case "<":
192632
+ return stageIndex(left, ladder, "<") < stageIndex(right, ladder, "<");
192633
+ case "<=":
192634
+ return stageIndex(left, ladder, "<=") <= stageIndex(right, ladder, "<=");
192635
+ case "+":
192636
+ case "-":
192637
+ case "*":
192638
+ case "/":
192639
+ throw new EvalError2(`'${n.op}' cannot be applied to a quality - a stage is a position, not a number; use advance() to move it`);
192640
+ default:
192641
+ break;
192642
+ }
192643
+ }
192644
+ switch (n.op) {
192645
+ case "==":
192646
+ return valueEquals(left, right);
192647
+ case "!=":
192648
+ return !valueEquals(left, right);
192649
+ case ">":
192650
+ assertNumbers(left, right, ">");
192651
+ return left > right;
192652
+ case ">=":
192653
+ assertNumbers(left, right, ">=");
192654
+ return left >= right;
192655
+ case "<":
192656
+ assertNumbers(left, right, "<");
192657
+ return left < right;
192658
+ case "<=":
192659
+ assertNumbers(left, right, "<=");
192660
+ return left <= right;
192661
+ case "+":
192662
+ if (typeof left === "number" && typeof right === "number") return left + right;
192663
+ if (typeof left === "string" && typeof right === "string") return left + right;
192664
+ throw new EvalError2(`'+' requires two numbers or two strings, got ${typeof left} and ${typeof right}`);
192665
+ case "-":
192666
+ assertNumbers(left, right, "-");
192667
+ return left - right;
192668
+ case "*":
192669
+ assertNumbers(left, right, "*");
192670
+ return left * right;
192671
+ case "/":
192672
+ assertNumbers(left, right, "/");
192673
+ if (right === 0) throw new EvalError2("division by zero");
192674
+ return left / right;
192675
+ }
192676
+ }
192677
+ }
192678
+ };
192679
+ return rec(node);
192680
+ }
192681
+ function valueEquals(a, b) {
192682
+ if (Array.isArray(a) || Array.isArray(b)) {
192683
+ if (!Array.isArray(a) || !Array.isArray(b)) return false;
192684
+ if (a.length !== b.length) return false;
192685
+ const x = [...a].sort();
192686
+ const y = [...b].sort();
192687
+ for (let i = 0; i < x.length; i++) if (x[i] !== y[i]) return false;
192688
+ return true;
192689
+ }
192690
+ return a === b;
192691
+ }
192692
+ function assertNumbers(l2, r, op) {
192693
+ if (typeof l2 !== "number" || typeof r !== "number") {
192694
+ throw new EvalError2(`'${op}' requires numeric operands, got ${typeof l2} and ${typeof r}`);
192695
+ }
192696
+ }
192697
+ function ladderOf(node, ctx) {
192698
+ if (node.kind !== "scopedvar" || ctx.qualities === void 0) return void 0;
192699
+ return ctx.qualities(node.scope, node.name);
192700
+ }
192701
+ function stageIndex(value, ladder, op) {
192702
+ if (typeof value !== "string") {
192703
+ throw new EvalError2(`'${op}' on a quality compares stages, got ${typeof value}`);
192704
+ }
192705
+ const i = ladder.indexOf(value);
192706
+ if (i < 0) throw new EvalError2(`"${value}" is not a stage of this quality (stages: ${ladder.join(", ")})`);
192707
+ return i;
192708
+ }
192709
+ var sameLadder = (a, b) => a.length === b.length && a.every((x, i) => x === b[i]);
192710
+
192711
+ // ../../../expr/packages/expr/src/prng.ts
192712
+ function toUint32(seed) {
192713
+ if (Number.isNaN(seed) || !Number.isFinite(seed)) return 0;
192714
+ const modded = Math.trunc(seed) % 4294967296;
192715
+ return modded < 0 ? modded + 4294967296 : modded;
192716
+ }
192717
+ function makePrng(seed) {
192718
+ let s = toUint32(seed);
192719
+ return {
192720
+ next() {
192721
+ s = s + 1831565813 >>> 0;
192722
+ let t = Math.imul(s ^ s >>> 15, 1 | s);
192723
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
192724
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
192725
+ },
192726
+ state() {
192727
+ return s;
192728
+ }
192729
+ };
192730
+ }
192731
+
192732
+ // ../../../expr/packages/expr/src/latches.ts
192733
+ var scopedRef = (ast) => Array.isArray(ast) && ast[0] === "sv" ? `@${String(ast[1])}.${String(ast[2])}` : void 0;
192734
+ function latchOf(ast, owner, keyOf2) {
192735
+ const direct = scopedRef(ast);
192736
+ if (direct !== void 0) return keyOf2(direct, owner);
192737
+ if (!Array.isArray(ast)) return void 0;
192738
+ if (ast[0] === "bin" && ast[1] === "==") {
192739
+ const [, , l2, r] = ast;
192740
+ for (const [a, b] of [[l2, r], [r, l2]]) {
192741
+ const ref = scopedRef(a);
192742
+ if (ref !== void 0 && Array.isArray(b) && b[0] === "b" && b[1] === true) return keyOf2(ref, owner);
192743
+ }
192744
+ return void 0;
192745
+ }
192746
+ if (ast[0] === "call" && ast[1] === "check_flags") {
192747
+ const ref = scopedRef(ast[2]);
192748
+ const args = ast.slice(3);
192749
+ if (ref === void 0 || args.length !== 1) return void 0;
192750
+ const arg = args[0];
192751
+ if (Array.isArray(arg) && arg[0] === "fd" && arg[1] === "+") {
192752
+ return `${keyOf2(ref, owner)}:${String(arg[2])}`;
192753
+ }
192754
+ }
192755
+ return void 0;
192756
+ }
192757
+ function disjuncts(ast) {
192758
+ if (Array.isArray(ast) && ast[0] === "bin" && ast[1] === "or") {
192759
+ const [, , l2, r] = ast;
192760
+ return [...disjuncts(l2), ...disjuncts(r)];
192761
+ }
192762
+ return [ast];
192763
+ }
192764
+ function terms(ast, owner, keyOf2, negated = false, into = []) {
192765
+ const latch = latchOf(ast, owner, keyOf2);
192766
+ if (latch !== void 0) {
192767
+ into.push({ key: latch, negated });
192768
+ return into;
192769
+ }
192770
+ if (!Array.isArray(ast)) return into;
192771
+ if (ast[0] === "u" && ast[1] === "not") return terms(ast[2], owner, keyOf2, !negated, into);
192772
+ if (ast[0] === "bin" && ast[1] === "and" && !negated) {
192773
+ terms(ast[2], owner, keyOf2, false, into);
192774
+ terms(ast[3], owner, keyOf2, false, into);
192775
+ }
192776
+ return into;
192777
+ }
192778
+
192779
+ // ../../../expr/packages/expr/src/names.ts
192780
+ var RESERVED_PROPERTY_NAMES = KEYWORD_NAMES;
192781
+ function propertyNameify(text) {
192782
+ const trimmed = text.trim();
192783
+ const deliberateLeading = trimmed.startsWith("_");
192784
+ let out = trimmed.toLowerCase().replace(/['’]/g, "").replace(/[^a-z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
192785
+ if (out === "") return "";
192786
+ if (deliberateLeading || /^[0-9]/.test(out)) out = `_${out}`;
192787
+ if (RESERVED_PROPERTY_NAMES.includes(out)) out = `${out}_`;
192788
+ return out;
192789
+ }
192790
+ function isValidPropertyName(name) {
192791
+ return /^[a-z_][a-z0-9_]*$/.test(name) && !RESERVED_PROPERTY_NAMES.includes(name);
192792
+ }
192793
+ function isCaseOnlyPropertyName(name) {
192794
+ return !isValidPropertyName(name) && isValidPropertyName(name.toLowerCase());
192795
+ }
192796
+
192797
+ // ../../../expr/packages/expr/src/validate.ts
192798
+ function validateExpressionAst(node, schema, dialect) {
192799
+ const issues = [];
192800
+ walkValidate(node, schema, dialect, [], issues);
192801
+ return finaliseResult(issues);
192802
+ }
192803
+ function validateExpr(node, schema, dialect) {
192804
+ return validateExpressionAst(node, schema, dialect).issues;
192805
+ }
192806
+ function finaliseResult(issues) {
192807
+ const hasError = issues.some((i) => i.severity === "error");
192808
+ const summary = issues.map((i) => i.message).join("; ");
192809
+ return { ok: !hasError, issues, summary };
192810
+ }
192811
+ function walkValidate(node, schema, dialect, path, issues) {
192812
+ switch (node.kind) {
192813
+ case "bool":
192814
+ case "number":
192815
+ case "string":
192816
+ case "flagdelta":
192817
+ return;
192818
+ case "scopedvar": {
192819
+ const scopeMap = schema.properties.get(node.scope);
192820
+ if (scopeMap && !scopeMap.has(node.name)) {
192821
+ const isDefault = node.scope === dialect.defaultScope;
192822
+ issues.push({
192823
+ path,
192824
+ kind: isDefault ? "unresolved-property" : "unresolved-scoped-property",
192825
+ severity: "error",
192826
+ message: isDefault ? `unresolved property reference '@${node.name}'` : `unresolved ${node.scope} property reference '@${node.scope}.${node.name}'`,
192827
+ reference: isDefault ? node.name : `${node.scope}.${node.name}`
192828
+ });
192829
+ }
192830
+ return;
192831
+ }
192832
+ case "call": {
192833
+ if (node.name === "advance" && !dialect.functions[node.name]) {
192834
+ if (node.args.length !== 1) {
192835
+ issues.push({ path, kind: "wrong-arg-count", severity: "error", message: `advance() takes exactly 1 argument, got ${node.args.length}` });
192836
+ }
192837
+ const arg = node.args[0];
192838
+ if (arg) {
192839
+ walkValidate(arg, schema, dialect, [...path, "args", 0], issues);
192840
+ if (stagesOf(arg, schema) === void 0 && typeOf(arg, schema, dialect) !== "unknown") {
192841
+ issues.push({
192842
+ path: [...path, "args", 0],
192843
+ kind: "wrong-arg-type",
192844
+ severity: "error",
192845
+ message: "advance() needs a quality reference (@scope.name of a quality property)"
192846
+ });
192847
+ }
192848
+ }
192849
+ return;
192850
+ }
192851
+ const def = dialect.functions[node.name];
192852
+ if (!def) {
192853
+ issues.push({ path, kind: "unknown-function", severity: "error", message: `unknown function '${node.name}'` });
192854
+ return;
192855
+ }
192856
+ if (node.args.length < def.minArgs) {
192857
+ issues.push({
192858
+ path,
192859
+ kind: "wrong-arg-count",
192860
+ severity: "error",
192861
+ message: `${node.name}() requires at least ${def.minArgs} argument(s), got ${node.args.length}`
192862
+ });
192863
+ }
192864
+ if (def.maxArgs !== void 0 && node.args.length > def.maxArgs) {
192865
+ issues.push({
192866
+ path,
192867
+ kind: "wrong-arg-count",
192868
+ severity: "error",
192869
+ message: `${node.name}() takes at most ${def.maxArgs} argument(s), got ${node.args.length}`
192870
+ });
192871
+ }
192872
+ for (let i = 0; i < node.args.length; i++) {
192873
+ walkValidate(node.args[i], schema, dialect, [...path, "args", i], issues);
192874
+ }
192875
+ if (def.validate) {
192876
+ def.validate(node.args, {
192877
+ schema,
192878
+ path,
192879
+ defaultScope: dialect.defaultScope,
192880
+ report: (issue) => issues.push(issue)
192881
+ });
192882
+ }
192883
+ return;
192884
+ }
192885
+ case "unary": {
192886
+ walkValidate(node.operand, schema, dialect, [...path, "operand"], issues);
192887
+ checkUnaryOperandType(node.op, node.operand, schema, dialect, [...path, "operand"], issues);
192888
+ return;
192889
+ }
192890
+ case "binary": {
192891
+ walkValidate(node.left, schema, dialect, [...path, "left"], issues);
192892
+ walkValidate(node.right, schema, dialect, [...path, "right"], issues);
192893
+ checkBinaryOperandTypes(node.op, node.left, node.right, schema, dialect, path, issues);
192894
+ if (node.op === "/" && node.right.kind === "number" && node.right.value === 0) {
192895
+ issues.push({
192896
+ path: [...path, "right"],
192897
+ kind: "division-by-zero",
192898
+ severity: "error",
192899
+ message: "division by zero - pick a non-zero divisor"
192900
+ });
192901
+ }
192902
+ if (node.op === "==" || node.op === "!=") {
192903
+ const left = node.left, right = node.right;
192904
+ let propNode = null;
192905
+ let strNode = null;
192906
+ let strSide = null;
192907
+ if (left.kind === "scopedvar" && right.kind === "string") {
192908
+ propNode = left;
192909
+ strNode = right;
192910
+ strSide = "right";
192911
+ } else if (right.kind === "scopedvar" && left.kind === "string") {
192912
+ propNode = right;
192913
+ strNode = left;
192914
+ strSide = "left";
192915
+ }
192916
+ if (propNode && strNode && strSide) {
192917
+ const meta = schema.properties.get(propNode.scope)?.get(propNode.name);
192918
+ if (meta?.type === "enum" && meta.enumValues && !meta.enumValues.includes(strNode.value)) {
192919
+ issues.push({
192920
+ path: [...path, strSide],
192921
+ kind: "unknown-enum-value",
192922
+ severity: "error",
192923
+ message: `'${strNode.value}' is not a valid value for this property - expected one of: ${meta.enumValues.join(", ")}`,
192924
+ reference: strNode.value
192925
+ });
192926
+ }
192927
+ }
192928
+ }
192929
+ return;
192930
+ }
192931
+ }
192932
+ }
192933
+ function inferredFromPropertyType(t) {
192934
+ if (t === "boolean") return "boolean";
192935
+ if (t === "number") return "number";
192936
+ if (t === "string" || t === "enum") return "string";
192937
+ if (t === "flags") return "flags";
192938
+ if (t === "quality") return "quality";
192939
+ return "unknown";
192940
+ }
192941
+ function inferredFromReturn(t) {
192942
+ return t;
192943
+ }
192944
+ function stagesOf(node, schema) {
192945
+ if (node.kind !== "scopedvar") return void 0;
192946
+ const meta = schema.properties.get(node.scope)?.get(node.name);
192947
+ return meta?.type === "quality" ? meta.stages : void 0;
192948
+ }
192949
+ function typeOf(node, schema, dialect) {
192950
+ switch (node.kind) {
192951
+ case "bool":
192952
+ return "boolean";
192953
+ case "number":
192954
+ return "number";
192955
+ case "string":
192956
+ return "string";
192957
+ case "flagdelta":
192958
+ return "unknown";
192959
+ case "scopedvar": {
192960
+ const meta = schema.properties.get(node.scope)?.get(node.name);
192961
+ return meta ? inferredFromPropertyType(meta.type) : "unknown";
192962
+ }
192963
+ case "call": {
192964
+ if (node.name === "advance") return "quality";
192965
+ const def = dialect.functions[node.name];
192966
+ return def ? inferredFromReturn(def.returnType) : "unknown";
192967
+ }
192968
+ case "unary":
192969
+ return node.op === "not" ? "boolean" : "number";
192970
+ case "binary":
192971
+ switch (node.op) {
192972
+ case "+":
192973
+ case "-":
192974
+ case "*":
192975
+ case "/":
192976
+ return "number";
192977
+ case "==":
192978
+ case "!=":
192979
+ case ">":
192980
+ case "<":
192981
+ case ">=":
192982
+ case "<=":
192983
+ case "and":
192984
+ case "or":
192985
+ return "boolean";
192986
+ }
192987
+ }
192988
+ }
192989
+ function describeType(t) {
192990
+ return t === "unknown" ? "unknown type" : t;
192991
+ }
192992
+ function checkBinaryOperandTypes(op, left, right, schema, dialect, path, issues) {
192993
+ const lt = typeOf(left, schema, dialect);
192994
+ const rt = typeOf(right, schema, dialect);
192995
+ const ordering = op === ">" || op === "<" || op === ">=" || op === "<=";
192996
+ if (lt === "quality" || rt === "quality") {
192997
+ if (ordering || op === "==" || op === "!=") {
192998
+ const ls = stagesOf(left, schema);
192999
+ const rs = stagesOf(right, schema);
193000
+ if (ls && rs) {
193001
+ if (ls.join("\0") !== rs.join("\0")) {
193002
+ issues.push({ path, kind: "operand-type-mismatch", severity: "error", message: `'${op}' compares two different qualities, whose stages are unrelated` });
193003
+ }
193004
+ return;
193005
+ }
193006
+ const ladder = ls ?? rs;
193007
+ const other = ls ? right : left;
193008
+ const otherSide = ls ? "right" : "left";
193009
+ if (other.kind === "string") {
193010
+ if (ladder && !ladder.includes(other.value)) {
193011
+ issues.push({
193012
+ path: [...path, otherSide],
193013
+ kind: "unknown-stage",
193014
+ severity: "error",
193015
+ message: `'${other.value}' is not a stage of this quality - expected one of: ${ladder.join(", ")}`,
193016
+ reference: other.value
193017
+ });
193018
+ }
193019
+ return;
193020
+ }
193021
+ const ot = ls ? rt : lt;
193022
+ if (ot !== "unknown" && ot !== "quality") {
193023
+ issues.push({
193024
+ path: [...path, otherSide],
193025
+ kind: "operand-type-mismatch",
193026
+ severity: "error",
193027
+ message: `'${op}' on a quality compares stages, got ${describeType(ot)} on the ${otherSide}`
193028
+ });
193029
+ }
193030
+ return;
193031
+ }
193032
+ if (op === "+" || op === "-" || op === "*" || op === "/") {
193033
+ issues.push({
193034
+ path,
193035
+ kind: "operand-type-mismatch",
193036
+ severity: "error",
193037
+ message: `'${op}' cannot be applied to a quality - a stage is a position, not a number; use advance() to move it`
193038
+ });
193039
+ return;
193040
+ }
193041
+ }
193042
+ if (op === "+" || op === "-" || op === "*" || op === "/" || ordering) {
193043
+ if (lt !== "unknown" && lt !== "number")
193044
+ issues.push({ path: [...path, "left"], kind: "operand-type-mismatch", severity: "error", message: `'${op}' requires a number on the left, got ${describeType(lt)}` });
193045
+ if (rt !== "unknown" && rt !== "number")
193046
+ issues.push({ path: [...path, "right"], kind: "operand-type-mismatch", severity: "error", message: `'${op}' requires a number on the right, got ${describeType(rt)}` });
193047
+ return;
193048
+ }
193049
+ if (op === "and" || op === "or") {
193050
+ if (lt !== "unknown" && lt !== "boolean")
193051
+ issues.push({ path: [...path, "left"], kind: "operand-type-mismatch", severity: "error", message: `'${op}' requires a boolean on the left, got ${describeType(lt)}` });
193052
+ if (rt !== "unknown" && rt !== "boolean")
193053
+ issues.push({ path: [...path, "right"], kind: "operand-type-mismatch", severity: "error", message: `'${op}' requires a boolean on the right, got ${describeType(rt)}` });
193054
+ return;
193055
+ }
193056
+ if (op === "==" || op === "!=") {
193057
+ if (lt !== "unknown" && rt !== "unknown" && lt !== rt)
193058
+ issues.push({ path, kind: "operand-type-mismatch", severity: "error", message: `'${op}' compares ${describeType(lt)} with ${describeType(rt)}; the values can never be equal` });
193059
+ }
193060
+ }
193061
+ function checkUnaryOperandType(op, operand, schema, dialect, path, issues) {
193062
+ const t = typeOf(operand, schema, dialect);
193063
+ if (t === "unknown") return;
193064
+ if (op === "not" && t !== "boolean")
193065
+ issues.push({ path, kind: "operand-type-mismatch", severity: "error", message: `'not' requires a boolean operand, got ${describeType(t)}` });
193066
+ if (op === "neg" && t !== "number")
193067
+ issues.push({ path, kind: "operand-type-mismatch", severity: "error", message: `unary '-' requires a number, got ${describeType(t)}` });
193068
+ }
193069
+
193070
+ // ../../../expr/packages/expr/src/index.ts
193071
+ function compile(src, dialect) {
193072
+ return { src, ast: serialiseAst(parse3(src, dialect)) };
193073
+ }
193074
+
193075
+ // ../model/src/index.ts
193076
+ function walkNodes(nodes, visit) {
193077
+ for (const node of nodes) {
193078
+ visit(node);
193079
+ const children = node.children;
193080
+ if (children) walkNodes(children, visit);
193081
+ }
193082
+ }
193083
+ function isContentlessBeat(beat, hasText) {
193084
+ if (beat.kind === "gameEvent") return false;
193085
+ if (hasText) return false;
193086
+ if (beat.gameData && Object.keys(beat.gameData).length > 0) return false;
193087
+ if (beat.tags && beat.tags.length > 0) return false;
193088
+ return beat.kind === "text" || !beat.character && !beat.direction;
193089
+ }
193090
+ function gameIdify(text) {
193091
+ return text.toLowerCase().replace(/['’]/g, "").replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
193092
+ }
193093
+ function isValidGameId(gameId) {
193094
+ return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(gameId);
193095
+ }
193096
+ function effectiveGameId(entity) {
193097
+ const g = entity.gameId?.trim();
193098
+ return g ? g : gameIdify(entity.name);
193099
+ }
193100
+ var DEFAULT_WRITING_STATUSES = [
193101
+ { name: "stub", colour: 0 },
193102
+ // red
193103
+ { name: "draft 1", colour: 1 },
193104
+ // rust
193105
+ { name: "draft 2", colour: 2 },
193106
+ // ochre
193107
+ { name: "edited", readyToRecord: true, colour: 4 },
193108
+ // green
193109
+ { name: "final", readyToShip: true, colour: 9 }
193110
+ // purple (violet)
193111
+ ];
193112
+ var DEFAULT_RECORDING_STATUSES = [
193113
+ { name: "missing", colour: 0 },
193114
+ // red
193115
+ { name: "scratch", colour: 2 },
193116
+ // ochre
193117
+ { name: "recorded", colour: 4 },
193118
+ // green
193119
+ { name: "final", colour: 9 }
193120
+ // purple
193121
+ ];
193122
+ var RERECORD_STATUS = "rerecord";
193123
+ function deriveRecordingFolders(audioRoot, statuses) {
193124
+ const root2 = audioRoot?.trim();
193125
+ return statuses.map((s, i) => {
193126
+ if (i === 0 || !root2) return { name: s.name };
193127
+ return { name: s.name, folder: `${root2}/${gameIdify(s.name)}` };
193128
+ });
193129
+ }
193130
+ var DEFAULT_DOCUMENTATION_CLASSES = [
193131
+ { name: "everyone", deliver: "*" },
193132
+ // every export, and (like all) the editor
193133
+ { name: "vo", deliver: ["vo"] },
193134
+ // voice-recording scripts
193135
+ { name: "loc", deliver: ["loc"] }
193136
+ // localisation handoff
193137
+ ];
193138
+ var PROJECT_LOCALE_SCENE = "@project";
193139
+ function castStringKey(name) {
193140
+ return `cast:${name}`;
193141
+ }
193142
+ var DEFAULT_CAPTION_DELIMITERS = { open: "[", close: "]" };
193143
+ var DEFAULT_CAPTION_CHARACTER = "SFX";
193144
+
193145
+ // ../core/src/serialize.ts
192197
193146
  function canonicalStringify(value, opts) {
192198
193147
  return write(value, "", opts?.trailingComma ?? true) + "\n";
192199
193148
  }
@@ -192793,7 +193742,7 @@ function merge3(base, ours, theirs, id, path, conflicts) {
192793
193742
  conflicts.push({ id, path, base, ours, theirs, kind: deletedKind(base, ours, theirs) });
192794
193743
  return ours;
192795
193744
  }
192796
- function mergeMap(base, ours, theirs, prefix, conflicts, resolve6) {
193745
+ function mergeMap(base, ours, theirs, prefix, conflicts, resolve7) {
192797
193746
  const out = {};
192798
193747
  for (const k of /* @__PURE__ */ new Set([...Object.keys(base), ...Object.keys(ours), ...Object.keys(theirs)])) {
192799
193748
  const b = base[k], o = ours[k], t = theirs[k];
@@ -192802,7 +193751,7 @@ function mergeMap(base, ours, theirs, prefix, conflicts, resolve6) {
192802
193751
  else if (eq(b, o)) v = t;
192803
193752
  else if (eq(b, t)) v = o;
192804
193753
  else {
192805
- const r = resolve6?.(k, b, o, t);
193754
+ const r = resolve7?.(k, b, o, t);
192806
193755
  if (r && r.resolved) v = r.value;
192807
193756
  else {
192808
193757
  conflicts.push({ id: k, path: `${prefix}.${k}`, base: b, ours: o, theirs: t, kind: r ? r.kind : deletedKind(b, o, t) });
@@ -193090,882 +194039,6 @@ function checkDuplicateIds(root2, conflicts) {
193090
194039
  var idMap = (nodes) => new Map(nodes.filter((n) => n.id).map((n) => [n.id, n]));
193091
194040
  var arrEq = (a, b) => a.length === b.length && a.every((x, i) => x === b[i]);
193092
194041
 
193093
- // ../../../expr/packages/expr/src/parser.ts
193094
- var ParseError = class extends Error {
193095
- constructor(message, pos2, source2) {
193096
- super(`Parse error at position ${pos2}: ${message}
193097
- ${source2}
193098
- ${" ".repeat(pos2)}^`);
193099
- this.pos = pos2;
193100
- this.source = source2;
193101
- this.name = "ParseError";
193102
- }
193103
- pos;
193104
- source;
193105
- };
193106
- var KEYWORDS = {
193107
- true: "BOOL",
193108
- false: "BOOL",
193109
- and: "AND",
193110
- or: "OR",
193111
- not: "NOT"
193112
- };
193113
- function tokenise(src) {
193114
- const tokens = [];
193115
- let i = 0;
193116
- while (i < src.length) {
193117
- if (/\s/.test(src[i])) {
193118
- i++;
193119
- continue;
193120
- }
193121
- const pos2 = i;
193122
- if (src[i] === "@") {
193123
- const m = src.slice(i).match(/^@([a-z_][a-z0-9_]*)/);
193124
- if (!m) throw new ParseError(`unexpected character '@'`, pos2, src);
193125
- tokens.push({ kind: "VAR", value: m[1], pos: pos2 });
193126
- i += m[0].length;
193127
- continue;
193128
- }
193129
- if (src[i] === '"' || src[i] === "'") {
193130
- const quote = src[i];
193131
- let s = "";
193132
- i++;
193133
- while (i < src.length && src[i] !== quote) {
193134
- if (src[i] === "\\" && i + 1 < src.length) {
193135
- i++;
193136
- const esc2 = { n: "\n", t: " ", r: "\r", "\\": "\\", "'": "'", '"': '"' };
193137
- s += esc2[src[i]] ?? src[i];
193138
- } else {
193139
- s += src[i];
193140
- }
193141
- i++;
193142
- }
193143
- if (i >= src.length) throw new ParseError("unterminated string literal", pos2, src);
193144
- i++;
193145
- tokens.push({ kind: "STR", value: s, pos: pos2 });
193146
- continue;
193147
- }
193148
- if (/[0-9]/.test(src[i])) {
193149
- const m = src.slice(i).match(/^[0-9]+(\.[0-9]+)?/);
193150
- tokens.push({ kind: "NUM", value: m[0], pos: pos2 });
193151
- i += m[0].length;
193152
- continue;
193153
- }
193154
- const two = src.slice(i, i + 2);
193155
- if (two === "==") {
193156
- tokens.push({ kind: "EQ", value: "==", pos: pos2 });
193157
- i += 2;
193158
- continue;
193159
- }
193160
- if (two === "!=") {
193161
- tokens.push({ kind: "NEQ", value: "!=", pos: pos2 });
193162
- i += 2;
193163
- continue;
193164
- }
193165
- if (two === "<>") {
193166
- tokens.push({ kind: "NEQ", value: "<>", pos: pos2 });
193167
- i += 2;
193168
- continue;
193169
- }
193170
- if (src[i] === "=" && src[i + 1] !== "=") {
193171
- tokens.push({ kind: "EQ", value: "=", pos: pos2 });
193172
- i++;
193173
- continue;
193174
- }
193175
- if (two === ">=") {
193176
- tokens.push({ kind: "GTE", value: ">=", pos: pos2 });
193177
- i += 2;
193178
- continue;
193179
- }
193180
- if (two === "<=") {
193181
- tokens.push({ kind: "LTE", value: "<=", pos: pos2 });
193182
- i += 2;
193183
- continue;
193184
- }
193185
- if (two === "&&") {
193186
- tokens.push({ kind: "AND", value: "&&", pos: pos2 });
193187
- i += 2;
193188
- continue;
193189
- }
193190
- if (two === "||") {
193191
- tokens.push({ kind: "OR", value: "||", pos: pos2 });
193192
- i += 2;
193193
- continue;
193194
- }
193195
- const ch = src[i];
193196
- if (ch === ">") {
193197
- tokens.push({ kind: "GT", value: ">", pos: pos2 });
193198
- i++;
193199
- continue;
193200
- }
193201
- if (ch === "<") {
193202
- tokens.push({ kind: "LT", value: "<", pos: pos2 });
193203
- i++;
193204
- continue;
193205
- }
193206
- if (ch === "+") {
193207
- tokens.push({ kind: "PLUS", value: "+", pos: pos2 });
193208
- i++;
193209
- continue;
193210
- }
193211
- if (ch === "-") {
193212
- tokens.push({ kind: "MINUS", value: "-", pos: pos2 });
193213
- i++;
193214
- continue;
193215
- }
193216
- if (ch === "*") {
193217
- tokens.push({ kind: "STAR", value: "*", pos: pos2 });
193218
- i++;
193219
- continue;
193220
- }
193221
- if (ch === "/") {
193222
- tokens.push({ kind: "SLASH", value: "/", pos: pos2 });
193223
- i++;
193224
- continue;
193225
- }
193226
- if (ch === "(") {
193227
- tokens.push({ kind: "LPAREN", value: "(", pos: pos2 });
193228
- i++;
193229
- continue;
193230
- }
193231
- if (ch === ")") {
193232
- tokens.push({ kind: "RPAREN", value: ")", pos: pos2 });
193233
- i++;
193234
- continue;
193235
- }
193236
- if (ch === ",") {
193237
- tokens.push({ kind: "COMMA", value: ",", pos: pos2 });
193238
- i++;
193239
- continue;
193240
- }
193241
- if (ch === ".") {
193242
- tokens.push({ kind: "DOT", value: ".", pos: pos2 });
193243
- i++;
193244
- continue;
193245
- }
193246
- if (ch === "!") {
193247
- tokens.push({ kind: "NOT", value: "!", pos: pos2 });
193248
- i++;
193249
- continue;
193250
- }
193251
- if (/[a-zA-Z_]/.test(ch)) {
193252
- const m = src.slice(i).match(/^[a-zA-Z_][a-zA-Z0-9_]*/);
193253
- const word = m[0];
193254
- const kw = KEYWORDS[word];
193255
- tokens.push({ kind: kw ?? "IDENT", value: word, pos: pos2 });
193256
- i += word.length;
193257
- continue;
193258
- }
193259
- throw new ParseError(`unexpected character '${ch}'`, pos2, src);
193260
- }
193261
- tokens.push({ kind: "EOF", value: "", pos: i });
193262
- return tokens;
193263
- }
193264
- var Parser = class {
193265
- constructor(tokens, src, dialect) {
193266
- this.tokens = tokens;
193267
- this.src = src;
193268
- this.scopes = new Set(dialect.scopes.map((s) => s.token));
193269
- this.defaultScope = dialect.defaultScope;
193270
- this.flagDeltaFns = new Set(
193271
- Object.entries(dialect.functions).filter(([, def]) => def.flagDeltaArgs).map(([name]) => name)
193272
- );
193273
- }
193274
- tokens;
193275
- src;
193276
- pos = 0;
193277
- scopes;
193278
- defaultScope;
193279
- flagDeltaFns;
193280
- peek() {
193281
- return this.tokens[this.pos];
193282
- }
193283
- advance() {
193284
- return this.tokens[this.pos++];
193285
- }
193286
- check(kind) {
193287
- return this.peek().kind === kind;
193288
- }
193289
- expect(kind) {
193290
- if (!this.check(kind)) {
193291
- const tok = this.peek();
193292
- throw new ParseError(`expected ${kind}, got '${tok.value}'`, tok.pos, this.src);
193293
- }
193294
- return this.advance();
193295
- }
193296
- parse() {
193297
- const node = this.parseOr();
193298
- if (!this.check("EOF")) {
193299
- const tok = this.peek();
193300
- throw new ParseError(`unexpected token '${tok.value}'`, tok.pos, this.src);
193301
- }
193302
- return node;
193303
- }
193304
- parseOr() {
193305
- let left = this.parseAnd();
193306
- while (this.check("OR")) {
193307
- this.advance();
193308
- const right = this.parseAnd();
193309
- left = { kind: "binary", op: "or", left, right };
193310
- }
193311
- return left;
193312
- }
193313
- parseAnd() {
193314
- let left = this.parseNot();
193315
- while (this.check("AND")) {
193316
- this.advance();
193317
- const right = this.parseNot();
193318
- left = { kind: "binary", op: "and", left, right };
193319
- }
193320
- return left;
193321
- }
193322
- parseNot() {
193323
- if (this.check("NOT")) {
193324
- this.advance();
193325
- const operand = this.parseNot();
193326
- return { kind: "unary", op: "not", operand };
193327
- }
193328
- return this.parseComparison();
193329
- }
193330
- parseComparison() {
193331
- const left = this.parseAdditive();
193332
- const opMap = {
193333
- EQ: "==",
193334
- NEQ: "!=",
193335
- GT: ">",
193336
- GTE: ">=",
193337
- LT: "<",
193338
- LTE: "<="
193339
- };
193340
- const op = opMap[this.peek().kind];
193341
- if (op !== void 0) {
193342
- this.advance();
193343
- const right = this.parseAdditive();
193344
- return { kind: "binary", op, left, right };
193345
- }
193346
- return left;
193347
- }
193348
- parseAdditive() {
193349
- let left = this.parseMultiplicative();
193350
- while (this.check("PLUS") || this.check("MINUS")) {
193351
- const op = this.advance().kind === "PLUS" ? "+" : "-";
193352
- const right = this.parseMultiplicative();
193353
- left = { kind: "binary", op, left, right };
193354
- }
193355
- return left;
193356
- }
193357
- parseMultiplicative() {
193358
- let left = this.parseUnaryMinus();
193359
- while (this.check("STAR") || this.check("SLASH")) {
193360
- const op = this.advance().kind === "STAR" ? "*" : "/";
193361
- const right = this.parseUnaryMinus();
193362
- left = { kind: "binary", op, left, right };
193363
- }
193364
- return left;
193365
- }
193366
- parseUnaryMinus() {
193367
- if (this.check("MINUS")) {
193368
- this.advance();
193369
- const operand = this.parseUnaryMinus();
193370
- if (operand.kind === "number") return { kind: "number", value: -operand.value };
193371
- return { kind: "unary", op: "neg", operand };
193372
- }
193373
- return this.parsePrimary();
193374
- }
193375
- // Scope-qualified property ref: <scope>.<name> (after a VAR or IDENT token).
193376
- maybeScopedVar(name) {
193377
- if (this.scopes.has(name) && this.check("DOT")) {
193378
- this.advance();
193379
- const propTok = this.peek();
193380
- if (propTok.kind !== "IDENT") {
193381
- throw new ParseError(
193382
- `expected a property name after '${name}.', got '${propTok.value}'`,
193383
- propTok.pos,
193384
- this.src
193385
- );
193386
- }
193387
- this.advance();
193388
- return { kind: "scopedvar", scope: name, name: propTok.value.toLowerCase() };
193389
- }
193390
- return null;
193391
- }
193392
- parsePrimary() {
193393
- const tok = this.peek();
193394
- if (tok.kind === "BOOL") {
193395
- this.advance();
193396
- return { kind: "bool", value: tok.value === "true" };
193397
- }
193398
- if (tok.kind === "NUM") {
193399
- this.advance();
193400
- return { kind: "number", value: Number(tok.value) };
193401
- }
193402
- if (tok.kind === "STR") {
193403
- this.advance();
193404
- return { kind: "string", value: tok.value };
193405
- }
193406
- if (tok.kind === "VAR") {
193407
- const name = tok.value;
193408
- this.advance();
193409
- const scoped = this.maybeScopedVar(name);
193410
- if (scoped) return scoped;
193411
- return { kind: "scopedvar", scope: this.defaultScope, name: name.toLowerCase() };
193412
- }
193413
- if (tok.kind === "IDENT") {
193414
- const name = tok.value;
193415
- this.advance();
193416
- const scoped = this.maybeScopedVar(name);
193417
- if (scoped) return scoped;
193418
- if (this.check("LPAREN")) {
193419
- this.advance();
193420
- const args = [];
193421
- if (!this.check("RPAREN")) {
193422
- args.push(this.parseOr());
193423
- while (this.check("COMMA")) {
193424
- this.advance();
193425
- const wantsFlagDelta = this.flagDeltaFns.has(name) && args.length >= 1;
193426
- if (wantsFlagDelta) {
193427
- const sign2 = this.check("PLUS") ? "+" : this.check("MINUS") ? "-" : null;
193428
- if (sign2 === null) {
193429
- const t = this.peek();
193430
- throw new ParseError(
193431
- `${name}: expected +flagName or -flagName, got '${t.value}'`,
193432
- t.pos,
193433
- this.src
193434
- );
193435
- }
193436
- this.advance();
193437
- const flagTok = this.peek();
193438
- if (flagTok.kind !== "IDENT") {
193439
- throw new ParseError(
193440
- `${name}: expected a flag name after '${sign2}', got '${flagTok.value}'`,
193441
- flagTok.pos,
193442
- this.src
193443
- );
193444
- }
193445
- this.advance();
193446
- args.push({ kind: "flagdelta", sign: sign2, name: flagTok.value });
193447
- } else {
193448
- args.push(this.parseOr());
193449
- }
193450
- }
193451
- }
193452
- this.expect("RPAREN");
193453
- return { kind: "call", name, args };
193454
- }
193455
- return { kind: "string", value: name };
193456
- }
193457
- if (tok.kind === "LPAREN") {
193458
- this.advance();
193459
- const inner = this.parseOr();
193460
- this.expect("RPAREN");
193461
- return inner;
193462
- }
193463
- if (tok.kind === "EOF") {
193464
- throw new ParseError("expression is incomplete - expected a value", tok.pos, this.src);
193465
- }
193466
- throw new ParseError(`unexpected token '${tok.value}'`, tok.pos, this.src);
193467
- }
193468
- };
193469
- function parse3(source2, dialect) {
193470
- const tokens = tokenise(source2);
193471
- return new Parser(tokens, source2, dialect).parse();
193472
- }
193473
-
193474
- // ../../../expr/packages/expr/src/ast.ts
193475
- function serialiseAst(node) {
193476
- switch (node.kind) {
193477
- case "bool":
193478
- return ["b", node.value];
193479
- case "number":
193480
- return ["n", node.value];
193481
- case "string":
193482
- return ["s", node.value];
193483
- case "scopedvar":
193484
- return ["sv", node.scope, node.name];
193485
- case "unary":
193486
- return ["u", node.op, serialiseAst(node.operand)];
193487
- case "binary":
193488
- return ["bin", node.op, serialiseAst(node.left), serialiseAst(node.right)];
193489
- case "call":
193490
- return ["call", node.name, ...node.args.map(serialiseAst)];
193491
- case "flagdelta":
193492
- return ["fd", node.sign, node.name];
193493
- }
193494
- }
193495
- function deserialiseAst(node) {
193496
- switch (node[0]) {
193497
- case "b":
193498
- return { kind: "bool", value: node[1] };
193499
- case "n":
193500
- return { kind: "number", value: node[1] };
193501
- case "s":
193502
- return { kind: "string", value: node[1] };
193503
- case "sv":
193504
- return { kind: "scopedvar", scope: node[1], name: node[2] };
193505
- case "u":
193506
- return { kind: "unary", op: node[1], operand: deserialiseAst(node[2]) };
193507
- case "bin":
193508
- return { kind: "binary", op: node[1], left: deserialiseAst(node[2]), right: deserialiseAst(node[3]) };
193509
- case "call": {
193510
- const args = node.slice(2).map(deserialiseAst);
193511
- return { kind: "call", name: node[1], args };
193512
- }
193513
- case "fd":
193514
- return { kind: "flagdelta", sign: node[1], name: node[2] };
193515
- }
193516
- }
193517
-
193518
- // ../../../expr/packages/expr/src/evaluate.ts
193519
- var EvalError2 = class extends Error {
193520
- constructor(message) {
193521
- super(message);
193522
- this.name = "EvalError";
193523
- }
193524
- };
193525
- function evaluate(node, ctx, dialect) {
193526
- const missingPolicy = new Map(
193527
- dialect.scopes.map((s) => [s.token, s.missing ?? "false"])
193528
- );
193529
- const rec = (n) => {
193530
- switch (n.kind) {
193531
- case "bool":
193532
- return n.value;
193533
- case "number":
193534
- return n.value;
193535
- case "string":
193536
- return n.value;
193537
- case "scopedvar": {
193538
- const scope = ctx.scopes[n.scope];
193539
- if (scope === void 0) {
193540
- return false;
193541
- }
193542
- const val = typeof scope.get === "function" ? scope.get(n.name) : scope[n.name];
193543
- if (val === void 0) {
193544
- if (missingPolicy.get(n.scope) === "throw") {
193545
- throw new EvalError2(`@${n.scope}.${n.name} is not declared on the current ${n.scope}.`);
193546
- }
193547
- return false;
193548
- }
193549
- return val;
193550
- }
193551
- case "call": {
193552
- if (n.name === "advance" && !dialect.functions[n.name]) {
193553
- const arg = n.args[0];
193554
- if (n.args.length !== 1 || arg === void 0) {
193555
- throw new EvalError2(`advance() takes exactly 1 argument, got ${n.args.length}`);
193556
- }
193557
- const ladder = ladderOf(arg, ctx);
193558
- if (ladder === void 0) {
193559
- throw new EvalError2("advance() needs a quality reference (@scope.name of a quality property)");
193560
- }
193561
- const current = stageIndex(rec(arg), ladder, "advance");
193562
- return ladder[Math.min(current + 1, ladder.length - 1)];
193563
- }
193564
- const def = dialect.functions[n.name];
193565
- if (!def) throw new EvalError2(`unknown function '${n.name}'`);
193566
- return def.eval(n.args, { evaluate: rec, ctx });
193567
- }
193568
- case "flagdelta":
193569
- throw new EvalError2("flagdelta node is only valid as an argument to a flag-delta function");
193570
- case "unary": {
193571
- if (n.op === "not") {
193572
- const val2 = rec(n.operand);
193573
- if (typeof val2 !== "boolean") throw new EvalError2(`'not' requires a boolean operand, got ${typeof val2}`);
193574
- return !val2;
193575
- }
193576
- const val = rec(n.operand);
193577
- if (typeof val !== "number") throw new EvalError2(`unary '-' requires a numeric operand, got ${typeof val}`);
193578
- return -val;
193579
- }
193580
- case "binary": {
193581
- if (n.op === "and") {
193582
- const l2 = rec(n.left);
193583
- if (typeof l2 !== "boolean") throw new EvalError2(`'and' requires boolean operands, left is ${typeof l2}`);
193584
- if (!l2) return false;
193585
- const r = rec(n.right);
193586
- if (typeof r !== "boolean") throw new EvalError2(`'and' requires boolean operands, right is ${typeof r}`);
193587
- return r;
193588
- }
193589
- if (n.op === "or") {
193590
- const l2 = rec(n.left);
193591
- if (typeof l2 !== "boolean") throw new EvalError2(`'or' requires boolean operands, left is ${typeof l2}`);
193592
- if (l2) return true;
193593
- const r = rec(n.right);
193594
- if (typeof r !== "boolean") throw new EvalError2(`'or' requires boolean operands, right is ${typeof r}`);
193595
- return r;
193596
- }
193597
- const left = rec(n.left);
193598
- const right = rec(n.right);
193599
- const lLadder = ladderOf(n.left, ctx);
193600
- const rLadder = ladderOf(n.right, ctx);
193601
- const ladder = lLadder ?? rLadder;
193602
- if (ladder !== void 0) {
193603
- if (lLadder && rLadder && !sameLadder(lLadder, rLadder)) {
193604
- if (n.op === ">" || n.op === ">=" || n.op === "<" || n.op === "<=") {
193605
- throw new EvalError2(`'${n.op}' compares two different qualities, whose stage orders are unrelated`);
193606
- }
193607
- }
193608
- switch (n.op) {
193609
- case ">":
193610
- return stageIndex(left, ladder, ">") > stageIndex(right, ladder, ">");
193611
- case ">=":
193612
- return stageIndex(left, ladder, ">=") >= stageIndex(right, ladder, ">=");
193613
- case "<":
193614
- return stageIndex(left, ladder, "<") < stageIndex(right, ladder, "<");
193615
- case "<=":
193616
- return stageIndex(left, ladder, "<=") <= stageIndex(right, ladder, "<=");
193617
- case "+":
193618
- case "-":
193619
- case "*":
193620
- case "/":
193621
- throw new EvalError2(`'${n.op}' cannot be applied to a quality - a stage is a position, not a number; use advance() to move it`);
193622
- default:
193623
- break;
193624
- }
193625
- }
193626
- switch (n.op) {
193627
- case "==":
193628
- return valueEquals(left, right);
193629
- case "!=":
193630
- return !valueEquals(left, right);
193631
- case ">":
193632
- assertNumbers(left, right, ">");
193633
- return left > right;
193634
- case ">=":
193635
- assertNumbers(left, right, ">=");
193636
- return left >= right;
193637
- case "<":
193638
- assertNumbers(left, right, "<");
193639
- return left < right;
193640
- case "<=":
193641
- assertNumbers(left, right, "<=");
193642
- return left <= right;
193643
- case "+":
193644
- if (typeof left === "number" && typeof right === "number") return left + right;
193645
- if (typeof left === "string" && typeof right === "string") return left + right;
193646
- throw new EvalError2(`'+' requires two numbers or two strings, got ${typeof left} and ${typeof right}`);
193647
- case "-":
193648
- assertNumbers(left, right, "-");
193649
- return left - right;
193650
- case "*":
193651
- assertNumbers(left, right, "*");
193652
- return left * right;
193653
- case "/":
193654
- assertNumbers(left, right, "/");
193655
- if (right === 0) throw new EvalError2("division by zero");
193656
- return left / right;
193657
- }
193658
- }
193659
- }
193660
- };
193661
- return rec(node);
193662
- }
193663
- function valueEquals(a, b) {
193664
- if (Array.isArray(a) || Array.isArray(b)) {
193665
- if (!Array.isArray(a) || !Array.isArray(b)) return false;
193666
- if (a.length !== b.length) return false;
193667
- for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
193668
- return true;
193669
- }
193670
- return a === b;
193671
- }
193672
- function assertNumbers(l2, r, op) {
193673
- if (typeof l2 !== "number" || typeof r !== "number") {
193674
- throw new EvalError2(`'${op}' requires numeric operands, got ${typeof l2} and ${typeof r}`);
193675
- }
193676
- }
193677
- function ladderOf(node, ctx) {
193678
- if (node.kind !== "scopedvar" || ctx.qualities === void 0) return void 0;
193679
- return ctx.qualities(node.scope, node.name);
193680
- }
193681
- function stageIndex(value, ladder, op) {
193682
- if (typeof value !== "string") {
193683
- throw new EvalError2(`'${op}' on a quality compares stages, got ${typeof value}`);
193684
- }
193685
- const i = ladder.indexOf(value);
193686
- if (i < 0) throw new EvalError2(`"${value}" is not a stage of this quality (stages: ${ladder.join(", ")})`);
193687
- return i;
193688
- }
193689
- var sameLadder = (a, b) => a.length === b.length && a.every((x, i) => x === b[i]);
193690
-
193691
- // ../../../expr/packages/expr/src/validate.ts
193692
- function validateExpressionAst(node, schema, dialect) {
193693
- const issues = [];
193694
- walkValidate(node, schema, dialect, [], issues);
193695
- return finaliseResult(issues);
193696
- }
193697
- function validateExpr(node, schema, dialect) {
193698
- return validateExpressionAst(node, schema, dialect).issues;
193699
- }
193700
- function finaliseResult(issues) {
193701
- const hasError = issues.some((i) => i.severity === "error");
193702
- const summary = issues.map((i) => i.message).join("; ");
193703
- return { ok: !hasError, issues, summary };
193704
- }
193705
- function walkValidate(node, schema, dialect, path, issues) {
193706
- switch (node.kind) {
193707
- case "bool":
193708
- case "number":
193709
- case "string":
193710
- case "flagdelta":
193711
- return;
193712
- case "scopedvar": {
193713
- const scopeMap = schema.properties.get(node.scope);
193714
- if (scopeMap && !scopeMap.has(node.name)) {
193715
- const isDefault = node.scope === dialect.defaultScope;
193716
- issues.push({
193717
- path,
193718
- kind: isDefault ? "unresolved-property" : "unresolved-scoped-property",
193719
- severity: "error",
193720
- message: isDefault ? `unresolved property reference '@${node.name}'` : `unresolved ${node.scope} property reference '@${node.scope}.${node.name}'`,
193721
- reference: isDefault ? node.name : `${node.scope}.${node.name}`
193722
- });
193723
- }
193724
- return;
193725
- }
193726
- case "call": {
193727
- if (node.name === "advance" && !dialect.functions[node.name]) {
193728
- if (node.args.length !== 1) {
193729
- issues.push({ path, kind: "wrong-arg-count", severity: "error", message: `advance() takes exactly 1 argument, got ${node.args.length}` });
193730
- }
193731
- const arg = node.args[0];
193732
- if (arg) {
193733
- walkValidate(arg, schema, dialect, [...path, "args", 0], issues);
193734
- if (stagesOf(arg, schema) === void 0 && typeOf(arg, schema, dialect) !== "unknown") {
193735
- issues.push({
193736
- path: [...path, "args", 0],
193737
- kind: "wrong-arg-type",
193738
- severity: "error",
193739
- message: "advance() needs a quality reference (@scope.name of a quality property)"
193740
- });
193741
- }
193742
- }
193743
- return;
193744
- }
193745
- const def = dialect.functions[node.name];
193746
- if (!def) {
193747
- issues.push({ path, kind: "unknown-function", severity: "error", message: `unknown function '${node.name}'` });
193748
- return;
193749
- }
193750
- if (node.args.length < def.minArgs) {
193751
- issues.push({
193752
- path,
193753
- kind: "wrong-arg-count",
193754
- severity: "error",
193755
- message: `${node.name}() requires at least ${def.minArgs} argument(s), got ${node.args.length}`
193756
- });
193757
- }
193758
- if (def.maxArgs !== void 0 && node.args.length > def.maxArgs) {
193759
- issues.push({
193760
- path,
193761
- kind: "wrong-arg-count",
193762
- severity: "error",
193763
- message: `${node.name}() takes at most ${def.maxArgs} argument(s), got ${node.args.length}`
193764
- });
193765
- }
193766
- for (let i = 0; i < node.args.length; i++) {
193767
- walkValidate(node.args[i], schema, dialect, [...path, "args", i], issues);
193768
- }
193769
- if (def.validate) {
193770
- def.validate(node.args, {
193771
- schema,
193772
- path,
193773
- defaultScope: dialect.defaultScope,
193774
- report: (issue) => issues.push(issue)
193775
- });
193776
- }
193777
- return;
193778
- }
193779
- case "unary": {
193780
- walkValidate(node.operand, schema, dialect, [...path, "operand"], issues);
193781
- checkUnaryOperandType(node.op, node.operand, schema, dialect, [...path, "operand"], issues);
193782
- return;
193783
- }
193784
- case "binary": {
193785
- walkValidate(node.left, schema, dialect, [...path, "left"], issues);
193786
- walkValidate(node.right, schema, dialect, [...path, "right"], issues);
193787
- checkBinaryOperandTypes(node.op, node.left, node.right, schema, dialect, path, issues);
193788
- if (node.op === "/" && node.right.kind === "number" && node.right.value === 0) {
193789
- issues.push({
193790
- path: [...path, "right"],
193791
- kind: "division-by-zero",
193792
- severity: "error",
193793
- message: "division by zero - pick a non-zero divisor"
193794
- });
193795
- }
193796
- if (node.op === "==" || node.op === "!=") {
193797
- const left = node.left, right = node.right;
193798
- let propNode = null;
193799
- let strNode = null;
193800
- let strSide = null;
193801
- if (left.kind === "scopedvar" && right.kind === "string") {
193802
- propNode = left;
193803
- strNode = right;
193804
- strSide = "right";
193805
- } else if (right.kind === "scopedvar" && left.kind === "string") {
193806
- propNode = right;
193807
- strNode = left;
193808
- strSide = "left";
193809
- }
193810
- if (propNode && strNode && strSide) {
193811
- const meta = schema.properties.get(propNode.scope)?.get(propNode.name);
193812
- if (meta?.type === "enum" && meta.enumValues && !meta.enumValues.includes(strNode.value)) {
193813
- issues.push({
193814
- path: [...path, strSide],
193815
- kind: "unknown-enum-value",
193816
- severity: "error",
193817
- message: `'${strNode.value}' is not a valid value for this property - expected one of: ${meta.enumValues.join(", ")}`,
193818
- reference: strNode.value
193819
- });
193820
- }
193821
- }
193822
- }
193823
- return;
193824
- }
193825
- }
193826
- }
193827
- function inferredFromPropertyType(t) {
193828
- if (t === "boolean") return "boolean";
193829
- if (t === "number") return "number";
193830
- if (t === "string" || t === "enum") return "string";
193831
- if (t === "flags") return "flags";
193832
- if (t === "quality") return "quality";
193833
- return "unknown";
193834
- }
193835
- function inferredFromReturn(t) {
193836
- return t;
193837
- }
193838
- function stagesOf(node, schema) {
193839
- if (node.kind !== "scopedvar") return void 0;
193840
- const meta = schema.properties.get(node.scope)?.get(node.name);
193841
- return meta?.type === "quality" ? meta.stages : void 0;
193842
- }
193843
- function typeOf(node, schema, dialect) {
193844
- switch (node.kind) {
193845
- case "bool":
193846
- return "boolean";
193847
- case "number":
193848
- return "number";
193849
- case "string":
193850
- return "string";
193851
- case "flagdelta":
193852
- return "unknown";
193853
- case "scopedvar": {
193854
- const meta = schema.properties.get(node.scope)?.get(node.name);
193855
- return meta ? inferredFromPropertyType(meta.type) : "unknown";
193856
- }
193857
- case "call": {
193858
- if (node.name === "advance") return "quality";
193859
- const def = dialect.functions[node.name];
193860
- return def ? inferredFromReturn(def.returnType) : "unknown";
193861
- }
193862
- case "unary":
193863
- return node.op === "not" ? "boolean" : "number";
193864
- case "binary":
193865
- switch (node.op) {
193866
- case "+":
193867
- case "-":
193868
- case "*":
193869
- case "/":
193870
- return "number";
193871
- case "==":
193872
- case "!=":
193873
- case ">":
193874
- case "<":
193875
- case ">=":
193876
- case "<=":
193877
- case "and":
193878
- case "or":
193879
- return "boolean";
193880
- }
193881
- }
193882
- }
193883
- function describeType(t) {
193884
- return t === "unknown" ? "unknown type" : t;
193885
- }
193886
- function checkBinaryOperandTypes(op, left, right, schema, dialect, path, issues) {
193887
- const lt = typeOf(left, schema, dialect);
193888
- const rt = typeOf(right, schema, dialect);
193889
- const ordering = op === ">" || op === "<" || op === ">=" || op === "<=";
193890
- if (lt === "quality" || rt === "quality") {
193891
- if (ordering || op === "==" || op === "!=") {
193892
- const ls = stagesOf(left, schema);
193893
- const rs = stagesOf(right, schema);
193894
- if (ls && rs) {
193895
- if (ls.join("\0") !== rs.join("\0")) {
193896
- issues.push({ path, kind: "operand-type-mismatch", severity: "error", message: `'${op}' compares two different qualities, whose stages are unrelated` });
193897
- }
193898
- return;
193899
- }
193900
- const ladder = ls ?? rs;
193901
- const other = ls ? right : left;
193902
- const otherSide = ls ? "right" : "left";
193903
- if (other.kind === "string") {
193904
- if (ladder && !ladder.includes(other.value)) {
193905
- issues.push({
193906
- path: [...path, otherSide],
193907
- kind: "unknown-stage",
193908
- severity: "error",
193909
- message: `'${other.value}' is not a stage of this quality - expected one of: ${ladder.join(", ")}`,
193910
- reference: other.value
193911
- });
193912
- }
193913
- return;
193914
- }
193915
- const ot = ls ? rt : lt;
193916
- if (ot !== "unknown" && ot !== "quality") {
193917
- issues.push({
193918
- path: [...path, otherSide],
193919
- kind: "operand-type-mismatch",
193920
- severity: "error",
193921
- message: `'${op}' on a quality compares stages, got ${describeType(ot)} on the ${otherSide}`
193922
- });
193923
- }
193924
- return;
193925
- }
193926
- if (op === "+" || op === "-" || op === "*" || op === "/") {
193927
- issues.push({
193928
- path,
193929
- kind: "operand-type-mismatch",
193930
- severity: "error",
193931
- message: `'${op}' cannot be applied to a quality - a stage is a position, not a number; use advance() to move it`
193932
- });
193933
- return;
193934
- }
193935
- }
193936
- if (op === "+" || op === "-" || op === "*" || op === "/" || ordering) {
193937
- if (lt !== "unknown" && lt !== "number")
193938
- issues.push({ path: [...path, "left"], kind: "operand-type-mismatch", severity: "error", message: `'${op}' requires a number on the left, got ${describeType(lt)}` });
193939
- if (rt !== "unknown" && rt !== "number")
193940
- issues.push({ path: [...path, "right"], kind: "operand-type-mismatch", severity: "error", message: `'${op}' requires a number on the right, got ${describeType(rt)}` });
193941
- return;
193942
- }
193943
- if (op === "and" || op === "or") {
193944
- if (lt !== "unknown" && lt !== "boolean")
193945
- issues.push({ path: [...path, "left"], kind: "operand-type-mismatch", severity: "error", message: `'${op}' requires a boolean on the left, got ${describeType(lt)}` });
193946
- if (rt !== "unknown" && rt !== "boolean")
193947
- issues.push({ path: [...path, "right"], kind: "operand-type-mismatch", severity: "error", message: `'${op}' requires a boolean on the right, got ${describeType(rt)}` });
193948
- return;
193949
- }
193950
- if (op === "==" || op === "!=") {
193951
- if (lt !== "unknown" && rt !== "unknown" && lt !== rt)
193952
- issues.push({ path, kind: "operand-type-mismatch", severity: "error", message: `'${op}' compares ${describeType(lt)} with ${describeType(rt)}; the values can never be equal` });
193953
- }
193954
- }
193955
- function checkUnaryOperandType(op, operand, schema, dialect, path, issues) {
193956
- const t = typeOf(operand, schema, dialect);
193957
- if (t === "unknown") return;
193958
- if (op === "not" && t !== "boolean")
193959
- issues.push({ path, kind: "operand-type-mismatch", severity: "error", message: `'not' requires a boolean operand, got ${describeType(t)}` });
193960
- if (op === "neg" && t !== "number")
193961
- issues.push({ path, kind: "operand-type-mismatch", severity: "error", message: `unary '-' requires a number, got ${describeType(t)}` });
193962
- }
193963
-
193964
- // ../../../expr/packages/expr/src/index.ts
193965
- function compile(src, dialect) {
193966
- return { src, ast: serialiseAst(parse3(src, dialect)) };
193967
- }
193968
-
193969
194042
  // ../dialect/src/index.ts
193970
194043
  function host(h) {
193971
194044
  return h.ctx.host ?? {};
@@ -194279,7 +194352,7 @@ function stripCaptions(text, open, close) {
194279
194352
  }
194280
194353
  return removed ? collapseCaptionWs(out) : text;
194281
194354
  }
194282
- function interpolate(text, resolve6) {
194355
+ function interpolate(text, resolve7) {
194283
194356
  if (text.indexOf("{") < 0) return text;
194284
194357
  let out = "";
194285
194358
  for (const tok of tokenise2(text)) {
@@ -194291,7 +194364,7 @@ function interpolate(text, resolve6) {
194291
194364
  out += tok.raw;
194292
194365
  continue;
194293
194366
  }
194294
- const v = resolve6(tok.ref);
194367
+ const v = resolve7(tok.ref);
194295
194368
  out += v === void 0 ? "" : renderSlotValue(v);
194296
194369
  }
194297
194370
  return out;
@@ -194628,6 +194701,159 @@ function exportBundle(input) {
194628
194701
  };
194629
194702
  }
194630
194703
 
194704
+ // ../ops/src/reachability.ts
194705
+ var normaliseRef = (ref) => ref.includes(".") ? ref : `@patter.${ref.slice(1)}`;
194706
+ var SEP = "\0";
194707
+ var keyOf = (ref, sceneId) => ref.startsWith("@scene.") ? `${sceneId}${SEP}${ref}` : ref;
194708
+ var shown = (key2) => {
194709
+ const bare = key2.includes(SEP) ? key2.slice(key2.indexOf(SEP) + 1) : key2;
194710
+ const at = bare.indexOf(":");
194711
+ return at < 0 ? bare : `${bare.slice(0, at)} +${bare.slice(at + 1)}`;
194712
+ };
194713
+ var termsOfAst = (ast, sceneId) => terms(ast, sceneId, keyOf);
194714
+ var requirementsOf = (expr, sceneId) => expr === void 0 ? [] : termsOfAst(expr.ast, sceneId);
194715
+ var asFlags = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
194716
+ function reachabilityIssues(loaded, compiled) {
194717
+ const bundle = compiled ?? exportBundle({ project: loaded.project, scenes: loaded.scenes, locales: loaded.locales });
194718
+ const hostTokens = new Set((loaded.project.scopeRegistry?.scopes ?? []).map((s) => s.token));
194719
+ const preset = /* @__PURE__ */ new Set();
194720
+ const notALatch = (decl, key2) => {
194721
+ if (decl.temporary) {
194722
+ preset.add(key2);
194723
+ for (const v of decl.values ?? []) preset.add(`${key2}:${v}`);
194724
+ return;
194725
+ }
194726
+ if (decl.type === "boolean" && decl.default === true) preset.add(key2);
194727
+ if (decl.type === "flags") for (const v of asFlags(decl.default)) preset.add(`${key2}:${v}`);
194728
+ };
194729
+ for (const decl of loaded.project.properties ?? []) notALatch(decl, `@patter.${decl.name}`);
194730
+ for (const scene of loaded.scenes) {
194731
+ for (const decl of scene.sceneProps ?? []) notALatch(decl, `${scene.id}${SEP}@scene.${decl.name}`);
194732
+ }
194733
+ const latched = /* @__PURE__ */ new Set();
194734
+ const broken = /* @__PURE__ */ new Set();
194735
+ const writers = /* @__PURE__ */ new Map();
194736
+ const noteWrite = (key2, requires) => {
194737
+ latched.add(key2);
194738
+ (writers.get(key2) ?? writers.set(key2, []).get(key2)).push({ requires });
194739
+ };
194740
+ const breakKey = (key2) => {
194741
+ broken.add(key2);
194742
+ for (const k of latched) if (k.startsWith(`${key2}:`)) broken.add(k);
194743
+ };
194744
+ const scanEffects = (effects, sceneId, need) => {
194745
+ for (const e of effects ?? []) {
194746
+ const ref = normaliseRef(e.target);
194747
+ const key2 = keyOf(ref, sceneId);
194748
+ const ast = e.value.ast;
194749
+ if (Array.isArray(ast) && ast[0] === "b" && ast[1] === true) {
194750
+ noteWrite(key2, need);
194751
+ continue;
194752
+ }
194753
+ if (Array.isArray(ast) && ast[0] === "call" && ast[1] === "set_flags" && scopedRef(ast[2]) === ref) {
194754
+ let clean3 = true;
194755
+ for (const arg of ast.slice(3)) {
194756
+ if (Array.isArray(arg) && arg[0] === "fd" && arg[1] === "+") noteWrite(`${key2}:${String(arg[2])}`, need);
194757
+ else clean3 = false;
194758
+ }
194759
+ if (clean3) continue;
194760
+ }
194761
+ breakKey(key2);
194762
+ }
194763
+ };
194764
+ const walk2 = (nodes, sceneId, gate) => {
194765
+ for (const node of nodes) {
194766
+ const here = [...gate, ...requirementsOf(node.condition, sceneId)];
194767
+ if (node.type === "group") walk2(node.children, sceneId, here);
194768
+ else {
194769
+ scanEffects(node.onEnter, sceneId, here);
194770
+ scanEffects(node.onExit, sceneId, here);
194771
+ }
194772
+ }
194773
+ };
194774
+ for (const scene of Object.values(bundle.scenes)) {
194775
+ scanEffects(scene.onEntry, scene.id, []);
194776
+ for (const block of scene.blocks) walk2(block.children, scene.id, []);
194777
+ }
194778
+ for (const key2 of [...latched]) {
194779
+ const at = key2.indexOf(":");
194780
+ if (at > 0 && broken.has(key2.slice(0, at))) broken.add(key2);
194781
+ }
194782
+ const hostDriven = (key2) => hostTokens.has(key2.slice(1, key2.indexOf(".")));
194783
+ const monotonic = (key2) => latched.has(key2) && !broken.has(key2) && !preset.has(key2) && !hostDriven(key2);
194784
+ const cache2 = /* @__PURE__ */ new Map();
194785
+ const inFlight = /* @__PURE__ */ new Set();
194786
+ const mustHold = (key2) => {
194787
+ const done = cache2.get(key2);
194788
+ if (done !== void 0) return { need: done, cut: false };
194789
+ if (inFlight.has(key2)) return { need: /* @__PURE__ */ new Set(), cut: true };
194790
+ const routes = writers.get(key2);
194791
+ if (routes === void 0 || routes.length === 0) return { need: /* @__PURE__ */ new Set(), cut: false };
194792
+ inFlight.add(key2);
194793
+ let shared;
194794
+ let cut = false;
194795
+ for (const route of routes) {
194796
+ const need = /* @__PURE__ */ new Set();
194797
+ for (const t of route.requires) {
194798
+ if (t.negated || !monotonic(t.key)) continue;
194799
+ need.add(t.key);
194800
+ const deeper = mustHold(t.key);
194801
+ cut ||= deeper.cut;
194802
+ for (const k of deeper.need) need.add(k);
194803
+ }
194804
+ shared = shared === void 0 ? need : new Set([...shared].filter((k) => need.has(k)));
194805
+ }
194806
+ inFlight.delete(key2);
194807
+ const result = shared ?? /* @__PURE__ */ new Set();
194808
+ if (!cut) cache2.set(key2, result);
194809
+ return { need: result, cut };
194810
+ };
194811
+ const refute = (gate) => {
194812
+ for (const no of gate.filter((t) => t.negated)) {
194813
+ if (!monotonic(no.key)) continue;
194814
+ if (gate.some((t) => !t.negated && t.key === no.key)) {
194815
+ return `it asks for ${shown(no.key)} to be both set and not set`;
194816
+ }
194817
+ for (const yes of gate.filter((t) => !t.negated && t.key !== no.key)) {
194818
+ if (!monotonic(yes.key)) continue;
194819
+ const chain = mustHold(yes.key);
194820
+ if (!chain.cut && chain.need.has(no.key)) {
194821
+ return `${shown(yes.key)} can only become true after ${shown(no.key)}, which nothing sets back, so this condition can never hold`;
194822
+ }
194823
+ }
194824
+ }
194825
+ return void 0;
194826
+ };
194827
+ const issues = [];
194828
+ const report = (nodes, sceneId, gate) => {
194829
+ for (const node of nodes) {
194830
+ const own = node.condition;
194831
+ const branches = own ? disjuncts(own.ast) : [void 0];
194832
+ let reason;
194833
+ const refuted = branches.every((b) => {
194834
+ const r = refute([...gate, ...b ? termsOfAst(b, sceneId) : []]);
194835
+ reason ??= r;
194836
+ return r !== void 0;
194837
+ });
194838
+ if (refuted && reason !== void 0 && own) {
194839
+ issues.push({
194840
+ nodeId: node.id,
194841
+ field: "condition",
194842
+ src: own.src,
194843
+ severity: "warning",
194844
+ message: `this can never run: ${reason}`
194845
+ });
194846
+ continue;
194847
+ }
194848
+ if (node.type === "group") report(node.children, sceneId, [...gate, ...requirementsOf(own, sceneId)]);
194849
+ }
194850
+ };
194851
+ for (const scene of Object.values(bundle.scenes)) {
194852
+ for (const block of scene.blocks) report(block.children, scene.id, []);
194853
+ }
194854
+ return issues;
194855
+ }
194856
+
194631
194857
  // ../ops/src/validate.ts
194632
194858
  function runValidate(loaded) {
194633
194859
  const { project, scenes, locales } = loaded;
@@ -194639,10 +194865,12 @@ function runValidate(loaded) {
194639
194865
  const staleBundles = checkBundles(loaded);
194640
194866
  const unresolvedMerges = sidecarIssues(walkFiles(loaded.root, CONFLICT_SIDECAR));
194641
194867
  const orphans = orphanShards(loaded);
194868
+ const reachability = structural.length === 0 && conditions.length === 0 ? reachabilityIssues(loaded) : [];
194642
194869
  return {
194643
194870
  structural,
194644
194871
  conditions,
194645
194872
  interpolation,
194873
+ reachability,
194646
194874
  hygiene,
194647
194875
  staleBundles,
194648
194876
  unresolvedMerges,
@@ -194781,7 +195009,7 @@ function bundleOutputPath(loaded) {
194781
195009
  }
194782
195010
 
194783
195011
  // ../ops/src/playable-runtime.ts
194784
- var PLAYABLE_RUNTIME_JS = '"use strict";var Patterplay=(()=>{var G=Object.defineProperty;var Se=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var ve=Object.prototype.hasOwnProperty;var be=(n,e)=>{for(var t in e)G(n,t,{get:e[t],enumerable:!0})},we=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of ye(e))!ve.call(n,s)&&s!==t&&G(n,s,{get:()=>e[s],enumerable:!(r=Se(e,s))||r.enumerable});return n};var xe=n=>we(G({},"__esModule",{value:!0}),n);var Me={};be(Me,{Engine:()=>N,Flow:()=>k,buildTagIndex:()=>P,describeBundle:()=>ue,effectiveGameData:()=>fe,gameDataFields:()=>ge,gameDataValue:()=>U});function v(n){switch(n[0]){case"b":return{kind:"bool",value:n[1]};case"n":return{kind:"number",value:n[1]};case"s":return{kind:"string",value:n[1]};case"sv":return{kind:"scopedvar",scope:n[1],name:n[2]};case"u":return{kind:"unary",op:n[1],operand:v(n[2])};case"bin":return{kind:"binary",op:n[1],left:v(n[2]),right:v(n[3])};case"call":{let e=n.slice(2).map(v);return{kind:"call",name:n[1],args:e}}case"fd":return{kind:"flagdelta",sign:n[1],name:n[2]}}}var l=class extends Error{constructor(e){super(e),this.name="EvalError"}};function D(n,e,t){let r=new Map(t.scopes.map(i=>[i.token,i.missing??"false"])),s=i=>{switch(i.kind){case"bool":return i.value;case"number":return i.value;case"string":return i.value;case"scopedvar":{let o=e.scopes[i.scope];if(o===void 0)return!1;let a=typeof o.get=="function"?o.get(i.name):o[i.name];if(a===void 0){if(r.get(i.scope)==="throw")throw new l(`@${i.scope}.${i.name} is not declared on the current ${i.scope}.`);return!1}return a}case"call":{if(i.name==="advance"&&!t.functions[i.name]){let a=i.args[0];if(i.args.length!==1||a===void 0)throw new l(`advance() takes exactly 1 argument, got ${i.args.length}`);let c=T(a,e);if(c===void 0)throw new l("advance() needs a quality reference (@scope.name of a quality property)");let d=S(s(a),c,"advance");return c[Math.min(d+1,c.length-1)]}let o=t.functions[i.name];if(!o)throw new l(`unknown function \'${i.name}\'`);return o.eval(i.args,{evaluate:s,ctx:e})}case"flagdelta":throw new l("flagdelta node is only valid as an argument to a flag-delta function");case"unary":{if(i.op==="not"){let a=s(i.operand);if(typeof a!="boolean")throw new l(`\'not\' requires a boolean operand, got ${typeof a}`);return!a}let o=s(i.operand);if(typeof o!="number")throw new l(`unary \'-\' requires a numeric operand, got ${typeof o}`);return-o}case"binary":{if(i.op==="and"){let g=s(i.left);if(typeof g!="boolean")throw new l(`\'and\' requires boolean operands, left is ${typeof g}`);if(!g)return!1;let h=s(i.right);if(typeof h!="boolean")throw new l(`\'and\' requires boolean operands, right is ${typeof h}`);return h}if(i.op==="or"){let g=s(i.left);if(typeof g!="boolean")throw new l(`\'or\' requires boolean operands, left is ${typeof g}`);if(g)return!0;let h=s(i.right);if(typeof h!="boolean")throw new l(`\'or\' requires boolean operands, right is ${typeof h}`);return h}let o=s(i.left),a=s(i.right),c=T(i.left,e),d=T(i.right,e),p=c??d;if(p!==void 0){if(c&&d&&!ke(c,d)&&(i.op===">"||i.op===">="||i.op==="<"||i.op==="<="))throw new l(`\'${i.op}\' compares two different qualities, whose stage orders are unrelated`);switch(i.op){case">":return S(o,p,">")>S(a,p,">");case">=":return S(o,p,">=")>=S(a,p,">=");case"<":return S(o,p,"<")<S(a,p,"<");case"<=":return S(o,p,"<=")<=S(a,p,"<=");case"+":case"-":case"*":case"/":throw new l(`\'${i.op}\' cannot be applied to a quality - a stage is a position, not a number; use advance() to move it`);default:break}}switch(i.op){case"==":return X(o,a);case"!=":return!X(o,a);case">":return b(o,a,">"),o>a;case">=":return b(o,a,">="),o>=a;case"<":return b(o,a,"<"),o<a;case"<=":return b(o,a,"<="),o<=a;case"+":if(typeof o=="number"&&typeof a=="number"||typeof o=="string"&&typeof a=="string")return o+a;throw new l(`\'+\' requires two numbers or two strings, got ${typeof o} and ${typeof a}`);case"-":return b(o,a,"-"),o-a;case"*":return b(o,a,"*"),o*a;case"/":if(b(o,a,"/"),a===0)throw new l("division by zero");return o/a}}}};return s(n)}function X(n,e){if(Array.isArray(n)||Array.isArray(e)){if(!Array.isArray(n)||!Array.isArray(e)||n.length!==e.length)return!1;for(let t=0;t<n.length;t++)if(n[t]!==e[t])return!1;return!0}return n===e}function b(n,e,t){if(typeof n!="number"||typeof e!="number")throw new l(`\'${t}\' requires numeric operands, got ${typeof n} and ${typeof e}`)}function T(n,e){if(!(n.kind!=="scopedvar"||e.qualities===void 0))return e.qualities(n.scope,n.name)}function S(n,e,t){if(typeof n!="string")throw new l(`\'${t}\' on a quality compares stages, got ${typeof n}`);let r=e.indexOf(n);if(r<0)throw new l(`"${n}" is not a stage of this quality (stages: ${e.join(", ")})`);return r}var ke=(n,e)=>n.length===e.length&&n.every((t,r)=>t===e[r]);var Ce={name:"check_flags",count:n=>Math.max(1,n.args.length-1)},Ee=[Ce];function Y(n,e,t){let r=t?.countingCalls??Ee;return I(n,t?.want??!0,e,r)}function I(n,e,t,r){if(n.kind==="binary"&&(n.op==="and"||n.op==="or")){let s=I(n.left,e,t,r),i=I(n.right,e,t,r);return n.op==="and"===e?s>0&&i>0?s+i:0:Math.max(s,i)}if(n.kind==="unary"&&n.op==="not")return I(n.operand,!e,t,r);if(n.kind==="call"){let s=r.find(i=>i.name===n.name);if(s){let i=s.count(n),o=t(n);return e?o?i:0:o?0:1}}return t(n)===e?1:0}var M=class n{values={};decls=new Map;subscribers=new Set;auditors=new Set;norm;constructor(e=[],t){this.norm=t?.normalise??(r=>r.toLowerCase()),this.seed(e)}seed(e){for(let t of e){let r=this.norm(t.name);this.decls.set(r,t),this.values[r]=structuredClone(t.default??Q(t))}}get(e){return this.values[this.norm(e)]}set(e,t,r){let s=this.norm(e);if(this.decls.get(s)?.writable===!1)throw new Error(`\'${e}\' is read-only`);let i={name:s,prev:this.values[s],next:t,silent:r?.silent??!1,reason:r?.reason};this.values[s]=t;for(let o of this.auditors)o(i);if(!i.silent)for(let o of this.subscribers)o(i);return i}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}onAudit(e){return this.auditors.add(e),()=>this.auditors.delete(e)}rows(){return[...this.decls.entries()].map(([e,t])=>Z(t,this.get(e),void 0,e))}declarations(){return[...this.decls.values()]}clone(){let e=new n([],{normalise:this.norm});return e.decls=new Map(this.decls),Object.assign(e.values,structuredClone(this.values)),e}reseed(e){for(let t of Object.keys(this.values))delete this.values[t];this.decls.clear(),this.seed(e)}save(){return structuredClone(this.values)}load(e){for(let[t,r]of Object.entries(e))this.values[this.norm(t)]=r}};function Z(n,e,t,r){return{name:r??n.name.toLowerCase(),type:n.type,value:e,default:n.default??Q(n),...n.values!==void 0?{values:n.values}:{},writable:t??n.writable??!0}}var V=1,C=class{scopes=new Map;defineOwned(e,t){return this.mountOwned(e,new M(t))}mountOwned(e,t){return this.assertFree(e),this.scopes.set(e,{kind:"owned",bag:t}),this}ownedBag(e){let t=this.scopes.get(e);if(!t||t.kind!=="owned")throw new Error(`\'@${e}\' is not an owned scope`);return t.bag}reseedOwned(e,t){return this.ownedBag(e).reseed(t),this}defineForeign(e,t,r=[],s=!0){this.assertFree(e);let i=new Map;for(let o of r)i.set(o.name.toLowerCase(),o);return this.scopes.set(e,{kind:"foreign",resolver:t,decls:i,scopeWritable:s}),this}has(e){return this.scopes.has(e)}get(e,t){let r=this.scopes.get(e);if(r)return r.kind==="owned"?r.bag.get(t):r.resolver.get(t.toLowerCase())}set(e,t,r){let s=this.scopes.get(e);if(!s)throw new Error(`unknown scope \'@${e}\'`);if(s.kind==="owned"){try{s.bag.set(t,r)}catch{throw new Error(`\'@${e}.${t}\' is read-only`)}return}let i=t.toLowerCase();if(!this.foreignWritable(s,i))throw new Error(`\'@${e}.${t}\' is read-only`);s.resolver.set(i,r)}foreignWritable(e,t){return e.resolver.set?e.decls.get(t)?.writable??e.scopeWritable:!1}listProperties(){let e=[];for(let[t,r]of this.scopes)if(r.kind==="owned")for(let s of r.bag.rows())e.push({scope:t,...s});else for(let s of r.decls.values())e.push({scope:t,...Z(s,r.resolver.get(s.name.toLowerCase()),this.foreignWritable(r,s.name.toLowerCase()))});return e}toEvalContext(e){let t={};for(let[s,i]of this.scopes)t[s]=i.kind==="owned"?i.bag.values:i.resolver;let r=this.qualityLadders();return r.size===0?{scopes:t,host:e}:{scopes:t,host:e,qualities:(s,i)=>r.get(s)?.get(i.toLowerCase())}}qualityLadders(){let e=new Map;for(let[t,r]of this.scopes){let s=r.kind==="owned"?r.bag.declarations():[...r.decls.values()];for(let i of s){if(i.type!=="quality"||i.stages===void 0)continue;let o=e.get(t);o||(o=new Map,e.set(t,o)),o.set(i.name.toLowerCase(),i.stages)}}return e}toSchema(){let e=new Map;for(let[t,r]of this.scopes){let s=r.kind==="owned"?r.bag.declarations():[...r.decls.values()];if(s.length===0)continue;let i=new Map;for(let o of s)i.set(o.name.toLowerCase(),{type:o.type,enumValues:o.values,...o.stages!==void 0?{stages:o.stages}:{}});e.set(t,i)}return{properties:e}}save(){let e={};for(let[t,r]of this.scopes)r.kind==="owned"&&(e[t]=r.bag.save());return e}load(e){for(let[t,r]of Object.entries(e)){let s=this.scopes.get(t);s?.kind==="owned"&&s.bag.load(r)}}saveFragment(){return{version:V,scopes:this.save()}}loadFragment(e){if(e.version!==V)throw new Error(`unsupported owned-state fragment version ${e.version} (supported: ${V})`);this.load(e.scopes)}assertFree(e){if(this.scopes.has(e))throw new Error(`scope \'@${e}\' is already registered`)}};function Q(n){if(n.default!==void 0)return n.default;switch(n.type){case"boolean":return!1;case"number":return 0;case"string":return"";case"enum":return n.values?.[0]??"";case"flags":return[];case"quality":return n.stages?.[0]??""}}function E(n){return n.ctx.host??{}}var L={defaultScope:"patter",scopes:[{token:"patter"},{token:"scene"}],functions:{random:{minArgs:2,maxArgs:2,returnType:"number",eval(n,e){if(n.length!==2)throw new l("random(a, b) requires exactly 2 arguments");let t=E(e).nextRandom;if(!t)throw new l("random() called without a PRNG in context");let r=e.evaluate(n[0]),s=e.evaluate(n[1]);if(typeof r!="number"||typeof s!="number")throw new l("random(a, b) arguments must be numbers");if(!Number.isInteger(r)||!Number.isInteger(s))throw new l("random(a, b) arguments must be integers");let i=Math.min(r,s),o=Math.max(r,s);return Math.floor(t()*(o-i+1))+i}},check_flags:{minArgs:1,returnType:"boolean",flagDeltaArgs:!0,validate:te("check_flags"),eval(n,e){let t=ee(n[0],e,"check_flags");for(let r=1;r<n.length;r++){let s=n[r];if(s.kind!=="flagdelta")throw new l("check_flags() flag args must be +flagName or -flagName");if(s.sign==="+"?!t.includes(s.name):t.includes(s.name))return!1}return!0}},set_flags:{minArgs:1,returnType:"flags",flagDeltaArgs:!0,validate:te("set_flags"),eval(n,e){let t=[...ee(n[0],e,"set_flags")];for(let r=1;r<n.length;r++){let s=n[r];if(s.kind!=="flagdelta")throw new l("set_flags() flag args must be +flagName or -flagName");if(s.sign==="+")t.includes(s.name)||t.push(s.name);else{let i=t.indexOf(s.name);i>=0&&t.splice(i,1)}}return t}},visits:{minArgs:1,maxArgs:1,returnType:"number",validate:B("visits"),eval:(n,e)=>E(e).visits?.(R(n,e,"visits"))??0},seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:B("seen"),eval:(n,e)=>(E(e).visits?.(R(n,e,"seen"))??0)>0},patter_visits:{minArgs:1,maxArgs:1,returnType:"number",validate:B("patter_visits"),eval:(n,e)=>E(e).patterVisits?.(R(n,e,"patter_visits"))??0},patter_seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:B("patter_seen"),eval:(n,e)=>(E(e).patterVisits?.(R(n,e,"patter_seen"))??0)>0}}};function j(n,e){let t=n.replace(/^@/,"").split(".");return t.length===2&&e(t[0])?{scope:t[0],name:t[1].toLowerCase()}:{scope:"patter",name:t.join(".").toLowerCase()}}function R(n,e,t){let r=e.evaluate(n[0]);if(typeof r!="string")throw new l(`${t}(id) requires a string node id`);return r}function B(n){return(e,t)=>{let r=e[0];r&&r.kind!=="string"&&t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${n}(id): the argument must be a string id literal (a scene / block / node id)`})}}function ee(n,e,t){if(!n)throw new l(`${t}() requires at least one argument (the flags variable)`);let r=e.evaluate(n);if(Array.isArray(r))return r;if(r===!1||r===null||r===void 0)return[];throw new l(`${t}() first argument must be a flags property`)}function te(n){return(e,t)=>{if(e.length===0)return;let r=e[0];if(r.kind!=="scopedvar"){t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${n}(): first argument must be a flags property reference (@name or @scope.name)`});return}let s=t.schema.properties.get(r.scope)?.get(r.name);if(s&&s.type!=="flags"){let i=r.scope===t.defaultScope?r.name:`${r.scope}.${r.name}`;t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${n}(): \'@${i}\' is not a flags property (got ${s.type})`});return}for(let i=1;i<e.length;i++){let o=e[i];o.kind!=="flagdelta"?t.report({path:[...t.path,"args",i],kind:"wrong-arg-type",severity:"error",message:`${n}(): argument ${i+1} must be +flagName or -flagName`}):s?.type==="flags"&&s.enumValues&&!s.enumValues.includes(o.name)&&t.report({path:[...t.path,"args",i],kind:"unknown-flag-name",severity:"error",message:`${n}(): unknown flag \'${o.name}\'`,reference:o.name})}}}var De=/^@[A-Za-z0-9_.]+$/;function*Ie(n){let e="",t=0;for(;t<n.length;){let r=n[t];if(r==="{"&&n[t+1]==="{"){e+="{",t+=2;continue}if(r==="}"&&n[t+1]==="}"){e+="}",t+=2;continue}if(r==="{"){let s=n.indexOf("}",t+1);if(s!==-1){let i=n.slice(t,s+1),o=n.slice(t+1,s).trim();if(o.startsWith("@")){e&&(yield{kind:"text",value:e},e=""),yield{kind:"slot",raw:i,inner:o,ref:De.test(o)?o:void 0},t=s+1;continue}e+=i,t=s+1;continue}}e+=r,t+=1}e&&(yield{kind:"text",value:e})}function Re(n){return Array.isArray(n)?n.join(", "):typeof n=="boolean"?n?"true":"false":String(n)}function Be(n){return n===" "||n===" "||n===`\n`||n==="\\r"||n==="\\f"||n==="\\v"}function Oe(n){let e="",t=!1;for(let r of n){if(Be(r)){t=!0;continue}t&&e.length>0&&(e+=" "),t=!1,e+=r}return e}function re(n,e,t){if(e.length===0||n.indexOf(e)<0)return n;let r="",s=0,i=!1;for(;s<n.length;){if(n.startsWith(e,s)){let o=n.indexOf(t,s+e.length);if(o>=0){s=o+t.length,i=!0;continue}r+=n.slice(s);break}r+=n[s],s+=1}return i?Oe(r):n}function ne(n,e){if(n.indexOf("{")<0)return n;let t="";for(let r of Ie(n)){if(r.kind==="text"){t+=r.value;continue}if(!r.ref){t+=r.raw;continue}let s=e(r.ref);t+=s===void 0?"":Re(s)}return t}function x(n,e){for(let t of n){e(t);let r=t.children;r&&x(r,e)}}function Pe(n){return n.toLowerCase().replace(/[\'\u2019]/g,"").replace(/[^a-z0-9-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function f(n){let e=n.gameId?.trim();return e||Pe(n.name)}function $(n){return`cast:${n}`}var _={open:"[",close:"]"},se="SFX";function O(n){let e=new Set,t=[];for(let r of n)e.has(r)||(e.add(r),t.push(r));return t}function P(n){let e=new Map,t=(r,s)=>{let i=O([...s,...r.tags??[]]);if(e.set(r.id,i),r.type==="group")for(let o of r.children)t(o,i);else for(let o of r.beats??[])e.set(o.id,O([...i,...o.tags??[]]))};for(let r of Object.values(n.scenes)){let s=O(r.tags??[]);e.set(r.id,s);for(let i of r.blocks){let o=O([...s,...i.tags??[]]);e.set(i.id,o);for(let a of i.children)t(a,o)}}return e}var ie=new WeakMap,N=class n{host;defaultSeed;flowsById=new Map;allStrings;currentLocale;sourceDebug;sceneGameIdToId=new Map;blockGameIdToId=new Map;creationOptions;constructor(e,t={}){this.creationOptions=t;let r=t.locale??e.locales.default,s=e.strings;this.allStrings=s,this.currentLocale=r;let i=s[r]??{},o=s[e.locales.default]??{},a=e.localisation,c=a?.mode==="ids"&&!a.sourceDebug;this.sourceDebug=a?.mode==="ids"&&!!a.sourceDebug,this.sourceDebug&&typeof console<"u"&&console.warn("[Patterplay] source-only DEBUG build: strings are the source language for debugging, not a shippable localised build.");let d=new Map;for(let u of e.cast??[])u.displayName&&d.set(u.name,u.displayName);this.defaultSeed=(t.seed??2654435769)>>>0;let p=new Map,g=new Map,h=new Map;for(let[u,y]of Object.entries(e.scenes)){this.sceneGameIdToId.set(f(y),u);let w=new Map;for(let m of y.blocks)g.set(m.id,{sceneId:u}),h.set(m.id,m),w.set(f(m),m.id),x(m.children,J=>p.set(J.id,J));this.blockGameIdToId.set(u,w)}let W=e.properties??[],A=W.filter(u=>u.shared??!0).map(ae),he=W.filter(u=>!(u.shared??!0)).map(ae),me=new Set(A.map(u=>u.name.toLowerCase())),F=new C().defineOwned("patter",A),K=new Set;if(t.world){let u=e.scopeRegistry?.scopes.find(w=>w.token==="world"),y=(u?.declarations??[]).map(ce);F.defineForeign("world",t.world,y,u?.writable??!0),K.add("world")}for(let u of e.scopeRegistry?.scopes??[]){if(K.has(u.token))continue;let y=(u.declarations??[]).map(ce);F.defineForeign(u.token,Fe(u.declarations??[]),y,u.writable??!0)}let z=new Map;for(let[u,y]of Object.entries(e.scenes)){let w=new Set((y.sceneProps??[]).filter(m=>m.shared??!1).map(m=>m.name.toLowerCase()));z.set(u,w)}this.host={bundle:e,emitIds:c,strings:i,defaultStrings:o,castDisplay:d,nodeIndex:p,blockIndex:g,blockById:h,sceneGameIdToId:this.sceneGameIdToId,blockGameIdToId:this.blockGameIdToId,tagIndex:P(e),shared:F,patterSharedDecls:A,patterLocalDecls:he,patterSharedNames:me,sceneSharedNames:z,sharedVisits:new Map,sharedSelectors:new Map,stageBags:new Map,customRng:t.rng,onDryChoice:t.onDryChoice,replayPromptOnChoose:t.replayPromptOnChoose??!1,captionsOn:t.closedCaptions??!0,captionOpen:(e.closedCaptions??_).open,captionClose:(e.closedCaptions??_).close,captionCharacter:e.closedCaptions?.character||se,refSplitCache:new Map}}get locale(){return this.currentLocale}get isSourceDebug(){return this.sourceDebug}setLocale(e){this.currentLocale=e,this.host.strings=this.allStrings[e]??{}}replaceStrings(e){this.allStrings=e.strings,this.host.strings=this.allStrings[this.currentLocale]??{},this.host.defaultStrings=this.allStrings[this.host.bundle.locales.default]??{}}hotSwap(e){let t=this.saveGame(),r=i=>(i.setLocale(this.currentLocale),i.setClosedCaptions(this.host.captionsOn),i),s=new n(e,this.creationOptions);try{return s.loadGame(t),r(s)}catch{let i=new n(e,this.creationOptions);for(let[o,a]of Object.entries(t.flows)){let c=a.cursor.currentSceneId;try{i.openFlow(o,c!==null?{scene:c}:{})}catch{}}return r(i)}}get closedCaptions(){return this.host.captionsOn}setClosedCaptions(e){this.host.captionsOn=e}openFlow(e,t={}){let r=this.resolveSceneRef(t.scene),s=this.resolveBlockRef(r,t.block);this.flowsById.get(e)?.close();let i=new k(e,this.host,t.seed??this.defaultSeed);return this.flowsById.set(e,i),i.start(r,s),i}runFlow(e,t,r){let s=this.flowsById.get(e);if(!s)return this.openFlow(e,{scene:t,block:r}).advanceToStop().played;if(!s.goto(t,r))throw new Error(`runFlow: address not found: ${t}${r===void 0?"":` / ${r}`}`);return s.advanceToStop().played}resolveSceneRef(e){if(e!=null)return this.host.bundle.scenes[e]?e:this.sceneGameIdToId.get(e)??e}resolveBlockRef(e,t){if(t!=null){if(this.host.blockById.has(t))return t;if(e!=null){let r=this.blockGameIdToId.get(e)?.get(t);if(r)return r}return t}}sceneAddress(e){let t=this.host.bundle.scenes[e];return t?f(t):void 0}blockAddress(e){let t=this.host.blockById.get(e);return t?f(t):void 0}tagsForBeat(e){return this.host.tagIndex.get(e)??[]}tagsForScene(e){let t=this.resolveSceneRef(e);return(t!=null?this.host.tagIndex.get(t):void 0)??[]}tagsForBlock(e,t){let r=this.resolveSceneRef(e),s=this.resolveBlockRef(r,t);return(s!=null?this.host.tagIndex.get(s):void 0)??[]}getCast(){let e=[];for(let t of this.host.bundle.cast??[])t?.name&&e.push(t.name);return e}castForScene(e){let t=this.resolveSceneRef(e),r=t!=null?this.host.bundle.scenes[t]:void 0;if(!r)return[];let s=new Set;for(let i of r.blocks)oe(i.children,s);return[...s]}castForBlock(e,t){let r=this.resolveSceneRef(e),s=this.resolveBlockRef(r,t),i=s!=null?this.host.blockById.get(s):void 0;if(!i)return[];let o=new Set;return oe(i.children,o),[...o]}getOutline(){return Object.values(this.host.bundle.scenes).map(e=>({id:e.id,...f(e)?{gameId:f(e)}:{},name:e.name,...this.tagsField(e.id),blocks:e.blocks.map(t=>({id:t.id,...f(t)?{gameId:f(t)}:{},name:t.name,...this.tagsField(t.id),children:t.children.map(r=>this.outlineNode(r))}))}))}getBeatSequence(){let e=[];for(let t of Object.values(this.host.bundle.scenes))for(let r of t.blocks)x(r.children,s=>{if(s.type==="snippet")for(let i of s.beats??[])e.push({sceneId:t.id,blockId:r.id,snippetId:s.id,beat:this.beatInfo(i)})});return e}outlineNode(e){return e.type==="group"?{type:"group",id:e.id,...this.tagsField(e.id),...e.selector?{selector:e.selector}:{},...e.prompt?{prompt:this.beatInfo(e.prompt)}:{},children:e.children.map(t=>this.outlineNode(t))}:{type:"snippet",id:e.id,...this.tagsField(e.id),beats:(e.beats??[]).map(t=>this.beatInfo(t)),...e.jump?{jumpTo:e.jump.to,...e.jump.mode?{jumpMode:e.jump.mode}:{}}:{}}}beatInfo(e){let t=this.host.tagIndex.get(e.id),r={id:e.id,kind:e.kind};if(e.kind==="line"){if(e.character!==void 0){r.character=e.character;let s=this.host.defaultStrings[$(e.character)]??this.host.castDisplay.get(e.character);s!==void 0&&(r.characterName=s)}e.direction!==void 0&&(r.direction=e.direction)}if(e.kind==="line"||e.kind==="text"){let s=this.host.defaultStrings[e.id];s!==void 0&&(r.text=s)}return e.gameData&&Object.keys(e.gameData).length&&(r.gameData=e.gameData),t&&t.length&&(r.tags=t),r}tagsField(e){let t=this.host.tagIndex.get(e);return t&&t.length?{tags:t}:{}}getFlow(e){return this.flowsById.get(e)}flows(){return[...this.flowsById.values()]}closeFlow(e){this.flowsById.get(e)?.close(),this.flowsById.delete(e)}reset(){for(let e of this.flowsById.values())e.close();this.flowsById.clear(),this.host.shared.reseedOwned("patter",this.host.patterSharedDecls),this.host.sharedVisits.clear(),this.host.sharedSelectors.clear(),this.host.stageBags.clear()}getProperty(e){let{scope:t,name:r}=this.splitShared(e);return this.host.shared.get(t,r)}setProperty(e,t){let{scope:r,name:s}=this.splitShared(e);this.host.shared.set(r,s,t)}listProperties(){return this.host.patterSharedDecls.map(e=>({ref:`@${e.name}`,type:e.type,values:e.values,stages:e.stages,value:this.getProperty(`@${e.name}`),default:Ne(e)}))}splitShared(e){let t=this.host.refSplitCache.get(e);if(t||(t=j(e,r=>r==="scene"||this.host.shared.has(r)),this.host.refSplitCache.set(e,t)),t.scope==="scene")throw new Error(`\'${e}\': @scene properties are scene-scoped - read/write them on a Flow, not the Engine`);return t}save(){return this.host.shared.save()}load(e){this.host.shared.load(e)}saveGame(){let e={};for(let[t,r]of this.flowsById)e[t]=r.snapshot();return{version:2,shared:this.host.shared.save(),sharedVisits:Object.fromEntries(this.host.sharedVisits),sharedSelectors:pe(this.host.sharedSelectors),stageBags:Object.fromEntries([...this.host.stageBags].map(([t,r])=>[t,{...r}])),flows:e}}loadGame(e){if(e.version!==2)throw new Error(`unsupported save version: ${e.version}`);this.host.shared.load(e.shared),this.host.sharedVisits.clear();for(let[t,r]of Object.entries(e.sharedVisits??{}))this.host.sharedVisits.set(t,r);this.host.sharedSelectors.clear();for(let[t,r]of de(e.sharedSelectors))this.host.sharedSelectors.set(t,r);this.host.stageBags.clear();for(let[t,r]of Object.entries(e.stageBags??{}))this.host.stageBags.set(t,{...r});this.flowsById.clear();for(let[t,r]of Object.entries(e.flows)){let s=new k(t,this.host,this.defaultSeed);s.restore(r),this.flowsById.set(t,s)}}},k=class{id;host;local;rngState;started=!1;flowEnded=!1;closed=!1;currentSceneId=null;stack=[];activeSnippet=null;beatIndex=0;pendingChoice=null;pendingPromptBeat=null;pendingPromptOwnerId=null;selectors=new Map;visitCounts=new Map;sceneBags=new Map;patterResolver={get:e=>this.host.patterSharedNames.has(e)?this.host.shared.get("patter",e):this.local.get("patter",e),set:(e,t)=>{this.host.patterSharedNames.has(e)?this.host.shared.set("patter",e,t):this.local.set("patter",e,t)}};sceneResolver={get:e=>{let t=this.currentSceneId;return t===null?void 0:(this.host.sceneSharedNames.get(t)?.has(e)?this.host.stageBags.get(t):this.sceneBags.get(t))?.[e]},set:(e,t)=>{let r=this.currentSceneId;if(r===null)return;let s=this.host.sceneSharedNames.get(r)?.has(e)?this.host.stageBags.get(r):this.sceneBags.get(r);s&&(s[e]=t)}};evalCtx;constructor(e,t,r){this.id=e,this.host=t,this.rngState=r>>>0,this.local=this.freshLocal();let s={...t.shared.toEvalContext().scopes};s.patter=this.patterResolver,s.scene=this.sceneResolver,this.evalCtx={scopes:s,host:{nextRandom:this.rng,visits:i=>this.visitCounts.get(i)??0,patterVisits:i=>this.host.sharedVisits.get(i)??0},qualities:(i,o)=>this.stagesFor(i,o)}}stagesFor(e,t){let r=t.toLowerCase(),s=i=>i?.find(o=>o.name.toLowerCase()===r&&o.type==="quality")?.stages;if(e==="patter")return s(this.host.patterSharedDecls)??s(this.host.patterLocalDecls);if(e==="scene"){let i=this.currentSceneId!=null?this.host.bundle.scenes[this.currentSceneId]:void 0;return s(i?.sceneProps)}return s(this.host.bundle.scopeRegistry?.scopes.find(i=>i.token===e)?.declarations)}start(e,t){if(this.sceneBags.clear(),this.local=this.freshLocal(),this.selectors.clear(),this.visitCounts.clear(),this.stack=[],this.currentSceneId=null,this.flowEnded=!1,this.activeSnippet=null,this.beatIndex=0,this.pendingChoice=null,this.started=!0,t){let r=this.host.blockIndex.get(t);if(!r)throw new Error(`unknown block: ${t}`);this.enterSceneSetup(r.sceneId),this.stack=[{sceneId:r.sceneId,containerId:t,index:0}],this.enter(t)}else{let r=e??Object.keys(this.host.bundle.scenes)[0],s=r?this.host.bundle.scenes[r]:void 0;if(!s)throw new Error(r?`unknown scene: ${r}`:"no scenes in bundle");this.enterSceneSetup(r);let i=s.blocks[0];i&&(this.stack=[{sceneId:r,containerId:i.id,index:0}],this.enter(i.id))}this.settle()}reset(e,t){this.start(e,t)}goto(e,t){if(this.closed)return!1;if(e==="END")return this.started=!0,this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!0,this.stack=[],!0;let r=this.host.sceneGameIdToId.get(e)??(this.host.bundle.scenes[e]?e:void 0);if(r===void 0)return!1;let s;return t!==void 0&&(s=this.host.blockGameIdToId.get(r)?.get(t)??(this.host.blockIndex.get(t)?.sceneId===r?t:void 0),s===void 0)?!1:this.started?(this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!1,this.enterTarget(s??r,"jump"),this.settle(),!0):(this.start(r,s),!0)}close(){this.closed=!0,this.flowEnded=!0,this.stack=[],this.activeSnippet=null,this.beatIndex=0,this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null}get isClosed(){return this.closed}get currentScene(){return this.currentSceneId}advance(){if(this.closed)return{type:"end"};if(!this.started)throw new Error("flow has not been started");if(this.pendingPromptBeat){let e=this.pendingPromptBeat;return this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.beatResult(e)}return this.settle(),this.flowEnded?{type:"end"}:this.pendingChoice?{type:"choice",groupId:this.pendingChoice.groupId,options:this.pendingChoice.options}:this.activeSnippet?this.beatResult(this.activeSnippet.beats[this.beatIndex++]):(this.flowEnded=!0,{type:"end"})}advanceToStop(){let e=[];for(;;){let t=this.advance();if(t.type==="choice"||t.type==="end")return{played:e,stop:t};e.push(t)}}settle(){let e=0;for(;;){if(++e>1e4)throw new Error("flow did not settle after 10000 transitions - likely a jump cycle with no deliverable content");if(this.flowEnded||this.pendingChoice)return;if(this.activeSnippet){if(this.beatIndex<(this.activeSnippet.beats?.length??0))return;this.runEffects(this.activeSnippet.onExit);let s=this.activeSnippet.jump;this.activeSnippet=null,this.beatIndex=0,this.resolveJump(s);continue}let t=this.stack[this.stack.length-1];if(!t){this.flowEnded=!0;return}t.sceneId!==this.currentSceneId&&(this.currentSceneId=t.sceneId);let r=this.childrenOf(t.containerId);if(!r){this.stack.pop();continue}for(;t.index<r.length&&!this.eligible(r[t.index]);)t.index++;if(t.index>=r.length){this.stack.pop();continue}this.enterChild(r[t.index++])}}getChoices(){return this.pendingChoice?.options??[]}choose(e){let t=this.pendingChoice;if(!t)throw new Error("no choice is pending");let r=t.options.find(i=>i.id===e);if(!r)throw new Error(`unknown choice option: ${e}`);if(!r.eligible)throw new Error(`choice option is not eligible: ${e}`);let s=t.byId.get(e);this.pendingChoice=null,this.pendingPromptBeat=this.host.replayPromptOnChoose?this.promptBeatOf(s)??null:null,this.pendingPromptOwnerId=this.pendingPromptBeat?s.id:null,this.enterChild(s)}isEnded(){return this.flowEnded}getProperty(e){let{scope:t,name:r}=this.splitRef(e);return t==="patter"?this.patterResolver.get(r):t==="scene"?this.sceneResolver.get(r):this.host.shared.get(t,r)}setProperty(e,t){let{scope:r,name:s}=this.splitRef(e);if(r==="patter")this.patterResolver.set(s,t);else if(r==="scene"){if(this.currentSceneId===null)throw new Error(`\'${e}\': the flow has not entered a scene yet`);this.sceneResolver.set(s,t)}else this.host.shared.set(r,s,t)}snapshot(){return{scopes:this.local.save(),sceneBags:Object.fromEntries([...this.sceneBags].map(([e,t])=>[e,{...t}])),rngState:this.rngState,visits:Object.fromEntries(this.visitCounts),cursor:{flowEnded:this.flowEnded,currentSceneId:this.currentSceneId,stack:this.stack.map(e=>{let t=this.childrenOf(e.containerId)?.[e.index];return t?{...e,nextId:t.id}:{...e}}),activeSnippetId:this.activeSnippet?.id??null,beatIndex:this.beatIndex,pendingChoice:this.pendingChoice?{groupId:this.pendingChoice.groupId,options:this.pendingChoice.options.map(e=>({...e}))}:null,pendingPromptOwnerId:this.pendingPromptOwnerId,selectors:pe(this.selectors)}}}restore(e){this.rngState=e.rngState>>>0,this.visitCounts=new Map(Object.entries(e.visits??{}));let t=e.cursor;if(this.started=!0,this.flowEnded=t.flowEnded,this.beatIndex=t.beatIndex,this.currentSceneId=t.currentSceneId,this.stack=t.stack.map(r=>{let{nextId:s,...i}=r;if(s!==void 0){let o=this.childrenOf(i.containerId)?.findIndex(a=>a.id===s)??-1;if(o>=0)return{...i,index:o}}return{...i}}),this.sceneBags=new Map(Object.entries(e.sceneBags??{}).map(([r,s])=>[r,{...s}])),this.local=this.freshLocal(),this.local.load(e.scopes),this.activeSnippet=null,t.activeSnippetId!==null){let r=this.host.nodeIndex.get(t.activeSnippetId);r&&r.type==="snippet"&&(this.activeSnippet=r)}if(this.selectors=de(t.selectors),this.pendingChoice=null,t.pendingChoice!==null){let r=new Map,s=[];for(let i of t.pendingChoice.options){let o=this.host.nodeIndex.get(i.id);o&&(r.set(i.id,o),s.push({...i}))}s.length>0&&(this.pendingChoice={groupId:t.pendingChoice.groupId,options:s,byId:r})}if(this.pendingPromptBeat=null,this.pendingPromptOwnerId=t.pendingPromptOwnerId??null,this.pendingPromptOwnerId){let r=this.host.nodeIndex.get(this.pendingPromptOwnerId);this.pendingPromptBeat=r?this.promptBeatOf(r)??null:null,this.pendingPromptBeat||(this.pendingPromptOwnerId=null)}}enterSceneSetup(e){let t=this.host.bundle.scenes[e];if(!t)throw new Error(`unknown scene: ${e}`);this.currentSceneId=e,this.enter(e),this.seedScene(t),this.runEffects(t.onEntry)}enterChild(e){if(this.enter(e.id),e.type==="snippet"){this.beginSnippet(e);return}let t=e.selector??"run";if(t==="run"){this.stack.push({sceneId:this.currentSceneId,containerId:e.id,index:0});return}if(t==="choice"){this.setupChoice(e);return}let r=this.selectChild(e);r&&this.enterChild(r)}childrenOf(e){let t=this.host.blockById.get(e);if(t)return t.children;let r=this.host.nodeIndex.get(e);if(r&&r.type==="group")return r.children}beginSnippet(e){this.runEffects(e.onEnter),this.activeSnippet=e,this.beatIndex=0}setupChoice(e){let t=[],r=new Map,s=[];for(let o of e.children){if(o.fallback===!0){s.push(o);continue}if(o.sticky!==!0&&(this.visitCounts.get(o.id)??0)>=1)continue;let a=this.eligible(o),c=o.secretUntilEligible===!0;!a&&c||(t.push({id:o.id,prompt:this.promptFor(o),eligible:a,gameData:o.gameData}),r.set(o.id,o))}if(t.length>0){this.pendingChoice={groupId:e.id,options:t,byId:r};return}let i=s.find(o=>this.eligible(o));if(i){this.enterChild(i);return}this.host.onDryChoice?.(e.id)}resolveJump(e){e&&this.enterTarget(e.to,e.mode==="call"?"call":"jump")}enterTarget(e,t){if(e==="END"){this.flowEnded=!0,this.stack=[];return}let r,s,i=this.host.bundle.scenes[e];if(i){this.enterSceneSetup(e);let a=i.blocks[0];if(!a){t==="jump"&&(this.stack=[]);return}r=e,s=a.id}else{let a=this.host.blockIndex.get(e);if(!a)throw new Error(`jump target not found: ${e}`);a.sceneId!==this.currentSceneId&&this.enterSceneSetup(a.sceneId),r=a.sceneId,s=e}this.enter(s);let o={sceneId:r,containerId:s,index:0};t==="call"?this.stack.push(o):this.stack=[o]}selectChild(e){let t=e.children.filter(s=>this.eligible(s));if(t.length===0)return null;let r=this.selectorState(e);switch(e.selector){case"branch":return t[0];case"sequence":{let s=e.options?.order??"sequential",i=e.options?.exhaust??"once";return s==="shuffle"?this.pickShuffle(t,i,r):s==="specificity"?this.pickSpecificity(t,i,r):this.pickSequential(t,i,r)}default:return null}}pickSequential(e,t,r){let s=e.length,i=r.seq??0;return r.seq=i+1,t==="repeat"?e[i%s]:i<s?e[i]:t==="stick"?e[s-1]:null}pickShuffle(e,t,r){let s=e.length,i=t==="stick",o=()=>(i?e.slice(0,s-1):e).map(g=>g.id);if(r.bag===void 0&&(r.bag=o()),r.bag.length===0){if(t==="once")return null;if(i){let g=e[s-1];return r.last=g.id,g}r.bag=o()}let a=r.bag,c=r.last!==void 0&&a.length>1?a.indexOf(r.last):-1,d=Math.floor(this.rng()*(c>=0?a.length-1:a.length));c>=0&&d>=c&&d++;let p=a[d];return a.splice(d,1),r.last=p,e.find(g=>g.id===p)}pickSpecificity(e,t,r){let s=e;if(t!=="repeat"){r.bag===void 0&&(r.bag=e.map(p=>p.id));let d=new Set(r.bag);if(s=e.filter(p=>d.has(p.id)),s.length===0)return t==="stick"&&r.last!==void 0?e.find(p=>p.id===r.last)??null:null}let i=-1,a=s.map(d=>{let p=this.specScore(d);return p>i&&(i=p),{c:d,s:p}}).filter(d=>d.s===i).map(d=>d.c),c;if(a.length===1)c=a[0];else{let d=r.last!==void 0?a.findIndex(g=>g.id===r.last):-1,p=Math.floor(this.rng()*(d>=0?a.length-1:a.length));d>=0&&p>=d&&p++,c=a[p]}return t!=="repeat"&&(r.bag=r.bag.filter(d=>d!==c.id)),r.last=c.id,c}specScore(e){return e.condition?this.matchedSpec(this.conditionAst(e.condition),!0):0}matchedSpec(e,t){return Y(e,s=>le(D(s,this.evalCtx,L)),{want:t})}selectorState(e){let t=e.shared?this.host.sharedSelectors:this.selectors,r=t.get(e.id);return r||(r={},t.set(e.id,r)),r}runEffects(e){for(let t of e??[])this.setProperty(t.target,this.evalExpr(t.value))}eligible(e){return e.condition?le(this.evalExpr(e.condition)):!0}evalExpr(e){return D(this.conditionAst(e),this.evalCtx,L)}conditionAst(e){let t=ie.get(e);return t||(t=v(e.ast),ie.set(e,t)),t}enter(e){this.visitCounts.set(e,(this.visitCounts.get(e)??0)+1),this.host.sharedVisits.set(e,(this.host.sharedVisits.get(e)??0)+1)}rng=()=>{if(this.host.customRng)return this.host.customRng();let e=this.rngState+1831565813|0;this.rngState=e;let t=Math.imul(e^e>>>15,1|e);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/4294967296};beatResult(e){let t=this.host.tagIndex.get(e.id),r=t&&t.length?{tags:t}:{};switch(e.kind){case"gameEvent":return{type:"gameEvent",id:e.id,gameData:e.gameData,...r};case"text":return{type:"text",id:e.id,text:this.interpolate(this.resolveString(e.id)),gameData:e.gameData,...r};case"line":{let s=this.resolveString(e.id),i=!this.host.captionsOn,a=i&&e.character===this.host.captionCharacter?"":this.captionLine(this.host.bundle.voiced?s:this.interpolate(s)),c=i&&a.length===0;return{type:"line",id:e.id,text:a,character:c?void 0:e.character,characterName:c?void 0:this.resolveCharacterName(e.character),direction:c?void 0:e.direction,gameData:e.gameData,...r}}}}interpolate(e){return ne(e,t=>this.getProperty(t))}stripCaptions(e){return re(e,this.host.captionOpen,this.host.captionClose)}captionLine(e){return this.host.captionsOn?e:this.stripCaptions(e)}promptFor(e){let t=this.promptBeatOf(e);if(!t)return;let r=this.interpolate(this.resolveString(t.id));return t.kind==="line"?{kind:"line",text:this.captionLine(r),character:t.character,characterName:this.resolveCharacterName(t.character),direction:t.direction}:{kind:"text",text:r}}promptBeatOf(e){return e.type==="group"&&e.prompt?e.prompt:((e.type==="snippet"?e:this.firstTextSnippetIn(e.children))?.beats??[]).find(r=>r.kind==="line"||r.kind==="text")}firstTextSnippetIn(e){let t;return x(e,r=>{!t&&r.type==="snippet"&&(r.beats??[]).some(s=>s.kind==="line"||s.kind==="text")&&(t=r)}),t}resolveString(e){if(this.host.emitIds)return e;let t=this.host.strings[e];if(t!==void 0)return t;let r=this.host.defaultStrings[e];return r!==void 0?`<Untranslated: ${e}> ${r}`:e}resolveCharacterName(e){if(e===void 0||this.host.emitIds)return;let t=$(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.castDisplay.get(e)}splitRef(e){let t=this.host.refSplitCache.get(e);return t||(t=j(e,r=>r==="scene"||this.host.shared.has(r)),this.host.refSplitCache.set(e,t)),t}freshLocal(){return new C().defineOwned("patter",this.host.patterLocalDecls)}seedScene(e){let t=this.host.sceneSharedNames.get(e.id)??new Set;if(!this.sceneBags.has(e.id)){let r={};for(let s of e.sceneProps??[]){let i=s.name.toLowerCase();t.has(i)||(r[i]=q(s))}this.sceneBags.set(e.id,r)}if(!this.host.stageBags.has(e.id)){let r={};for(let s of e.sceneProps??[]){let i=s.name.toLowerCase();t.has(i)&&(r[i]=q(s))}this.host.stageBags.set(e.id,r)}for(let r of e.sceneProps??[]){if(!r.temporary)continue;let s=r.name.toLowerCase(),i=t.has(s)?this.host.stageBags.get(e.id):this.sceneBags.get(e.id);i&&(i[s]=q(r))}}};function oe(n,e){x(n,t=>{if(t.type==="group"){t.prompt?.kind==="line"&&t.prompt.character&&e.add(t.prompt.character);return}for(let r of t.beats??[])r.kind==="line"&&r.character&&e.add(r.character)})}function pe(n){let e={};for(let[t,r]of n){let s={};r.seq!==void 0&&(s.seq=r.seq),r.bag&&(s.bag=[...r.bag]),r.last!==void 0&&(s.last=r.last),e[t]=s}return e}function de(n){let e=new Map;for(let[t,r]of Object.entries(n??{})){let s={};r.seq!==void 0&&(s.seq=r.seq),r.bag&&(s.bag=[...r.bag]),r.last!==void 0&&(s.last=r.last),e.set(t,s)}return e}function ae(n){return{name:n.name,type:n.type,values:n.values,stages:n.stages,default:n.default}}function Ne(n){if(n.default!==void 0)return n.default;switch(n.type){case"number":return 0;case"string":return"";case"flags":return[];case"enum":return n.values?.[0]??"";case"quality":return n.stages?.[0]??"";default:return!1}}function ce(n){return{name:n.name,type:n.type,values:n.values,stages:n.stages,default:n.default,writable:n.writable}}function Ae(n){if(n.default!==void 0)return n.default;switch(n.type){case"boolean":return!1;case"number":return 0;case"string":return"";case"flags":return[];case"enum":return n.values?.[0]??"";case"quality":return n.stages?.[0]??""}}function Fe(n){let e=r=>r.toLowerCase(),t=new Map;for(let r of n)t.set(e(r.name),Ae(r));return{get:r=>t.get(e(r)),set:(r,s)=>{t.set(e(r),s)}}}function q(n){if(n.default!==void 0)return n.default;switch(n.type){case"boolean":return!1;case"number":return 0;case"string":return"";case"flags":return[];case"enum":return n.values?.[0]??"";case"quality":return n.stages?.[0]??""}}function le(n){return typeof n=="boolean"?n:typeof n=="number"?n!==0:typeof n=="string"?n!=="":n.length>0}var Ge=(n,e)=>n.shared??e;function H(n,e){return{name:n.name,type:n.type,hasDefault:n.default!==void 0,...n.default!==void 0?{default:n.default}:{},shared:Ge(n,e)}}function Te(n){return{name:n.name,type:n.type,hasDefault:n.default!==void 0,...n.values?{values:[...n.values]}:{},...n.purpose?{purpose:n.purpose}:{}}}function Ve(n,e){e.blocks++;let t=[...n.children];for(;t.length;){let r=t.pop();if(r.type==="group"){e.groups++,r.prompt&&e.prompts++,t.push(...r.children);continue}e.snippets++;for(let s of r.beats??[])e.beats++,s.kind==="gameEvent"&&e.gameEvents++}}function ue(n){let e={scenes:0,blocks:0,groups:0,snippets:0,beats:0,prompts:0,gameEvents:0,cast:n.cast?.length??0},t=[],r=[];for(let o of Object.values(n.scenes)){e.scenes++;let a=f(o);t.push({gameId:a,name:o.name,blocks:o.blocks.map(c=>({gameId:f(c),name:c.name}))});for(let c of o.blocks)Ve(c,e);o.sceneProps?.length&&r.push({gameId:a,properties:o.sceneProps.map(c=>H(c,!1))})}let s=(n.scopeRegistry?.scopes??[]).map(o=>({token:o.token,writable:o.writable??!0,opaque:o.declarations===void 0,properties:(o.declarations??[]).map(a=>H(a,!0))})),i=Object.entries(n.gameDataFields??{}).filter(([,o])=>(o?.length??0)>0).map(([o,a])=>({kind:o,fields:(a??[]).map(Te)}));return{identity:{schema:n.schema,project:n.content.project,...n.content.version!==void 0?{version:n.content.version}:{},...n.content.hash!==void 0?{hash:n.content.hash}:{},...n.content.structureHash!==void 0?{structureHash:n.content.structureHash}:{},voiced:n.voiced,defaultLocale:n.locales.default,locales:[...n.locales.included],localisation:n.localisation?.mode??"embedded",sourceDebug:n.localisation?.sourceDebug??!1},addresses:t,hostScopes:s,properties:{patter:(n.properties??[]).map(o=>H(o,!0)),scene:r},gameData:i,counts:e}}function ge(n,e){return n.gameDataFields?.[e]??[]}function U(n,e,t){return e&&Object.prototype.hasOwnProperty.call(e,t)?e[t]:n.find(r=>r.name===t)?.default}function fe(n,e){let t={};for(let r of n){let s=U(n,e,r.name);s!==void 0&&(t[r.name]=s)}for(let[r,s]of Object.entries(e??{}))r in t||(t[r]=s);return t}return xe(Me);})();\n//# sourceMappingURL=patterplay.min.js.map';
195012
+ var PLAYABLE_RUNTIME_JS = '"use strict";var Patterplay=(()=>{var G=Object.defineProperty;var ve=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var we=Object.prototype.hasOwnProperty;var xe=(n,e)=>{for(var t in e)G(n,t,{get:e[t],enumerable:!0})},ke=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of be(e))!we.call(n,s)&&s!==t&&G(n,s,{get:()=>e[s],enumerable:!(r=ve(e,s))||r.enumerable});return n};var Ce=n=>ke(G({},"__esModule",{value:!0}),n);var Le={};xe(Le,{Engine:()=>A,Flow:()=>k,buildTagIndex:()=>N,describeBundle:()=>fe,effectiveGameData:()=>me,gameDataFields:()=>he,gameDataValue:()=>K});function v(n){switch(n[0]){case"b":return{kind:"bool",value:n[1]};case"n":return{kind:"number",value:n[1]};case"s":return{kind:"string",value:n[1]};case"sv":return{kind:"scopedvar",scope:n[1],name:n[2]};case"u":return{kind:"unary",op:n[1],operand:v(n[2])};case"bin":return{kind:"binary",op:n[1],left:v(n[2]),right:v(n[3])};case"call":{let e=n.slice(2).map(v);return{kind:"call",name:n[1],args:e}}case"fd":return{kind:"flagdelta",sign:n[1],name:n[2]}}}var l=class extends Error{constructor(e){super(e),this.name="EvalError"}};function I(n,e,t){let r=new Map(t.scopes.map(i=>[i.token,i.missing??"false"])),s=i=>{switch(i.kind){case"bool":return i.value;case"number":return i.value;case"string":return i.value;case"scopedvar":{let o=e.scopes[i.scope];if(o===void 0)return!1;let a=typeof o.get=="function"?o.get(i.name):o[i.name];if(a===void 0){if(r.get(i.scope)==="throw")throw new l(`@${i.scope}.${i.name} is not declared on the current ${i.scope}.`);return!1}return a}case"call":{if(i.name==="advance"&&!t.functions[i.name]){let a=i.args[0];if(i.args.length!==1||a===void 0)throw new l(`advance() takes exactly 1 argument, got ${i.args.length}`);let c=V(a,e);if(c===void 0)throw new l("advance() needs a quality reference (@scope.name of a quality property)");let d=S(s(a),c,"advance");return c[Math.min(d+1,c.length-1)]}let o=t.functions[i.name];if(!o)throw new l(`unknown function \'${i.name}\'`);return o.eval(i.args,{evaluate:s,ctx:e})}case"flagdelta":throw new l("flagdelta node is only valid as an argument to a flag-delta function");case"unary":{if(i.op==="not"){let a=s(i.operand);if(typeof a!="boolean")throw new l(`\'not\' requires a boolean operand, got ${typeof a}`);return!a}let o=s(i.operand);if(typeof o!="number")throw new l(`unary \'-\' requires a numeric operand, got ${typeof o}`);return-o}case"binary":{if(i.op==="and"){let g=s(i.left);if(typeof g!="boolean")throw new l(`\'and\' requires boolean operands, left is ${typeof g}`);if(!g)return!1;let h=s(i.right);if(typeof h!="boolean")throw new l(`\'and\' requires boolean operands, right is ${typeof h}`);return h}if(i.op==="or"){let g=s(i.left);if(typeof g!="boolean")throw new l(`\'or\' requires boolean operands, left is ${typeof g}`);if(g)return!0;let h=s(i.right);if(typeof h!="boolean")throw new l(`\'or\' requires boolean operands, right is ${typeof h}`);return h}let o=s(i.left),a=s(i.right),c=V(i.left,e),d=V(i.right,e),p=c??d;if(p!==void 0){if(c&&d&&!Ee(c,d)&&(i.op===">"||i.op===">="||i.op==="<"||i.op==="<="))throw new l(`\'${i.op}\' compares two different qualities, whose stage orders are unrelated`);switch(i.op){case">":return S(o,p,">")>S(a,p,">");case">=":return S(o,p,">=")>=S(a,p,">=");case"<":return S(o,p,"<")<S(a,p,"<");case"<=":return S(o,p,"<=")<=S(a,p,"<=");case"+":case"-":case"*":case"/":throw new l(`\'${i.op}\' cannot be applied to a quality - a stage is a position, not a number; use advance() to move it`);default:break}}switch(i.op){case"==":return Z(o,a);case"!=":return!Z(o,a);case">":return b(o,a,">"),o>a;case">=":return b(o,a,">="),o>=a;case"<":return b(o,a,"<"),o<a;case"<=":return b(o,a,"<="),o<=a;case"+":if(typeof o=="number"&&typeof a=="number"||typeof o=="string"&&typeof a=="string")return o+a;throw new l(`\'+\' requires two numbers or two strings, got ${typeof o} and ${typeof a}`);case"-":return b(o,a,"-"),o-a;case"*":return b(o,a,"*"),o*a;case"/":if(b(o,a,"/"),a===0)throw new l("division by zero");return o/a}}}};return s(n)}function Z(n,e){if(Array.isArray(n)||Array.isArray(e)){if(!Array.isArray(n)||!Array.isArray(e)||n.length!==e.length)return!1;let t=[...n].sort(),r=[...e].sort();for(let s=0;s<t.length;s++)if(t[s]!==r[s])return!1;return!0}return n===e}function b(n,e,t){if(typeof n!="number"||typeof e!="number")throw new l(`\'${t}\' requires numeric operands, got ${typeof n} and ${typeof e}`)}function V(n,e){if(!(n.kind!=="scopedvar"||e.qualities===void 0))return e.qualities(n.scope,n.name)}function S(n,e,t){if(typeof n!="string")throw new l(`\'${t}\' on a quality compares stages, got ${typeof n}`);let r=e.indexOf(n);if(r<0)throw new l(`"${n}" is not a stage of this quality (stages: ${e.join(", ")})`);return r}var Ee=(n,e)=>n.length===e.length&&n.every((t,r)=>t===e[r]);function C(n){if(Number.isNaN(n)||!Number.isFinite(n))return 0;let e=Math.trunc(n)%4294967296;return e<0?e+4294967296:e}function M(n){let e=C(n);return{next(){e=e+1831565813>>>0;let t=Math.imul(e^e>>>15,1|e);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/4294967296},state(){return e}}}var De={name:"check_flags",count:n=>Math.max(1,n.args.length-1)},Ie=[De];function Q(n,e,t){let r=t?.countingCalls??Ie;return R(n,t?.want??!0,e,r)}function R(n,e,t,r){if(n.kind==="binary"&&(n.op==="and"||n.op==="or")){let s=R(n.left,e,t,r),i=R(n.right,e,t,r);return n.op==="and"===e?s>0&&i>0?s+i:0:Math.max(s,i)}if(n.kind==="unary"&&n.op==="not")return R(n.operand,!e,t,r);if(n.kind==="call"){let s=r.find(i=>i.name===n.name);if(s){let i=s.count(n),o=t(n);return e?o?i:0:o?0:1}}return t(n)===e?1:0}var L=class n{values={};decls=new Map;subscribers=new Set;auditors=new Set;norm;constructor(e=[],t){this.norm=t?.normalise??(r=>r.toLowerCase()),this.seed(e)}seed(e){for(let t of e){let r=this.norm(t.name);this.decls.set(r,t),this.values[r]=structuredClone(t.default??te(t))}}get(e){return this.values[this.norm(e)]}set(e,t,r){let s=this.norm(e);if(this.decls.get(s)?.writable===!1)throw new Error(`\'${e}\' is read-only`);let i={name:s,prev:this.values[s],next:t,silent:r?.silent??!1,reason:r?.reason};this.values[s]=t;for(let o of this.auditors)o(i);if(!i.silent)for(let o of this.subscribers)o(i);return i}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}onAudit(e){return this.auditors.add(e),()=>this.auditors.delete(e)}rows(){return[...this.decls.entries()].map(([e,t])=>ee(t,this.get(e),void 0,e))}declarations(){return[...this.decls.values()]}clone(){let e=new n([],{normalise:this.norm});return e.decls=new Map(this.decls),Object.assign(e.values,structuredClone(this.values)),e}reseed(e){for(let t of Object.keys(this.values))delete this.values[t];this.decls.clear(),this.seed(e)}save(){return structuredClone(this.values)}load(e){for(let[t,r]of Object.entries(e))this.values[this.norm(t)]=r}};function ee(n,e,t,r){return{name:r??n.name.toLowerCase(),type:n.type,value:e,default:n.default??te(n),...n.values!==void 0?{values:n.values}:{},writable:t??n.writable??!0}}var j=1,E=class{scopes=new Map;defineOwned(e,t){return this.mountOwned(e,new L(t))}mountOwned(e,t){return this.assertFree(e),this.scopes.set(e,{kind:"owned",bag:t}),this}ownedBag(e){let t=this.scopes.get(e);if(!t||t.kind!=="owned")throw new Error(`\'@${e}\' is not an owned scope`);return t.bag}reseedOwned(e,t){return this.ownedBag(e).reseed(t),this}defineForeign(e,t,r=[],s=!0){this.assertFree(e);let i=new Map;for(let o of r)i.set(o.name.toLowerCase(),o);return this.scopes.set(e,{kind:"foreign",resolver:t,decls:i,scopeWritable:s}),this}has(e){return this.scopes.has(e)}get(e,t){let r=this.scopes.get(e);if(r)return r.kind==="owned"?r.bag.get(t):r.resolver.get(t.toLowerCase())}set(e,t,r){let s=this.scopes.get(e);if(!s)throw new Error(`unknown scope \'@${e}\'`);if(s.kind==="owned"){try{s.bag.set(t,r)}catch{throw new Error(`\'@${e}.${t}\' is read-only`)}return}let i=t.toLowerCase();if(!this.foreignWritable(s,i))throw new Error(`\'@${e}.${t}\' is read-only`);s.resolver.set(i,r)}foreignWritable(e,t){return e.resolver.set?e.decls.get(t)?.writable??e.scopeWritable:!1}listProperties(){let e=[];for(let[t,r]of this.scopes)if(r.kind==="owned")for(let s of r.bag.rows())e.push({scope:t,...s});else for(let s of r.decls.values())e.push({scope:t,...ee(s,r.resolver.get(s.name.toLowerCase()),this.foreignWritable(r,s.name.toLowerCase()))});return e}toEvalContext(e){let t={};for(let[s,i]of this.scopes)t[s]=i.kind==="owned"?i.bag.values:i.resolver;let r=this.qualityLadders();return r.size===0?{scopes:t,host:e}:{scopes:t,host:e,qualities:(s,i)=>r.get(s)?.get(i.toLowerCase())}}qualityLadders(){let e=new Map;for(let[t,r]of this.scopes){let s=r.kind==="owned"?r.bag.declarations():[...r.decls.values()];for(let i of s){if(i.type!=="quality"||i.stages===void 0)continue;let o=e.get(t);o||(o=new Map,e.set(t,o)),o.set(i.name.toLowerCase(),i.stages)}}return e}toSchema(){let e=new Map;for(let[t,r]of this.scopes){let s=r.kind==="owned"?r.bag.declarations():[...r.decls.values()];if(s.length===0)continue;let i=new Map;for(let o of s)i.set(o.name.toLowerCase(),{type:o.type,enumValues:o.values,...o.stages!==void 0?{stages:o.stages}:{}});e.set(t,i)}return{properties:e}}save(){let e={};for(let[t,r]of this.scopes)r.kind==="owned"&&(e[t]=r.bag.save());return e}load(e){for(let[t,r]of Object.entries(e)){let s=this.scopes.get(t);s?.kind==="owned"&&s.bag.load(r)}}saveFragment(){return{version:j,scopes:this.save()}}loadFragment(e){if(e.version!==j)throw new Error(`unsupported owned-state fragment version ${e.version} (supported: ${j})`);this.load(e.scopes)}assertFree(e){if(this.scopes.has(e))throw new Error(`scope \'@${e}\' is already registered`)}};function te(n){if(n.default!==void 0)return n.default;switch(n.type){case"boolean":return!1;case"number":return 0;case"string":return"";case"enum":return n.values?.[0]??"";case"flags":return[];case"quality":return n.stages?.[0]??""}}function D(n){return n.ctx.host??{}}var $={defaultScope:"patter",scopes:[{token:"patter"},{token:"scene"}],functions:{random:{minArgs:2,maxArgs:2,returnType:"number",eval(n,e){if(n.length!==2)throw new l("random(a, b) requires exactly 2 arguments");let t=D(e).nextRandom;if(!t)throw new l("random() called without a PRNG in context");let r=e.evaluate(n[0]),s=e.evaluate(n[1]);if(typeof r!="number"||typeof s!="number")throw new l("random(a, b) arguments must be numbers");if(!Number.isInteger(r)||!Number.isInteger(s))throw new l("random(a, b) arguments must be integers");let i=Math.min(r,s),o=Math.max(r,s);return Math.floor(t()*(o-i+1))+i}},check_flags:{minArgs:1,returnType:"boolean",flagDeltaArgs:!0,validate:ne("check_flags"),eval(n,e){let t=re(n[0],e,"check_flags");for(let r=1;r<n.length;r++){let s=n[r];if(s.kind!=="flagdelta")throw new l("check_flags() flag args must be +flagName or -flagName");if(s.sign==="+"?!t.includes(s.name):t.includes(s.name))return!1}return!0}},set_flags:{minArgs:1,returnType:"flags",flagDeltaArgs:!0,validate:ne("set_flags"),eval(n,e){let t=[...re(n[0],e,"set_flags")];for(let r=1;r<n.length;r++){let s=n[r];if(s.kind!=="flagdelta")throw new l("set_flags() flag args must be +flagName or -flagName");if(s.sign==="+")t.includes(s.name)||t.push(s.name);else{let i=t.indexOf(s.name);i>=0&&t.splice(i,1)}}return t}},visits:{minArgs:1,maxArgs:1,returnType:"number",validate:O("visits"),eval:(n,e)=>D(e).visits?.(B(n,e,"visits"))??0},seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:O("seen"),eval:(n,e)=>(D(e).visits?.(B(n,e,"seen"))??0)>0},patter_visits:{minArgs:1,maxArgs:1,returnType:"number",validate:O("patter_visits"),eval:(n,e)=>D(e).patterVisits?.(B(n,e,"patter_visits"))??0},patter_seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:O("patter_seen"),eval:(n,e)=>(D(e).patterVisits?.(B(n,e,"patter_seen"))??0)>0}}};function q(n,e){let t=n.replace(/^@/,"").split(".");return t.length===2&&e(t[0])?{scope:t[0],name:t[1].toLowerCase()}:{scope:"patter",name:t.join(".").toLowerCase()}}function B(n,e,t){let r=e.evaluate(n[0]);if(typeof r!="string")throw new l(`${t}(id) requires a string node id`);return r}function O(n){return(e,t)=>{let r=e[0];r&&r.kind!=="string"&&t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${n}(id): the argument must be a string id literal (a scene / block / node id)`})}}function re(n,e,t){if(!n)throw new l(`${t}() requires at least one argument (the flags variable)`);let r=e.evaluate(n);if(Array.isArray(r))return r;if(r===!1||r===null||r===void 0)return[];throw new l(`${t}() first argument must be a flags property`)}function ne(n){return(e,t)=>{if(e.length===0)return;let r=e[0];if(r.kind!=="scopedvar"){t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${n}(): first argument must be a flags property reference (@name or @scope.name)`});return}let s=t.schema.properties.get(r.scope)?.get(r.name);if(s&&s.type!=="flags"){let i=r.scope===t.defaultScope?r.name:`${r.scope}.${r.name}`;t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${n}(): \'@${i}\' is not a flags property (got ${s.type})`});return}for(let i=1;i<e.length;i++){let o=e[i];o.kind!=="flagdelta"?t.report({path:[...t.path,"args",i],kind:"wrong-arg-type",severity:"error",message:`${n}(): argument ${i+1} must be +flagName or -flagName`}):s?.type==="flags"&&s.enumValues&&!s.enumValues.includes(o.name)&&t.report({path:[...t.path,"args",i],kind:"unknown-flag-name",severity:"error",message:`${n}(): unknown flag \'${o.name}\'`,reference:o.name})}}}var Re=/^@[A-Za-z0-9_.]+$/;function*Be(n){let e="",t=0;for(;t<n.length;){let r=n[t];if(r==="{"&&n[t+1]==="{"){e+="{",t+=2;continue}if(r==="}"&&n[t+1]==="}"){e+="}",t+=2;continue}if(r==="{"){let s=n.indexOf("}",t+1);if(s!==-1){let i=n.slice(t,s+1),o=n.slice(t+1,s).trim();if(o.startsWith("@")){e&&(yield{kind:"text",value:e},e=""),yield{kind:"slot",raw:i,inner:o,ref:Re.test(o)?o:void 0},t=s+1;continue}e+=i,t=s+1;continue}}e+=r,t+=1}e&&(yield{kind:"text",value:e})}function Oe(n){return Array.isArray(n)?n.join(", "):typeof n=="boolean"?n?"true":"false":String(n)}function Pe(n){return n===" "||n===" "||n===`\n`||n==="\\r"||n==="\\f"||n==="\\v"}function Ne(n){let e="",t=!1;for(let r of n){if(Pe(r)){t=!0;continue}t&&e.length>0&&(e+=" "),t=!1,e+=r}return e}function se(n,e,t){if(e.length===0||n.indexOf(e)<0)return n;let r="",s=0,i=!1;for(;s<n.length;){if(n.startsWith(e,s)){let o=n.indexOf(t,s+e.length);if(o>=0){s=o+t.length,i=!0;continue}r+=n.slice(s);break}r+=n[s],s+=1}return i?Ne(r):n}function ie(n,e){if(n.indexOf("{")<0)return n;let t="";for(let r of Be(n)){if(r.kind==="text"){t+=r.value;continue}if(!r.ref){t+=r.raw;continue}let s=e(r.ref);t+=s===void 0?"":Oe(s)}return t}function x(n,e){for(let t of n){e(t);let r=t.children;r&&x(r,e)}}function Ae(n){return n.toLowerCase().replace(/[\'\u2019]/g,"").replace(/[^a-z0-9-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function f(n){let e=n.gameId?.trim();return e||Ae(n.name)}function _(n){return`cast:${n}`}var H={open:"[",close:"]"},oe="SFX";function P(n){let e=new Set,t=[];for(let r of n)e.has(r)||(e.add(r),t.push(r));return t}function N(n){let e=new Map,t=(r,s)=>{let i=P([...s,...r.tags??[]]);if(e.set(r.id,i),r.type==="group")for(let o of r.children)t(o,i);else for(let o of r.beats??[])e.set(o.id,P([...i,...o.tags??[]]))};for(let r of Object.values(n.scenes)){let s=P(r.tags??[]);e.set(r.id,s);for(let i of r.blocks){let o=P([...s,...i.tags??[]]);e.set(i.id,o);for(let a of i.children)t(a,o)}}return e}var ae=new WeakMap,A=class n{host;defaultSeed;flowsById=new Map;allStrings;currentLocale;sourceDebug;sceneGameIdToId=new Map;blockGameIdToId=new Map;creationOptions;constructor(e,t={}){this.creationOptions=t;let r=t.locale??e.locales.default,s=e.strings;this.allStrings=s,this.currentLocale=r;let i=s[r]??{},o=s[e.locales.default]??{},a=e.localisation,c=a?.mode==="ids"&&!a.sourceDebug;this.sourceDebug=a?.mode==="ids"&&!!a.sourceDebug,this.sourceDebug&&typeof console<"u"&&console.warn("[Patterplay] source-only DEBUG build: strings are the source language for debugging, not a shippable localised build.");let d=new Map;for(let u of e.cast??[])u.displayName&&d.set(u.name,u.displayName);this.defaultSeed=(t.seed??2654435769)>>>0;let p=new Map,g=new Map,h=new Map;for(let[u,y]of Object.entries(e.scenes)){this.sceneGameIdToId.set(f(y),u);let w=new Map;for(let m of y.blocks)g.set(m.id,{sceneId:u}),h.set(m.id,m),w.set(f(m),m.id),x(m.children,X=>p.set(X.id,X));this.blockGameIdToId.set(u,w)}let J=e.properties??[],F=J.filter(u=>u.shared??!0).map(le),Se=J.filter(u=>!(u.shared??!0)).map(le),ye=new Set(F.map(u=>u.name.toLowerCase())),T=new E().defineOwned("patter",F),z=new Set;if(t.world){let u=e.scopeRegistry?.scopes.find(w=>w.token==="world"),y=(u?.declarations??[]).map(pe);T.defineForeign("world",t.world,y,u?.writable??!0),z.add("world")}for(let u of e.scopeRegistry?.scopes??[]){if(z.has(u.token))continue;let y=(u.declarations??[]).map(pe);T.defineForeign(u.token,Ge(u.declarations??[]),y,u.writable??!0)}let Y=new Map;for(let[u,y]of Object.entries(e.scenes)){let w=new Set((y.sceneProps??[]).filter(m=>m.shared??!1).map(m=>m.name.toLowerCase()));Y.set(u,w)}this.host={bundle:e,emitIds:c,strings:i,defaultStrings:o,castDisplay:d,nodeIndex:p,blockIndex:g,blockById:h,sceneGameIdToId:this.sceneGameIdToId,blockGameIdToId:this.blockGameIdToId,tagIndex:N(e),shared:T,patterSharedDecls:F,patterLocalDecls:Se,patterSharedNames:ye,sceneSharedNames:Y,sharedVisits:new Map,sharedSelectors:new Map,stageBags:new Map,customRng:t.rng,onDryChoice:t.onDryChoice,replayPromptOnChoose:t.replayPromptOnChoose??!1,captionsOn:t.closedCaptions??!0,captionOpen:(e.closedCaptions??H).open,captionClose:(e.closedCaptions??H).close,captionCharacter:e.closedCaptions?.character||oe,refSplitCache:new Map}}get locale(){return this.currentLocale}get isSourceDebug(){return this.sourceDebug}setLocale(e){this.currentLocale=e,this.host.strings=this.allStrings[e]??{}}replaceStrings(e){this.allStrings=e.strings,this.host.strings=this.allStrings[this.currentLocale]??{},this.host.defaultStrings=this.allStrings[this.host.bundle.locales.default]??{}}hotSwap(e){let t=this.saveGame(),r=i=>(i.setLocale(this.currentLocale),i.setClosedCaptions(this.host.captionsOn),i),s=new n(e,this.creationOptions);try{return s.loadGame(t),r(s)}catch{let i=new n(e,this.creationOptions);for(let[o,a]of Object.entries(t.flows)){let c=a.cursor.currentSceneId;try{i.openFlow(o,c!==null?{scene:c}:{})}catch{}}return r(i)}}get closedCaptions(){return this.host.captionsOn}setClosedCaptions(e){this.host.captionsOn=e}openFlow(e,t={}){let r=this.resolveSceneRef(t.scene),s=this.resolveBlockRef(r,t.block);this.flowsById.get(e)?.close();let i=new k(e,this.host,t.seed??this.defaultSeed);return this.flowsById.set(e,i),i.start(r,s),i}runFlow(e,t,r){let s=this.flowsById.get(e);if(!s)return this.openFlow(e,{scene:t,block:r}).advanceToStop().played;if(!s.goto(t,r))throw new Error(`runFlow: address not found: ${t}${r===void 0?"":` / ${r}`}`);return s.advanceToStop().played}resolveSceneRef(e){if(e!=null)return this.host.bundle.scenes[e]?e:this.sceneGameIdToId.get(e)??e}resolveBlockRef(e,t){if(t!=null){if(this.host.blockById.has(t))return t;if(e!=null){let r=this.blockGameIdToId.get(e)?.get(t);if(r)return r}return t}}sceneAddress(e){let t=this.host.bundle.scenes[e];return t?f(t):void 0}blockAddress(e){let t=this.host.blockById.get(e);return t?f(t):void 0}tagsForBeat(e){return this.host.tagIndex.get(e)??[]}tagsForScene(e){let t=this.resolveSceneRef(e);return(t!=null?this.host.tagIndex.get(t):void 0)??[]}tagsForBlock(e,t){let r=this.resolveSceneRef(e),s=this.resolveBlockRef(r,t);return(s!=null?this.host.tagIndex.get(s):void 0)??[]}getCast(){let e=[];for(let t of this.host.bundle.cast??[])t?.name&&e.push(t.name);return e}castForScene(e){let t=this.resolveSceneRef(e),r=t!=null?this.host.bundle.scenes[t]:void 0;if(!r)return[];let s=new Set;for(let i of r.blocks)ce(i.children,s);return[...s]}castForBlock(e,t){let r=this.resolveSceneRef(e),s=this.resolveBlockRef(r,t),i=s!=null?this.host.blockById.get(s):void 0;if(!i)return[];let o=new Set;return ce(i.children,o),[...o]}getOutline(){return Object.values(this.host.bundle.scenes).map(e=>({id:e.id,...f(e)?{gameId:f(e)}:{},name:e.name,...this.tagsField(e.id),blocks:e.blocks.map(t=>({id:t.id,...f(t)?{gameId:f(t)}:{},name:t.name,...this.tagsField(t.id),children:t.children.map(r=>this.outlineNode(r))}))}))}getBeatSequence(){let e=[];for(let t of Object.values(this.host.bundle.scenes))for(let r of t.blocks)x(r.children,s=>{if(s.type==="snippet")for(let i of s.beats??[])e.push({sceneId:t.id,blockId:r.id,snippetId:s.id,beat:this.beatInfo(i)})});return e}outlineNode(e){return e.type==="group"?{type:"group",id:e.id,...this.tagsField(e.id),...e.selector?{selector:e.selector}:{},...e.prompt?{prompt:this.beatInfo(e.prompt)}:{},children:e.children.map(t=>this.outlineNode(t))}:{type:"snippet",id:e.id,...this.tagsField(e.id),beats:(e.beats??[]).map(t=>this.beatInfo(t)),...e.jump?{jumpTo:e.jump.to,...e.jump.mode?{jumpMode:e.jump.mode}:{}}:{}}}beatInfo(e){let t=this.host.tagIndex.get(e.id),r={id:e.id,kind:e.kind};if(e.kind==="line"){if(e.character!==void 0){r.character=e.character;let s=this.host.defaultStrings[_(e.character)]??this.host.castDisplay.get(e.character);s!==void 0&&(r.characterName=s)}e.direction!==void 0&&(r.direction=e.direction)}if(e.kind==="line"||e.kind==="text"){let s=this.host.defaultStrings[e.id];s!==void 0&&(r.text=s)}return e.gameData&&Object.keys(e.gameData).length&&(r.gameData=e.gameData),t&&t.length&&(r.tags=t),r}tagsField(e){let t=this.host.tagIndex.get(e);return t&&t.length?{tags:t}:{}}getFlow(e){return this.flowsById.get(e)}flows(){return[...this.flowsById.values()]}closeFlow(e){this.flowsById.get(e)?.close(),this.flowsById.delete(e)}reset(){for(let e of this.flowsById.values())e.close();this.flowsById.clear(),this.host.shared.reseedOwned("patter",this.host.patterSharedDecls),this.host.sharedVisits.clear(),this.host.sharedSelectors.clear(),this.host.stageBags.clear()}getProperty(e){let{scope:t,name:r}=this.splitShared(e);return this.host.shared.get(t,r)}setProperty(e,t){let{scope:r,name:s}=this.splitShared(e);this.host.shared.set(r,s,t)}listProperties(){return this.host.patterSharedDecls.map(e=>({ref:`@${e.name}`,type:e.type,values:e.values,stages:e.stages,value:this.getProperty(`@${e.name}`),default:Fe(e)}))}splitShared(e){let t=this.host.refSplitCache.get(e);if(t||(t=q(e,r=>r==="scene"||this.host.shared.has(r)),this.host.refSplitCache.set(e,t)),t.scope==="scene")throw new Error(`\'${e}\': @scene properties are scene-scoped - read/write them on a Flow, not the Engine`);return t}save(){return this.host.shared.save()}load(e){this.host.shared.load(e)}saveGame(){let e={};for(let[t,r]of this.flowsById)e[t]=r.snapshot();return{version:2,shared:this.host.shared.save(),sharedVisits:Object.fromEntries(this.host.sharedVisits),sharedSelectors:ue(this.host.sharedSelectors),stageBags:Object.fromEntries([...this.host.stageBags].map(([t,r])=>[t,{...r}])),flows:e}}loadGame(e){if(e.version!==2)throw new Error(`unsupported save version: ${e.version}`);this.host.shared.load(e.shared),this.host.sharedVisits.clear();for(let[t,r]of Object.entries(e.sharedVisits??{}))this.host.sharedVisits.set(t,r);this.host.sharedSelectors.clear();for(let[t,r]of ge(e.sharedSelectors))this.host.sharedSelectors.set(t,r);this.host.stageBags.clear();for(let[t,r]of Object.entries(e.stageBags??{}))this.host.stageBags.set(t,{...r});this.flowsById.clear();for(let[t,r]of Object.entries(e.flows)){let s=new k(t,this.host,this.defaultSeed);s.restore(r),this.flowsById.set(t,s)}}},k=class{id;host;local;rngState;started=!1;flowEnded=!1;closed=!1;currentSceneId=null;stack=[];activeSnippet=null;beatIndex=0;pendingChoice=null;pendingPromptBeat=null;pendingPromptOwnerId=null;selectors=new Map;visitCounts=new Map;sceneBags=new Map;patterResolver={get:e=>this.host.patterSharedNames.has(e)?this.host.shared.get("patter",e):this.local.get("patter",e),set:(e,t)=>{this.host.patterSharedNames.has(e)?this.host.shared.set("patter",e,t):this.local.set("patter",e,t)}};sceneResolver={get:e=>{let t=this.currentSceneId;return t===null?void 0:(this.host.sceneSharedNames.get(t)?.has(e)?this.host.stageBags.get(t):this.sceneBags.get(t))?.[e]},set:(e,t)=>{let r=this.currentSceneId;if(r===null)return;let s=this.host.sceneSharedNames.get(r)?.has(e)?this.host.stageBags.get(r):this.sceneBags.get(r);s&&(s[e]=t)}};evalCtx;constructor(e,t,r){this.id=e,this.host=t,this.rngState=C(r),this.local=this.freshLocal();let s={...t.shared.toEvalContext().scopes};s.patter=this.patterResolver,s.scene=this.sceneResolver,this.evalCtx={scopes:s,host:{nextRandom:this.rng,visits:i=>this.visitCounts.get(i)??0,patterVisits:i=>this.host.sharedVisits.get(i)??0},qualities:(i,o)=>this.stagesFor(i,o)}}stagesFor(e,t){let r=t.toLowerCase(),s=i=>i?.find(o=>o.name.toLowerCase()===r&&o.type==="quality")?.stages;if(e==="patter")return s(this.host.patterSharedDecls)??s(this.host.patterLocalDecls);if(e==="scene"){let i=this.currentSceneId!=null?this.host.bundle.scenes[this.currentSceneId]:void 0;return s(i?.sceneProps)}return s(this.host.bundle.scopeRegistry?.scopes.find(i=>i.token===e)?.declarations)}start(e,t){if(this.sceneBags.clear(),this.local=this.freshLocal(),this.selectors.clear(),this.visitCounts.clear(),this.stack=[],this.currentSceneId=null,this.flowEnded=!1,this.activeSnippet=null,this.beatIndex=0,this.pendingChoice=null,this.started=!0,t){let r=this.host.blockIndex.get(t);if(!r)throw new Error(`unknown block: ${t}`);this.enterSceneSetup(r.sceneId),this.stack=[{sceneId:r.sceneId,containerId:t,index:0}],this.enter(t)}else{let r=e??Object.keys(this.host.bundle.scenes)[0],s=r?this.host.bundle.scenes[r]:void 0;if(!s)throw new Error(r?`unknown scene: ${r}`:"no scenes in bundle");this.enterSceneSetup(r);let i=s.blocks[0];i&&(this.stack=[{sceneId:r,containerId:i.id,index:0}],this.enter(i.id))}this.settle()}reset(e,t){this.start(e,t)}goto(e,t){if(this.closed)return!1;if(e==="END")return this.started=!0,this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!0,this.stack=[],!0;let r=this.host.sceneGameIdToId.get(e)??(this.host.bundle.scenes[e]?e:void 0);if(r===void 0)return!1;let s;return t!==void 0&&(s=this.host.blockGameIdToId.get(r)?.get(t)??(this.host.blockIndex.get(t)?.sceneId===r?t:void 0),s===void 0)?!1:this.started?(this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!1,this.enterTarget(s??r,"jump"),this.settle(),!0):(this.start(r,s),!0)}close(){this.closed=!0,this.flowEnded=!0,this.stack=[],this.activeSnippet=null,this.beatIndex=0,this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null}get isClosed(){return this.closed}get currentScene(){return this.currentSceneId}advance(){if(this.closed)return{type:"end"};if(!this.started)throw new Error("flow has not been started");if(this.pendingPromptBeat){let e=this.pendingPromptBeat;return this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.beatResult(e)}return this.settle(),this.flowEnded?{type:"end"}:this.pendingChoice?{type:"choice",groupId:this.pendingChoice.groupId,options:this.pendingChoice.options}:this.activeSnippet?this.beatResult(this.activeSnippet.beats[this.beatIndex++]):(this.flowEnded=!0,{type:"end"})}advanceToStop(){let e=[];for(;;){let t=this.advance();if(t.type==="choice"||t.type==="end")return{played:e,stop:t};e.push(t)}}settle(){let e=0;for(;;){if(++e>1e4)throw new Error("flow did not settle after 10000 transitions - likely a jump cycle with no deliverable content");if(this.flowEnded||this.pendingChoice)return;if(this.activeSnippet){if(this.beatIndex<(this.activeSnippet.beats?.length??0))return;this.runEffects(this.activeSnippet.onExit);let s=this.activeSnippet.jump;this.activeSnippet=null,this.beatIndex=0,this.resolveJump(s);continue}let t=this.stack[this.stack.length-1];if(!t){this.flowEnded=!0;return}t.sceneId!==this.currentSceneId&&(this.currentSceneId=t.sceneId);let r=this.childrenOf(t.containerId);if(!r){this.stack.pop();continue}for(;t.index<r.length&&!this.eligible(r[t.index]);)t.index++;if(t.index>=r.length){this.stack.pop();continue}this.enterChild(r[t.index++])}}getChoices(){return this.pendingChoice?.options??[]}choose(e){let t=this.pendingChoice;if(!t)throw new Error("no choice is pending");let r=t.options.find(i=>i.id===e);if(!r)throw new Error(`unknown choice option: ${e}`);if(!r.eligible)throw new Error(`choice option is not eligible: ${e}`);let s=t.byId.get(e);this.pendingChoice=null,this.pendingPromptBeat=this.host.replayPromptOnChoose?this.promptBeatOf(s)??null:null,this.pendingPromptOwnerId=this.pendingPromptBeat?s.id:null,this.enterChild(s)}isEnded(){return this.flowEnded}getProperty(e){let{scope:t,name:r}=this.splitRef(e);return t==="patter"?this.patterResolver.get(r):t==="scene"?this.sceneResolver.get(r):this.host.shared.get(t,r)}setProperty(e,t){let{scope:r,name:s}=this.splitRef(e);if(r==="patter")this.patterResolver.set(s,t);else if(r==="scene"){if(this.currentSceneId===null)throw new Error(`\'${e}\': the flow has not entered a scene yet`);this.sceneResolver.set(s,t)}else this.host.shared.set(r,s,t)}snapshot(){return{scopes:this.local.save(),sceneBags:Object.fromEntries([...this.sceneBags].map(([e,t])=>[e,{...t}])),rngState:this.rngState,visits:Object.fromEntries(this.visitCounts),cursor:{flowEnded:this.flowEnded,currentSceneId:this.currentSceneId,stack:this.stack.map(e=>{let t=this.childrenOf(e.containerId)?.[e.index];return t?{...e,nextId:t.id}:{...e}}),activeSnippetId:this.activeSnippet?.id??null,beatIndex:this.beatIndex,pendingChoice:this.pendingChoice?{groupId:this.pendingChoice.groupId,options:this.pendingChoice.options.map(e=>({...e}))}:null,pendingPromptOwnerId:this.pendingPromptOwnerId,selectors:ue(this.selectors)}}}restore(e){this.rngState=C(e.rngState),this.visitCounts=new Map(Object.entries(e.visits??{}));let t=e.cursor;if(this.started=!0,this.flowEnded=t.flowEnded,this.beatIndex=t.beatIndex,this.currentSceneId=t.currentSceneId,this.stack=t.stack.map(r=>{let{nextId:s,...i}=r;if(s!==void 0){let o=this.childrenOf(i.containerId)?.findIndex(a=>a.id===s)??-1;if(o>=0)return{...i,index:o}}return{...i}}),this.sceneBags=new Map(Object.entries(e.sceneBags??{}).map(([r,s])=>[r,{...s}])),this.local=this.freshLocal(),this.local.load(e.scopes),this.activeSnippet=null,t.activeSnippetId!==null){let r=this.host.nodeIndex.get(t.activeSnippetId);r&&r.type==="snippet"&&(this.activeSnippet=r)}if(this.selectors=ge(t.selectors),this.pendingChoice=null,t.pendingChoice!==null){let r=new Map,s=[];for(let i of t.pendingChoice.options){let o=this.host.nodeIndex.get(i.id);o&&(r.set(i.id,o),s.push({...i}))}s.length>0&&(this.pendingChoice={groupId:t.pendingChoice.groupId,options:s,byId:r})}if(this.pendingPromptBeat=null,this.pendingPromptOwnerId=t.pendingPromptOwnerId??null,this.pendingPromptOwnerId){let r=this.host.nodeIndex.get(this.pendingPromptOwnerId);this.pendingPromptBeat=r?this.promptBeatOf(r)??null:null,this.pendingPromptBeat||(this.pendingPromptOwnerId=null)}}enterSceneSetup(e){let t=this.host.bundle.scenes[e];if(!t)throw new Error(`unknown scene: ${e}`);this.currentSceneId=e,this.enter(e),this.seedScene(t),this.runEffects(t.onEntry)}enterChild(e){if(this.enter(e.id),e.type==="snippet"){this.beginSnippet(e);return}let t=e.selector??"run";if(t==="run"){this.stack.push({sceneId:this.currentSceneId,containerId:e.id,index:0});return}if(t==="choice"){this.setupChoice(e);return}let r=this.selectChild(e);r&&this.enterChild(r)}childrenOf(e){let t=this.host.blockById.get(e);if(t)return t.children;let r=this.host.nodeIndex.get(e);if(r&&r.type==="group")return r.children}beginSnippet(e){this.runEffects(e.onEnter),this.activeSnippet=e,this.beatIndex=0}setupChoice(e){let t=[],r=new Map,s=[];for(let o of e.children){if(o.fallback===!0){s.push(o);continue}if(o.sticky!==!0&&(this.visitCounts.get(o.id)??0)>=1)continue;let a=this.eligible(o),c=o.secretUntilEligible===!0;!a&&c||(t.push({id:o.id,prompt:this.promptFor(o),eligible:a,gameData:o.gameData}),r.set(o.id,o))}if(t.length>0){this.pendingChoice={groupId:e.id,options:t,byId:r};return}let i=s.find(o=>this.eligible(o));if(i){this.enterChild(i);return}this.host.onDryChoice?.(e.id)}resolveJump(e){e&&this.enterTarget(e.to,e.mode==="call"?"call":"jump")}enterTarget(e,t){if(e==="END"){this.flowEnded=!0,this.stack=[];return}let r,s,i=this.host.bundle.scenes[e];if(i){this.enterSceneSetup(e);let a=i.blocks[0];if(!a){t==="jump"&&(this.stack=[]);return}r=e,s=a.id}else{let a=this.host.blockIndex.get(e);if(!a)throw new Error(`jump target not found: ${e}`);a.sceneId!==this.currentSceneId&&this.enterSceneSetup(a.sceneId),r=a.sceneId,s=e}this.enter(s);let o={sceneId:r,containerId:s,index:0};t==="call"?this.stack.push(o):this.stack=[o]}selectChild(e){let t=e.children.filter(s=>this.eligible(s));if(t.length===0)return null;let r=this.selectorState(e);switch(e.selector){case"branch":return t[0];case"sequence":{let s=e.options?.order??"sequential",i=e.options?.exhaust??"once";return s==="shuffle"?this.pickShuffle(t,i,r):s==="specificity"?this.pickSpecificity(t,i,r):this.pickSequential(t,i,r)}default:return null}}pickSequential(e,t,r){let s=e.length,i=r.seq??0;return r.seq=i+1,t==="repeat"?e[i%s]:i<s?e[i]:t==="stick"?e[s-1]:null}pickShuffle(e,t,r){let s=e.length,i=t==="stick",o=()=>(i?e.slice(0,s-1):e).map(g=>g.id);if(r.bag===void 0&&(r.bag=o()),r.bag.length===0){if(t==="once")return null;if(i){let g=e[s-1];return r.last=g.id,g}r.bag=o()}let a=r.bag,c=r.last!==void 0&&a.length>1?a.indexOf(r.last):-1,d=Math.floor(this.rng()*(c>=0?a.length-1:a.length));c>=0&&d>=c&&d++;let p=a[d];return a.splice(d,1),r.last=p,e.find(g=>g.id===p)}pickSpecificity(e,t,r){let s=e;if(t!=="repeat"){r.bag===void 0&&(r.bag=e.map(p=>p.id));let d=new Set(r.bag);if(s=e.filter(p=>d.has(p.id)),s.length===0)return t==="stick"&&r.last!==void 0?e.find(p=>p.id===r.last)??null:null}let i=-1,a=s.map(d=>{let p=this.specScore(d);return p>i&&(i=p),{c:d,s:p}}).filter(d=>d.s===i).map(d=>d.c),c;if(a.length===1)c=a[0];else{let d=r.last!==void 0?a.findIndex(g=>g.id===r.last):-1,p=Math.floor(this.rng()*(d>=0?a.length-1:a.length));d>=0&&p>=d&&p++,c=a[p]}return t!=="repeat"&&(r.bag=r.bag.filter(d=>d!==c.id)),r.last=c.id,c}specScore(e){return e.condition?this.matchedSpec(this.conditionAst(e.condition),!0):0}matchedSpec(e,t){return Q(e,s=>de(I(s,this.evalCtx,$)),{want:t})}selectorState(e){let t=e.shared?this.host.sharedSelectors:this.selectors,r=t.get(e.id);return r||(r={},t.set(e.id,r)),r}runEffects(e){for(let t of e??[])this.setProperty(t.target,this.evalExpr(t.value))}eligible(e){return e.condition?de(this.evalExpr(e.condition)):!0}evalExpr(e){return I(this.conditionAst(e),this.evalCtx,$)}conditionAst(e){let t=ae.get(e);return t||(t=v(e.ast),ae.set(e,t)),t}enter(e){this.visitCounts.set(e,(this.visitCounts.get(e)??0)+1),this.host.sharedVisits.set(e,(this.host.sharedVisits.get(e)??0)+1)}rng=()=>{if(this.host.customRng)return this.host.customRng();let e=M(this.rngState),t=e.next();return this.rngState=e.state(),t};beatResult(e){let t=this.host.tagIndex.get(e.id),r=t&&t.length?{tags:t}:{};switch(e.kind){case"gameEvent":return{type:"gameEvent",id:e.id,gameData:e.gameData,...r};case"text":return{type:"text",id:e.id,text:this.interpolate(this.resolveString(e.id)),gameData:e.gameData,...r};case"line":{let s=this.resolveString(e.id),i=!this.host.captionsOn,a=i&&e.character===this.host.captionCharacter?"":this.captionLine(this.host.bundle.voiced?s:this.interpolate(s)),c=i&&a.length===0;return{type:"line",id:e.id,text:a,character:c?void 0:e.character,characterName:c?void 0:this.resolveCharacterName(e.character),direction:c?void 0:e.direction,gameData:e.gameData,...r}}}}interpolate(e){return ie(e,t=>this.getProperty(t))}stripCaptions(e){return se(e,this.host.captionOpen,this.host.captionClose)}captionLine(e){return this.host.captionsOn?e:this.stripCaptions(e)}promptFor(e){let t=this.promptBeatOf(e);if(!t)return;let r=this.interpolate(this.resolveString(t.id));return t.kind==="line"?{kind:"line",text:this.captionLine(r),character:t.character,characterName:this.resolveCharacterName(t.character),direction:t.direction}:{kind:"text",text:r}}promptBeatOf(e){return e.type==="group"&&e.prompt?e.prompt:((e.type==="snippet"?e:this.firstTextSnippetIn(e.children))?.beats??[]).find(r=>r.kind==="line"||r.kind==="text")}firstTextSnippetIn(e){let t;return x(e,r=>{!t&&r.type==="snippet"&&(r.beats??[]).some(s=>s.kind==="line"||s.kind==="text")&&(t=r)}),t}resolveString(e){if(this.host.emitIds)return e;let t=this.host.strings[e];if(t!==void 0)return t;let r=this.host.defaultStrings[e];return r!==void 0?`<Untranslated: ${e}> ${r}`:e}resolveCharacterName(e){if(e===void 0||this.host.emitIds)return;let t=_(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.castDisplay.get(e)}splitRef(e){let t=this.host.refSplitCache.get(e);return t||(t=q(e,r=>r==="scene"||this.host.shared.has(r)),this.host.refSplitCache.set(e,t)),t}freshLocal(){return new E().defineOwned("patter",this.host.patterLocalDecls)}seedScene(e){let t=this.host.sceneSharedNames.get(e.id)??new Set;if(!this.sceneBags.has(e.id)){let r={};for(let s of e.sceneProps??[]){let i=s.name.toLowerCase();t.has(i)||(r[i]=U(s))}this.sceneBags.set(e.id,r)}if(!this.host.stageBags.has(e.id)){let r={};for(let s of e.sceneProps??[]){let i=s.name.toLowerCase();t.has(i)&&(r[i]=U(s))}this.host.stageBags.set(e.id,r)}for(let r of e.sceneProps??[]){if(!r.temporary)continue;let s=r.name.toLowerCase(),i=t.has(s)?this.host.stageBags.get(e.id):this.sceneBags.get(e.id);i&&(i[s]=U(r))}}};function ce(n,e){x(n,t=>{if(t.type==="group"){t.prompt?.kind==="line"&&t.prompt.character&&e.add(t.prompt.character);return}for(let r of t.beats??[])r.kind==="line"&&r.character&&e.add(r.character)})}function ue(n){let e={};for(let[t,r]of n){let s={};r.seq!==void 0&&(s.seq=r.seq),r.bag&&(s.bag=[...r.bag]),r.last!==void 0&&(s.last=r.last),e[t]=s}return e}function ge(n){let e=new Map;for(let[t,r]of Object.entries(n??{})){let s={};r.seq!==void 0&&(s.seq=r.seq),r.bag&&(s.bag=[...r.bag]),r.last!==void 0&&(s.last=r.last),e.set(t,s)}return e}function le(n){return{name:n.name,type:n.type,values:n.values,stages:n.stages,default:n.default}}function Fe(n){if(n.default!==void 0)return n.default;switch(n.type){case"number":return 0;case"string":return"";case"flags":return[];case"enum":return n.values?.[0]??"";case"quality":return n.stages?.[0]??"";default:return!1}}function pe(n){return{name:n.name,type:n.type,values:n.values,stages:n.stages,default:n.default,writable:n.writable}}function Te(n){if(n.default!==void 0)return n.default;switch(n.type){case"boolean":return!1;case"number":return 0;case"string":return"";case"flags":return[];case"enum":return n.values?.[0]??"";case"quality":return n.stages?.[0]??""}}function Ge(n){let e=r=>r.toLowerCase(),t=new Map;for(let r of n)t.set(e(r.name),Te(r));return{get:r=>t.get(e(r)),set:(r,s)=>{t.set(e(r),s)}}}function U(n){if(n.default!==void 0)return n.default;switch(n.type){case"boolean":return!1;case"number":return 0;case"string":return"";case"flags":return[];case"enum":return n.values?.[0]??"";case"quality":return n.stages?.[0]??""}}function de(n){return typeof n=="boolean"?n:typeof n=="number"?n!==0:typeof n=="string"?n!=="":n.length>0}var Ve=(n,e)=>n.shared??e;function W(n,e){return{name:n.name,type:n.type,hasDefault:n.default!==void 0,...n.default!==void 0?{default:n.default}:{},shared:Ve(n,e)}}function Me(n){return{name:n.name,type:n.type,hasDefault:n.default!==void 0,...n.values?{values:[...n.values]}:{},...n.purpose?{purpose:n.purpose}:{}}}function je(n,e){e.blocks++;let t=[...n.children];for(;t.length;){let r=t.pop();if(r.type==="group"){e.groups++,r.prompt&&e.prompts++,t.push(...r.children);continue}e.snippets++;for(let s of r.beats??[])e.beats++,s.kind==="gameEvent"&&e.gameEvents++}}function fe(n){let e={scenes:0,blocks:0,groups:0,snippets:0,beats:0,prompts:0,gameEvents:0,cast:n.cast?.length??0},t=[],r=[];for(let o of Object.values(n.scenes)){e.scenes++;let a=f(o);t.push({gameId:a,name:o.name,blocks:o.blocks.map(c=>({gameId:f(c),name:c.name}))});for(let c of o.blocks)je(c,e);o.sceneProps?.length&&r.push({gameId:a,properties:o.sceneProps.map(c=>W(c,!1))})}let s=(n.scopeRegistry?.scopes??[]).map(o=>({token:o.token,writable:o.writable??!0,opaque:o.declarations===void 0,properties:(o.declarations??[]).map(a=>W(a,!0))})),i=Object.entries(n.gameDataFields??{}).filter(([,o])=>(o?.length??0)>0).map(([o,a])=>({kind:o,fields:(a??[]).map(Me)}));return{identity:{schema:n.schema,project:n.content.project,...n.content.version!==void 0?{version:n.content.version}:{},...n.content.hash!==void 0?{hash:n.content.hash}:{},...n.content.structureHash!==void 0?{structureHash:n.content.structureHash}:{},voiced:n.voiced,defaultLocale:n.locales.default,locales:[...n.locales.included],localisation:n.localisation?.mode??"embedded",sourceDebug:n.localisation?.sourceDebug??!1},addresses:t,hostScopes:s,properties:{patter:(n.properties??[]).map(o=>W(o,!0)),scene:r},gameData:i,counts:e}}function he(n,e){return n.gameDataFields?.[e]??[]}function K(n,e,t){return e&&Object.prototype.hasOwnProperty.call(e,t)?e[t]:n.find(r=>r.name===t)?.default}function me(n,e){let t={};for(let r of n){let s=K(n,e,r.name);s!==void 0&&(t[r.name]=s)}for(let[r,s]of Object.entries(e??{}))r in t||(t[r]=s);return t}return Ce(Le);})();\n//# sourceMappingURL=patterplay.min.js.map';
194785
195013
 
194786
195014
  // ../ops/src/export-html.ts
194787
195015
  var esc = (s) => s.replace(/[&<>]/g, (c2) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;" })[c2]);
@@ -195935,7 +196163,7 @@ var Flow = class {
195935
196163
  constructor(id, host2, seed) {
195936
196164
  this.id = id;
195937
196165
  this.host = host2;
195938
- this.rngState = seed >>> 0;
196166
+ this.rngState = toUint32(seed);
195939
196167
  this.local = this.freshLocal();
195940
196168
  const scopes = { ...host2.shared.toEvalContext().scopes };
195941
196169
  scopes["patter"] = this.patterResolver;
@@ -196233,7 +196461,7 @@ var Flow = class {
196233
196461
  }
196234
196462
  /** @internal Restore this flow from a snapshot. */
196235
196463
  restore(snap) {
196236
- this.rngState = snap.rngState >>> 0;
196464
+ this.rngState = toUint32(snap.rngState);
196237
196465
  this.visitCounts = new Map(Object.entries(snap.visits ?? {}));
196238
196466
  const c2 = snap.cursor;
196239
196467
  this.started = true;
@@ -196548,14 +196776,19 @@ var Flow = class {
196548
196776
  this.visitCounts.set(id, (this.visitCounts.get(id) ?? 0) + 1);
196549
196777
  this.host.sharedVisits.set(id, (this.host.sharedVisits.get(id) ?? 0) + 1);
196550
196778
  }
196551
- /** Next float in [0, 1): the shared custom PRNG, or this flow's serialisable mulberry32. */
196779
+ /** Next float in [0, 1): the shared custom PRNG, or this flow's serialisable mulberry32.
196780
+ *
196781
+ * The mixing is @wildwinter/expr's makePrng, not a copy inline here. It is a
196782
+ * fixed published algorithm that both product families need and neither
196783
+ * owns, and it existed thirteen times across the two of them. `rngState` is
196784
+ * still the serialisable position, so saves are unaffected: a generator is
196785
+ * made from it, drawn once, and the new state written back. */
196552
196786
  rng = () => {
196553
196787
  if (this.host.customRng) return this.host.customRng();
196554
- const a = this.rngState + 1831565813 | 0;
196555
- this.rngState = a;
196556
- let t = Math.imul(a ^ a >>> 15, 1 | a);
196557
- t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
196558
- return ((t ^ t >>> 14) >>> 0) / 4294967296;
196788
+ const prng = makePrng(this.rngState);
196789
+ const draw = prng.next();
196790
+ this.rngState = prng.state();
196791
+ return draw;
196559
196792
  };
196560
196793
  // -- Strings / beats ------------------------------------------------------
196561
196794
  beatResult(beat) {
@@ -196914,13 +197147,8 @@ var CADENCE_PROB = {
196914
197147
  often: 0.8
196915
197148
  };
196916
197149
  function mulberry32(seed) {
196917
- let a = seed >>> 0;
196918
- return () => {
196919
- a = a + 1831565813 | 0;
196920
- let t = Math.imul(a ^ a >>> 15, 1 | a);
196921
- t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
196922
- return ((t ^ t >>> 14) >>> 0) / 4294967296;
196923
- };
197150
+ const prng = makePrng(seed);
197151
+ return () => prng.next();
196924
197152
  }
196925
197153
  function scanExpr(node, hostTokens, refs, proposals) {
196926
197154
  const refOf = (n) => n.kind === "scopedvar" && hostTokens.has(n.scope) ? `@${n.scope}.${n.name}` : void 0;
@@ -196959,40 +197187,113 @@ function targetHostRef(target, hostTokens) {
196959
197187
  const m = /^@([A-Za-z_][\w]*)\.(.+)$/.exec(target);
196960
197188
  return m && hostTokens.has(m[1]) ? `@${m[1]}.${m[2]}` : void 0;
196961
197189
  }
197190
+ function flagKeys(node, hostTokens, fn) {
197191
+ if (node.kind !== "call" || node.name !== fn) return [];
197192
+ const subject = node.args[0];
197193
+ if (!subject || subject.kind !== "scopedvar" || !hostTokens.has(subject.scope)) return [];
197194
+ const ref = `@${subject.scope}.${subject.name}`;
197195
+ return node.args.slice(1).filter((a) => a.kind === "flagdelta").map((a) => `${ref}:${a.name}`);
197196
+ }
197197
+ function fineRefsIn(node, hostTokens, out) {
197198
+ for (const k of flagKeys(node, hostTokens, "check_flags")) out.add(k);
197199
+ switch (node.kind) {
197200
+ case "unary":
197201
+ fineRefsIn(node.operand, hostTokens, out);
197202
+ break;
197203
+ case "binary":
197204
+ fineRefsIn(node.left, hostTokens, out);
197205
+ fineRefsIn(node.right, hostTokens, out);
197206
+ break;
197207
+ case "call":
197208
+ for (const a of node.args) fineRefsIn(a, hostTokens, out);
197209
+ break;
197210
+ default:
197211
+ break;
197212
+ }
197213
+ }
196962
197214
  function analyzeHostScopes(bundle, hostTokens) {
196963
197215
  const written = /* @__PURE__ */ new Set();
196964
197216
  const gatesByBeat = /* @__PURE__ */ new Map();
197217
+ const fineGatesByBeat = /* @__PURE__ */ new Map();
196965
197218
  const proposals = /* @__PURE__ */ new Map();
196966
- if (hostTokens.size === 0) return { written, gatesByBeat, proposals };
197219
+ const writerSites = /* @__PURE__ */ new Map();
197220
+ const opaqueWrites = /* @__PURE__ */ new Set();
197221
+ const empty = { written, gatesByBeat, proposals, fineGatesByBeat, writerSites, opaqueWrites };
197222
+ if (hostTokens.size === 0) return empty;
196967
197223
  const refsIn = (expr) => {
196968
197224
  const refs = /* @__PURE__ */ new Set();
196969
197225
  if (expr) scanExpr(deserialiseAst(expr.ast), hostTokens, refs, proposals);
196970
197226
  return refs;
196971
197227
  };
196972
- const scanEffects = (effects) => {
197228
+ const fineIn = (expr) => {
197229
+ const refs = /* @__PURE__ */ new Set();
197230
+ if (expr) fineRefsIn(deserialiseAst(expr.ast), hostTokens, refs);
197231
+ return refs;
197232
+ };
197233
+ const addSite = (key2, witnesses) => {
197234
+ (writerSites.get(key2) ?? writerSites.set(key2, []).get(key2)).push(witnesses);
197235
+ };
197236
+ const scanEffects = (effects, witnesses) => {
196973
197237
  for (const e of effects ?? []) {
196974
- const t = targetHostRef(e.target, hostTokens);
196975
- if (t) written.add(t);
197238
+ const target = targetHostRef(e.target, hostTokens);
197239
+ if (target) {
197240
+ written.add(target);
197241
+ addSite(target, witnesses);
197242
+ const flags = e.value ? flagKeys(deserialiseAst(e.value.ast), hostTokens, "set_flags") : [];
197243
+ if (flags.length) for (const k of flags) addSite(k, witnesses);
197244
+ else opaqueWrites.add(target);
197245
+ }
196976
197246
  refsIn(e.value);
196977
197247
  }
196978
197248
  };
196979
- const walk2 = (nodes, gate) => {
197249
+ const walk2 = (nodes, gate, fine) => {
196980
197250
  for (const node of nodes) {
196981
197251
  const here = /* @__PURE__ */ new Set([...gate, ...refsIn(node.condition)]);
197252
+ const hereFine = /* @__PURE__ */ new Set([...fine, ...fineIn(node.condition)]);
196982
197253
  if (node.type === "group") {
196983
- walk2(node.children, here);
197254
+ walk2(node.children, here, hereFine);
196984
197255
  } else {
196985
- scanEffects(node.onEnter);
196986
- scanEffects(node.onExit);
196987
- for (const beat of node.beats ?? []) gatesByBeat.set(beat.id, here);
197256
+ const witnesses = (node.beats ?? []).map((b) => b.id);
197257
+ scanEffects(node.onEnter, witnesses);
197258
+ scanEffects(node.onExit, witnesses);
197259
+ for (const beat of node.beats ?? []) {
197260
+ gatesByBeat.set(beat.id, here);
197261
+ fineGatesByBeat.set(beat.id, hereFine);
197262
+ }
196988
197263
  }
196989
197264
  }
196990
197265
  };
196991
197266
  for (const scene of Object.values(bundle.scenes)) {
196992
- scanEffects(scene.onEntry);
196993
- for (const block of scene.blocks) walk2(block.children, /* @__PURE__ */ new Set());
197267
+ const sceneBeats = [];
197268
+ const collect = (nodes) => {
197269
+ for (const n of nodes) {
197270
+ if (n.type === "group") collect(n.children);
197271
+ else for (const b of n.beats ?? []) sceneBeats.push(b.id);
197272
+ }
197273
+ };
197274
+ for (const block of scene.blocks) collect(block.children);
197275
+ scanEffects(scene.onEntry, sceneBeats);
197276
+ for (const block of scene.blocks) walk2(block.children, /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set());
196994
197277
  }
196995
- return { written, gatesByBeat, proposals };
197278
+ return empty;
197279
+ }
197280
+ function blockedGates(beatId, analysis, drivenRefs, reachedRuns) {
197281
+ const out = [];
197282
+ const gates = /* @__PURE__ */ new Set([...analysis.gatesByBeat.get(beatId) ?? [], ...analysis.fineGatesByBeat.get(beatId) ?? []]);
197283
+ for (const ref of [...gates].sort()) {
197284
+ const coarse = ref.includes(":") ? ref.slice(0, ref.indexOf(":")) : ref;
197285
+ if (drivenRefs.has(coarse)) continue;
197286
+ if (!analysis.written.has(coarse)) continue;
197287
+ if (ref !== coarse && analysis.opaqueWrites.has(coarse)) continue;
197288
+ if (ref === coarse && [...gates].some((g) => g !== ref && g.startsWith(`${ref}:`))) continue;
197289
+ const sites = analysis.writerSites.get(ref) ?? [];
197290
+ if (!sites.length) continue;
197291
+ if (sites.some((s) => !s.length || s.some((w) => !reachedRuns.has(w)))) continue;
197292
+ if (!sites.every((s) => s.every((w) => reachedRuns.get(w) === 0))) continue;
197293
+ const writers = [...new Set(sites.flat())].sort();
197294
+ out.push({ ref, writers });
197295
+ }
197296
+ return out;
196996
197297
  }
196997
197298
  function proposeCoverageDrivers(loaded) {
196998
197299
  const hostTokens = new Set((loaded.project.scopeRegistry?.scopes ?? []).map((s) => s.token));
@@ -197125,12 +197426,15 @@ function* sweep(loaded, options = {}, hooks = {}) {
197125
197426
  const m = meta.get(id);
197126
197427
  const reached = reachedRuns.get(id);
197127
197428
  let needsInput;
197429
+ let blockedBy;
197128
197430
  if (reached === 0) {
197129
197431
  const gates = [...analysis.gatesByBeat.get(id) ?? []].filter((r) => !analysis.written.has(r) && !drivenRefs.has(r));
197130
197432
  if (gates.length) {
197131
197433
  needsInput = gates;
197132
197434
  for (const g of gates) unwrittenInputs.add(g);
197133
197435
  }
197436
+ const blocked = blockedGates(id, analysis, drivenRefs, reachedRuns);
197437
+ if (blocked.length) blockedBy = blocked;
197134
197438
  }
197135
197439
  return {
197136
197440
  id,
@@ -197141,7 +197445,8 @@ function* sweep(loaded, options = {}, hooks = {}) {
197141
197445
  hits: hitCount.get(id),
197142
197446
  reachedRuns: reached,
197143
197447
  reachPct: executed ? reached / executed * 100 : 0,
197144
- ...needsInput ? { needsInput } : {}
197448
+ ...needsInput ? { needsInput } : {},
197449
+ ...blockedBy ? { blockedBy } : {}
197145
197450
  };
197146
197451
  });
197147
197452
  const neverHit = beats.filter((b) => b.reachedRuns === 0).length;
@@ -197194,9 +197499,16 @@ function renderCoverageText(report, sceneName = (id) => id) {
197194
197499
  out.push("");
197195
197500
  out.push(`${sceneName(scene)}${dead ? ` (${dead} never reached)` : ""}`);
197196
197501
  for (const b of beats) {
197197
- const mark = b.reachedRuns === 0 ? b.needsInput ? "? " : "\u203C " : " ";
197502
+ const mark = b.reachedRuns === 0 ? b.needsInput || b.blockedBy ? "? " : "\u203C " : " ";
197198
197503
  const label = b.character ? `${b.character}: ${clip(b.preview)}` : clip(b.preview || `(${b.kind})`);
197199
197504
  out.push(` ${mark}${b.reachPct.toFixed(0).padStart(3)}% ${String(b.hits).padStart(6)} ${label}`);
197505
+ for (const bg of b.blockedBy ?? []) {
197506
+ const names = bg.writers.map((w) => {
197507
+ const target = report.beats.find((x) => x.id === w);
197508
+ return target ? clip(target.preview || target.id, 28) : w;
197509
+ });
197510
+ out.push(` gated on ${bg.ref}, written only by: ${names.join(", ")} (never played either)`);
197511
+ }
197200
197512
  }
197201
197513
  }
197202
197514
  return out;
@@ -198805,14 +199117,14 @@ var require_events = /* @__PURE__ */ __commonJSMin(((exports2, module2) => {
198805
199117
  return ret2;
198806
199118
  }
198807
199119
  function once2(emitter, name) {
198808
- return new Promise(function(resolve6, reject2) {
199120
+ return new Promise(function(resolve7, reject2) {
198809
199121
  function errorListener(err) {
198810
199122
  emitter.removeListener(name, resolver);
198811
199123
  reject2(err);
198812
199124
  }
198813
199125
  function resolver() {
198814
199126
  if (typeof emitter.removeListener === "function") emitter.removeListener("error", errorListener);
198815
- resolve6([].slice.call(arguments));
199127
+ resolve7([].slice.call(arguments));
198816
199128
  }
198817
199129
  eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
198818
199130
  if (name !== "error") addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });
@@ -201714,8 +202026,8 @@ var require_util5 = /* @__PURE__ */ __commonJSMin(((exports2) => {
201714
202026
  }
201715
202027
  function fn() {
201716
202028
  var promiseResolve, promiseReject;
201717
- var promise = new Promise(function(resolve6, reject2) {
201718
- promiseResolve = resolve6;
202029
+ var promise = new Promise(function(resolve7, reject2) {
202030
+ promiseResolve = resolve7;
201719
202031
  promiseReject = reject2;
201720
202032
  });
201721
202033
  var args = [];
@@ -201896,7 +202208,7 @@ var require_buffer_list2 = /* @__PURE__ */ __commonJSMin(((exports2, module2) =>
201896
202208
  },
201897
202209
  {
201898
202210
  key: "join",
201899
- value: function join7(s) {
202211
+ value: function join8(s) {
201900
202212
  if (this.length === 0) return "";
201901
202213
  var p = this.head;
201902
202214
  var ret2 = "" + p.data;
@@ -203081,14 +203393,14 @@ var require_async_iterator2 = /* @__PURE__ */ __commonJSMin(((exports2, module2)
203081
203393
  };
203082
203394
  }
203083
203395
  function readAndResolve(iter) {
203084
- var resolve6 = iter[kLastResolve];
203085
- if (resolve6 !== null) {
203396
+ var resolve7 = iter[kLastResolve];
203397
+ if (resolve7 !== null) {
203086
203398
  var data = iter[kStream].read();
203087
203399
  if (data !== null) {
203088
203400
  iter[kLastPromise] = null;
203089
203401
  iter[kLastResolve] = null;
203090
203402
  iter[kLastReject] = null;
203091
- resolve6(createIterResult(data, false));
203403
+ resolve7(createIterResult(data, false));
203092
203404
  }
203093
203405
  }
203094
203406
  }
@@ -203096,13 +203408,13 @@ var require_async_iterator2 = /* @__PURE__ */ __commonJSMin(((exports2, module2)
203096
203408
  process$1.nextTick(readAndResolve, iter);
203097
203409
  }
203098
203410
  function wrapForNext(lastPromise, iter) {
203099
- return function(resolve6, reject2) {
203411
+ return function(resolve7, reject2) {
203100
203412
  lastPromise.then(function() {
203101
203413
  if (iter[kEnded]) {
203102
- resolve6(createIterResult(void 0, true));
203414
+ resolve7(createIterResult(void 0, true));
203103
203415
  return;
203104
203416
  }
203105
- iter[kHandlePromise](resolve6, reject2);
203417
+ iter[kHandlePromise](resolve7, reject2);
203106
203418
  }, reject2);
203107
203419
  };
203108
203420
  }
@@ -203117,10 +203429,10 @@ var require_async_iterator2 = /* @__PURE__ */ __commonJSMin(((exports2, module2)
203117
203429
  var error = this[kError];
203118
203430
  if (error !== null) return Promise.reject(error);
203119
203431
  if (this[kEnded]) return Promise.resolve(createIterResult(void 0, true));
203120
- if (this[kStream].destroyed) return new Promise(function(resolve6, reject2) {
203432
+ if (this[kStream].destroyed) return new Promise(function(resolve7, reject2) {
203121
203433
  process$1.nextTick(function() {
203122
203434
  if (_this[kError]) reject2(_this[kError]);
203123
- else resolve6(createIterResult(void 0, true));
203435
+ else resolve7(createIterResult(void 0, true));
203124
203436
  });
203125
203437
  });
203126
203438
  var lastPromise = this[kLastPromise];
@@ -203138,13 +203450,13 @@ var require_async_iterator2 = /* @__PURE__ */ __commonJSMin(((exports2, module2)
203138
203450
  return this;
203139
203451
  }), _defineProperty2(_Object$setPrototypeO, "return", function _return() {
203140
203452
  var _this2 = this;
203141
- return new Promise(function(resolve6, reject2) {
203453
+ return new Promise(function(resolve7, reject2) {
203142
203454
  _this2[kStream].destroy(null, function(err) {
203143
203455
  if (err) {
203144
203456
  reject2(err);
203145
203457
  return;
203146
203458
  }
203147
- resolve6(createIterResult(void 0, true));
203459
+ resolve7(createIterResult(void 0, true));
203148
203460
  });
203149
203461
  });
203150
203462
  }), _Object$setPrototypeO), AsyncIteratorPrototype);
@@ -203166,15 +203478,15 @@ var require_async_iterator2 = /* @__PURE__ */ __commonJSMin(((exports2, module2)
203166
203478
  value: stream2._readableState.endEmitted,
203167
203479
  writable: true
203168
203480
  }), _defineProperty2(_Object$create, kHandlePromise, {
203169
- value: function value(resolve6, reject2) {
203481
+ value: function value(resolve7, reject2) {
203170
203482
  var data = iterator[kStream].read();
203171
203483
  if (data) {
203172
203484
  iterator[kLastPromise] = null;
203173
203485
  iterator[kLastResolve] = null;
203174
203486
  iterator[kLastReject] = null;
203175
- resolve6(createIterResult(data, false));
203487
+ resolve7(createIterResult(data, false));
203176
203488
  } else {
203177
- iterator[kLastResolve] = resolve6;
203489
+ iterator[kLastResolve] = resolve7;
203178
203490
  iterator[kLastReject] = reject2;
203179
203491
  }
203180
203492
  },
@@ -203193,12 +203505,12 @@ var require_async_iterator2 = /* @__PURE__ */ __commonJSMin(((exports2, module2)
203193
203505
  iterator[kError] = err;
203194
203506
  return;
203195
203507
  }
203196
- var resolve6 = iterator[kLastResolve];
203197
- if (resolve6 !== null) {
203508
+ var resolve7 = iterator[kLastResolve];
203509
+ if (resolve7 !== null) {
203198
203510
  iterator[kLastPromise] = null;
203199
203511
  iterator[kLastResolve] = null;
203200
203512
  iterator[kLastReject] = null;
203201
- resolve6(createIterResult(void 0, true));
203513
+ resolve7(createIterResult(void 0, true));
203202
203514
  }
203203
203515
  iterator[kEnded] = true;
203204
203516
  });
@@ -214564,7 +214876,7 @@ var require_xml = /* @__PURE__ */ __commonJSMin(((exports2, module2) => {
214564
214876
  }
214565
214877
  }
214566
214878
  function add(value, last2) {
214567
- format(append, resolve6(value, indent, indent ? 1 : 0), last2);
214879
+ format(append, resolve7(value, indent, indent ? 1 : 0), last2);
214568
214880
  }
214569
214881
  function end() {
214570
214882
  if (stream2) {
@@ -214603,12 +214915,12 @@ var require_xml = /* @__PURE__ */ __commonJSMin(((exports2, module2) => {
214603
214915
  return output;
214604
214916
  }
214605
214917
  function element() {
214606
- var self2 = { _elem: resolve6(Array.prototype.slice.call(arguments)) };
214918
+ var self2 = { _elem: resolve7(Array.prototype.slice.call(arguments)) };
214607
214919
  self2.push = function(input) {
214608
214920
  if (!this.append) throw new Error("not assigned to a parent!");
214609
214921
  var that = this;
214610
214922
  var indent = this._elem.indent;
214611
- format(this.append, resolve6(input, indent, this._elem.icount + (indent ? 1 : 0)), function() {
214923
+ format(this.append, resolve7(input, indent, this._elem.icount + (indent ? 1 : 0)), function() {
214612
214924
  that.append(true);
214613
214925
  });
214614
214926
  };
@@ -214621,7 +214933,7 @@ var require_xml = /* @__PURE__ */ __commonJSMin(((exports2, module2) => {
214621
214933
  function create_indent(character, count) {
214622
214934
  return new Array(count || 0).join(character || "");
214623
214935
  }
214624
- function resolve6(data, indent, indent_count) {
214936
+ function resolve7(data, indent, indent_count) {
214625
214937
  indent_count = indent_count || 0;
214626
214938
  var indent_spaces = create_indent(indent, indent_count);
214627
214939
  var name;
@@ -214656,7 +214968,7 @@ var require_xml = /* @__PURE__ */ __commonJSMin(((exports2, module2) => {
214656
214968
  content.push("");
214657
214969
  values.forEach(function(value) {
214658
214970
  if (typeof value == "object") if (Object.keys(value)[0] == "_attr") get_attributes(value._attr);
214659
- else content.push(resolve6(value, indent, indent_count + 1));
214971
+ else content.push(resolve7(value, indent, indent_count + 1));
214660
214972
  else {
214661
214973
  content.pop();
214662
214974
  isStringContent = true;
@@ -217508,28 +217820,28 @@ var Pointer = class extends Base {
217508
217820
  if (offset === this.options.nullValue && this.options.allowNull) {
217509
217821
  return null;
217510
217822
  }
217511
- let relative2;
217823
+ let relative3;
217512
217824
  switch (this.options.type) {
217513
217825
  case "local":
217514
- relative2 = ctx._startOffset;
217826
+ relative3 = ctx._startOffset;
217515
217827
  break;
217516
217828
  case "immediate":
217517
- relative2 = stream2.pos - this.offsetType.size();
217829
+ relative3 = stream2.pos - this.offsetType.size();
217518
217830
  break;
217519
217831
  case "parent":
217520
- relative2 = ctx.parent._startOffset;
217832
+ relative3 = ctx.parent._startOffset;
217521
217833
  break;
217522
217834
  default:
217523
217835
  var c2 = ctx;
217524
217836
  while (c2.parent) {
217525
217837
  c2 = c2.parent;
217526
217838
  }
217527
- relative2 = c2._startOffset || 0;
217839
+ relative3 = c2._startOffset || 0;
217528
217840
  }
217529
217841
  if (this.options.relativeTo) {
217530
- relative2 += this.relativeToGetter(ctx);
217842
+ relative3 += this.relativeToGetter(ctx);
217531
217843
  }
217532
- const ptr = offset + relative2;
217844
+ const ptr = offset + relative3;
217533
217845
  if (this.type != null) {
217534
217846
  let val = null;
217535
217847
  const decodeValue = () => {
@@ -217581,7 +217893,7 @@ var Pointer = class extends Base {
217581
217893
  return this.offsetType.size();
217582
217894
  }
217583
217895
  encode(stream2, val, ctx) {
217584
- let relative2;
217896
+ let relative3;
217585
217897
  const parent2 = ctx;
217586
217898
  if (val == null) {
217587
217899
  this.offsetType.encode(stream2, this.options.nullValue);
@@ -217589,25 +217901,25 @@ var Pointer = class extends Base {
217589
217901
  }
217590
217902
  switch (this.options.type) {
217591
217903
  case "local":
217592
- relative2 = ctx.startOffset;
217904
+ relative3 = ctx.startOffset;
217593
217905
  break;
217594
217906
  case "immediate":
217595
- relative2 = stream2.pos + this.offsetType.size(val, parent2);
217907
+ relative3 = stream2.pos + this.offsetType.size(val, parent2);
217596
217908
  break;
217597
217909
  case "parent":
217598
217910
  ctx = ctx.parent;
217599
- relative2 = ctx.startOffset;
217911
+ relative3 = ctx.startOffset;
217600
217912
  break;
217601
217913
  default:
217602
- relative2 = 0;
217914
+ relative3 = 0;
217603
217915
  while (ctx.parent) {
217604
217916
  ctx = ctx.parent;
217605
217917
  }
217606
217918
  }
217607
217919
  if (this.options.relativeTo) {
217608
- relative2 += this.relativeToGetter(parent2.val);
217920
+ relative3 += this.relativeToGetter(parent2.val);
217609
217921
  }
217610
- this.offsetType.encode(stream2, ctx.pointerOffset - relative2);
217922
+ this.offsetType.encode(stream2, ctx.pointerOffset - relative3);
217611
217923
  let { type } = this;
217612
217924
  if (type == null) {
217613
217925
  if (!(val instanceof VoidPointer)) {
@@ -237946,7 +238258,7 @@ var SERIF2 = (bold, italic) => bold && italic ? "Serif-BoldItalic" : bold ? "Ser
237946
238258
  var isEmoji = (cp) => cp >= 126976 || cp >= 9728 && cp <= 10175;
237947
238259
  async function scriptToPdf(doc) {
237948
238260
  const { scriptFont: scriptFont2 } = await Promise.resolve().then(() => (init_script_fonts(), script_fonts_exports));
237949
- return new Promise((resolve6, reject2) => {
238261
+ return new Promise((resolve7, reject2) => {
237950
238262
  const pdf = new PDFDocument({ size: "A4", margins: { top: MARGIN, bottom: MARGIN, left: MARGIN, right: MARGIN }, info: { Title: doc.project, Author: "Patter" }, font: null });
237951
238263
  pdf.registerFont("Serif", scriptFont2("serif"));
237952
238264
  pdf.registerFont("Serif-Bold", scriptFont2("serifBold"));
@@ -237987,7 +238299,7 @@ async function scriptToPdf(doc) {
237987
238299
  const bodyPieces = (runs, color, base = {}) => runs.flatMap((r) => r.code ? split(r.text, "Mono", ACCENT) : split(r.text, SERIF2(base.bold || r.bold, base.italic || r.italic), color));
237988
238300
  const chunks = [];
237989
238301
  pdf.on("data", (c2) => chunks.push(c2));
237990
- pdf.on("end", () => resolve6(Buffer.concat(chunks)));
238302
+ pdf.on("end", () => resolve7(Buffer.concat(chunks)));
237991
238303
  pdf.on("error", reject2);
237992
238304
  const pageRight = pdf.page.width - MARGIN;
237993
238305
  const pageBottom = pdf.page.height - MARGIN;
@@ -238530,10 +238842,21 @@ function buildIndex(loaded) {
238530
238842
  // ../ops/src/pack.ts
238531
238843
  var import_jszip = __toESM(require_lib3(), 1);
238532
238844
  import { readFileSync as readFileSync4 } from "fs";
238533
- import { dirname as dirname4, relative, sep as sep2 } from "path";
238845
+ import { dirname as dirname4, relative as relative2, sep as sep3 } from "path";
238846
+
238847
+ // ../../node_modules/@wildwinter/toolkit/dist/archive.js
238848
+ import { isAbsolute as isAbsolute2, normalize, sep as sep2, resolve as resolve4, join as join5, relative } from "path";
238849
+ function isUnsafeEntry(name) {
238850
+ if (isAbsolute2(name) || /^[a-zA-Z]:/.test(name)) return true;
238851
+ const norm = normalize(name);
238852
+ return norm === ".." || norm.startsWith(`..${sep2}`) || norm.startsWith("../");
238853
+ }
238854
+ var ARCHIVE_ENTRY_DATE = /* @__PURE__ */ new Date("2000-01-01T00:00:00Z");
238855
+ var ARCHIVE_ENTRY_OPTS = { date: ARCHIVE_ENTRY_DATE, createFolders: false };
238856
+
238857
+ // ../ops/src/pack.ts
238534
238858
  var SHARD_EXTENSIONS = [".patterflow", ".patterloc", ".patterx", ".patterproj"];
238535
- var FIXED_DATE = /* @__PURE__ */ new Date("2000-01-01T00:00:00Z");
238536
- var ENTRY_OPTS = { date: FIXED_DATE, createFolders: false };
238859
+ var ENTRY_OPTS = ARCHIVE_ENTRY_OPTS;
238537
238860
  async function runPack(startPath) {
238538
238861
  const projectFile = findProjectFile(startPath);
238539
238862
  const root2 = dirname4(projectFile);
@@ -238545,7 +238868,7 @@ async function runPack(startPath) {
238545
238868
  ` + unresolved.map((i) => ` ${i.file}`).join("\n")
238546
238869
  );
238547
238870
  }
238548
- const files = SHARD_EXTENSIONS.flatMap((ext) => walkFiles(root2, ext)).map((abs) => ({ abs, rel: relative(root2, abs).split(sep2).join("/") })).sort((a, b) => a.rel.localeCompare(b.rel));
238871
+ const files = SHARD_EXTENSIONS.flatMap((ext) => walkFiles(root2, ext)).map((abs) => ({ abs, rel: relative2(root2, abs).split(sep3).join("/") })).sort((a, b) => a.rel.localeCompare(b.rel));
238549
238872
  const manifest = {
238550
238873
  schema: "patter/document@0",
238551
238874
  project: { id: project.project.id, name: project.project.name },
@@ -238559,7 +238882,7 @@ async function runPack(startPath) {
238559
238882
 
238560
238883
  // ../ops/src/unpack.ts
238561
238884
  var import_jszip2 = __toESM(require_lib3(), 1);
238562
- import { join as join5, normalize, isAbsolute as isAbsolute2, resolve as resolve4, sep as sep3 } from "path";
238885
+ import { join as join6, resolve as resolve5, sep as sep4 } from "path";
238563
238886
  import { existsSync as existsSync3, readFileSync as readFileSync5 } from "fs";
238564
238887
  var MANIFEST = "patter.manifest.json";
238565
238888
  var UnsafeEntryError = class extends Error {
@@ -238645,22 +238968,17 @@ async function runUnpackMerge(returnedBytes, baseBytes, projectDir) {
238645
238968
  }
238646
238969
  return { shards, writes, sidecars, conflicts, warnings, provenance };
238647
238970
  }
238648
- function isUnsafeEntry(name) {
238649
- if (isAbsolute2(name) || /^[a-zA-Z]:/.test(name)) return true;
238650
- const norm = normalize(name);
238651
- return norm === ".." || norm.startsWith(".." + sep3) || norm.startsWith("../");
238652
- }
238653
238971
  function containedWrite(dir2, name) {
238654
- const root2 = resolve4(dir2);
238655
- const full = resolve4(join5(dir2, name));
238656
- if (full !== root2 && !full.startsWith(root2 + sep3)) {
238972
+ const root2 = resolve5(dir2);
238973
+ const full = resolve5(join6(dir2, name));
238974
+ if (full !== root2 && !full.startsWith(root2 + sep4)) {
238657
238975
  throw new UnsafeEntryError(`document entry escapes the target directory: ${name}`);
238658
238976
  }
238659
238977
  return full;
238660
238978
  }
238661
238979
 
238662
238980
  // ../../node_modules/@wildwinter/simple-vc-lib/dist/simpleVcLib.js
238663
- import { join as join6, dirname as dirname5, resolve as resolve5, sep as sep4, basename as basename6 } from "path";
238981
+ import { join as join7, dirname as dirname5, resolve as resolve6, sep as sep5, basename as basename6 } from "path";
238664
238982
  import { existsSync as existsSync4, readFileSync as readFileSync6, statSync as statSync3, unlinkSync, rmSync, renameSync, accessSync, constants, chmodSync, mkdirSync as mkdirSync2, cpSync, readdirSync as readdirSync4, writeFileSync as writeFileSync2 } from "fs";
238665
238983
  import { spawnSync, spawn } from "child_process";
238666
238984
  var VALID_SYSTEMS = ["git", "perforce", "plastic", "svn", "filesystem"];
@@ -238671,7 +238989,7 @@ function loadConfig(startDir) {
238671
238989
  }
238672
238990
  let dir2 = startDir;
238673
238991
  while (true) {
238674
- const configPath = join6(dir2, ".vcconfig");
238992
+ const configPath = join7(dir2, ".vcconfig");
238675
238993
  if (existsSync4(configPath)) {
238676
238994
  try {
238677
238995
  const parsed = JSON.parse(readFileSync6(configPath, "utf8"));
@@ -238715,7 +239033,7 @@ async function runCommandAsync(command, args, options = {}) {
238715
239033
  const overridden = await _overrideRunner(command, args, options);
238716
239034
  return { timedOut: false, ...overridden };
238717
239035
  }
238718
- return new Promise((resolve6) => {
239036
+ return new Promise((resolve7) => {
238719
239037
  const child = spawn(command, args, { cwd: options.cwd, windowsHide: true });
238720
239038
  let stdout = "";
238721
239039
  let stderr = "";
@@ -238737,7 +239055,7 @@ async function runCommandAsync(command, args, options = {}) {
238737
239055
  if (settled) return;
238738
239056
  settled = true;
238739
239057
  clearTimeout(timer);
238740
- resolve6(result);
239058
+ resolve7(result);
238741
239059
  };
238742
239060
  child.on("error", (err) => {
238743
239061
  finish({ exitCode: -1, output: "", error: stderr.trim() || err.message, timedOut });
@@ -238772,15 +239090,15 @@ function detectProvider(absPath) {
238772
239090
  }
238773
239091
  current = dir2;
238774
239092
  while (true) {
238775
- if (existsSync4(join6(current, ".git"))) {
239093
+ if (existsSync4(join7(current, ".git"))) {
238776
239094
  _rootCache.set(current, "git");
238777
239095
  return "git";
238778
239096
  }
238779
- if (existsSync4(join6(current, ".plastic"))) {
239097
+ if (existsSync4(join7(current, ".plastic"))) {
238780
239098
  _rootCache.set(current, "plastic");
238781
239099
  return "plastic";
238782
239100
  }
238783
- if (existsSync4(join6(current, ".svn"))) {
239101
+ if (existsSync4(join7(current, ".svn"))) {
238784
239102
  _rootCache.set(current, "svn");
238785
239103
  return "svn";
238786
239104
  }
@@ -238910,7 +239228,7 @@ var FilesystemProvider = class {
238910
239228
  */
238911
239229
  status(filePaths) {
238912
239230
  return filePaths.map((filePath) => {
238913
- const abs = resolve5(filePath);
239231
+ const abs = resolve6(filePath);
238914
239232
  return { filePath: abs, system: "filesystem", writable: writableBit(abs) };
238915
239233
  });
238916
239234
  }
@@ -238961,29 +239279,29 @@ function gitArgv(args, cwd) {
238961
239279
  }
238962
239280
  var _trackedCache = /* @__PURE__ */ new Set();
238963
239281
  function isTracked$2(filePath) {
238964
- const key2 = resolve5(filePath);
239282
+ const key2 = resolve6(filePath);
238965
239283
  if (_trackedCache.has(key2)) return true;
238966
239284
  const result = git(["ls-files", "--error-unmatch", filePath], dirname5(filePath));
238967
239285
  if (result.exitCode === 0) _trackedCache.add(key2);
238968
239286
  return result.exitCode === 0;
238969
239287
  }
238970
239288
  async function isTrackedAsync$2(filePath) {
238971
- const key2 = resolve5(filePath);
239289
+ const key2 = resolve6(filePath);
238972
239290
  if (_trackedCache.has(key2)) return true;
238973
239291
  const result = await gitAsync(["ls-files", "--error-unmatch", filePath], dirname5(filePath));
238974
239292
  if (result.exitCode === 0) _trackedCache.add(key2);
238975
239293
  return result.exitCode === 0;
238976
239294
  }
238977
239295
  function markTracked(filePath) {
238978
- _trackedCache.add(resolve5(filePath));
239296
+ _trackedCache.add(resolve6(filePath));
238979
239297
  }
238980
239298
  function unmarkTracked(filePath) {
238981
- _trackedCache.delete(resolve5(filePath));
239299
+ _trackedCache.delete(resolve6(filePath));
238982
239300
  }
238983
239301
  function unmarkTrackedUnder(folderPath) {
238984
- const prefix = resolve5(folderPath) + sep4;
239302
+ const prefix = resolve6(folderPath) + sep5;
238985
239303
  for (const path of _trackedCache) if (path.startsWith(prefix)) _trackedCache.delete(path);
238986
- _trackedCache.delete(resolve5(folderPath));
239304
+ _trackedCache.delete(resolve6(folderPath));
238987
239305
  }
238988
239306
  function isInRepo(dir2) {
238989
239307
  return git(["rev-parse", "--git-dir"], dir2).exitCode === 0;
@@ -239207,7 +239525,7 @@ var GitProvider = class {
239207
239525
  const infoByDir = /* @__PURE__ */ new Map();
239208
239526
  const groups = /* @__PURE__ */ new Map();
239209
239527
  for (const filePath of filePaths) {
239210
- const abs = resolve5(filePath);
239528
+ const abs = resolve6(filePath);
239211
239529
  const dir2 = dirname5(abs);
239212
239530
  let info = infoByDir.get(dir2);
239213
239531
  if (info === void 0) {
@@ -239237,7 +239555,7 @@ var GitProvider = class {
239237
239555
  const infoByDir = /* @__PURE__ */ new Map();
239238
239556
  const groups = /* @__PURE__ */ new Map();
239239
239557
  for (const filePath of filePaths) {
239240
- const abs = resolve5(filePath);
239558
+ const abs = resolve6(filePath);
239241
239559
  const dir2 = dirname5(abs);
239242
239560
  let info = infoByDir.get(dir2);
239243
239561
  if (info === void 0) {
@@ -239267,7 +239585,7 @@ function shouldQueryLfsLocks(root2, options) {
239267
239585
  }
239268
239586
  function repoUsesLfsLocks(root2) {
239269
239587
  try {
239270
- return /(^|\s)lockable(\s|$)/m.test(readFileSync6(join6(root2, ".gitattributes"), "utf8"));
239588
+ return /(^|\s)lockable(\s|$)/m.test(readFileSync6(join7(root2, ".gitattributes"), "utf8"));
239271
239589
  } catch {
239272
239590
  return false;
239273
239591
  }
@@ -239752,10 +240070,10 @@ function buildPerforceStatuses(output, filePaths) {
239752
240070
  const byClientFile = /* @__PURE__ */ new Map();
239753
240071
  for (const record of records) {
239754
240072
  const clientFile = record.fields.get("clientFile");
239755
- if (clientFile) byClientFile.set(resolve5(clientFile), record);
240073
+ if (clientFile) byClientFile.set(resolve6(clientFile), record);
239756
240074
  }
239757
240075
  return filePaths.map((filePath) => {
239758
- const abs = resolve5(filePath);
240076
+ const abs = resolve6(filePath);
239759
240077
  const status = { filePath: abs, system: "perforce", writable: writableBit(abs) };
239760
240078
  const record = byClientFile.get(abs);
239761
240079
  if (!record) {
@@ -240041,7 +240359,7 @@ var PlasticProvider = class {
240041
240359
  }
240042
240360
  };
240043
240361
  function plasticStatusArgs(filePaths) {
240044
- return ["status", "--machinereadable", "--all", "--ignored", ...filePaths.map((p) => resolve5(p))];
240362
+ return ["status", "--machinereadable", "--all", "--ignored", ...filePaths.map((p) => resolve6(p))];
240045
240363
  }
240046
240364
  function buildPlasticBase(result, filePaths) {
240047
240365
  const byPath = /* @__PURE__ */ new Map();
@@ -240051,7 +240369,7 @@ function buildPlasticBase(result, filePaths) {
240051
240369
  const parsed = parseCmStatusLine(line2);
240052
240370
  if (!parsed) continue;
240053
240371
  for (const p of parsed.paths) {
240054
- const abs = resolve5(p);
240372
+ const abs = resolve6(p);
240055
240373
  byPath.set(abs, parsed.info);
240056
240374
  const base = basename6(abs);
240057
240375
  if (!byBase.has(base)) byBase.set(base, []);
@@ -240060,7 +240378,7 @@ function buildPlasticBase(result, filePaths) {
240060
240378
  }
240061
240379
  }
240062
240380
  return filePaths.map((filePath) => {
240063
- const abs = resolve5(filePath);
240381
+ const abs = resolve6(filePath);
240064
240382
  const status = { filePath: abs, system: "plastic", writable: writableBit(abs) };
240065
240383
  let info = byPath.get(abs);
240066
240384
  if (!info) {
@@ -240370,7 +240688,7 @@ var SvnProvider = class {
240370
240688
  }
240371
240689
  };
240372
240690
  function svnStatusArgs(filePaths, options) {
240373
- const targets = filePaths.map((p) => resolve5(p));
240691
+ const targets = filePaths.map((p) => resolve6(p));
240374
240692
  return ["status", "--xml", "-v", ...options.remote ? ["-u"] : [], ...targets];
240375
240693
  }
240376
240694
  function buildSvnStatuses(output, filePaths) {
@@ -240380,7 +240698,7 @@ function buildSvnStatuses(output, filePaths) {
240380
240698
  const entryRe = /<entry\b[^>]*\bpath="([^"]*)"[^>]*>([\s\S]*?)<\/entry>/g;
240381
240699
  let m;
240382
240700
  while ((m = entryRe.exec(output)) !== null) {
240383
- const entryPath = resolve5(decodeXmlAttr(m[1]));
240701
+ const entryPath = resolve6(decodeXmlAttr(m[1]));
240384
240702
  const info = parseSvnEntry(m[2]);
240385
240703
  if (!info) continue;
240386
240704
  byPath.set(entryPath, info);
@@ -240390,7 +240708,7 @@ function buildSvnStatuses(output, filePaths) {
240390
240708
  }
240391
240709
  }
240392
240710
  return filePaths.map((filePath) => {
240393
- const abs = resolve5(filePath);
240711
+ const abs = resolve6(filePath);
240394
240712
  const status = { filePath: abs, system: "svn", writable: writableBit(abs) };
240395
240713
  let info = byPath.get(abs);
240396
240714
  if (!info) {
@@ -240464,7 +240782,7 @@ var PROVIDER_MAP = {
240464
240782
  };
240465
240783
  var _overrideProvider = null;
240466
240784
  function dirOf(p) {
240467
- const abs = resolve5(p);
240785
+ const abs = resolve6(p);
240468
240786
  try {
240469
240787
  return statSync3(abs).isDirectory() ? abs : dirname5(abs);
240470
240788
  } catch {
@@ -240479,7 +240797,7 @@ function resolveProvider(filePath) {
240479
240797
  const factory = PROVIDER_MAP[config.system];
240480
240798
  if (factory) return factory();
240481
240799
  }
240482
- const detected = detectProvider(resolve5(filePath));
240800
+ const detected = detectProvider(resolve6(filePath));
240483
240801
  return (PROVIDER_MAP[detected] ?? PROVIDER_MAP.filesystem)();
240484
240802
  }
240485
240803
  function deleteFile(filePath) {
@@ -240525,7 +240843,7 @@ function writeBinaryFile(filePath, data, forceWrite = false) {
240525
240843
  function writeTextFiles(files, encoding = "utf8") {
240526
240844
  const results = files.map(({ filePath, content }) => {
240527
240845
  try {
240528
- mkdirSync2(dirname5(resolve5(filePath)), { recursive: true });
240846
+ mkdirSync2(dirname5(resolve6(filePath)), { recursive: true });
240529
240847
  } catch (e) {
240530
240848
  return { filePath, success: false, status: "error", message: e.message };
240531
240849
  }
@@ -240535,6 +240853,44 @@ function writeTextFiles(files, encoding = "utf8") {
240535
240853
  return { success: results.every((r) => r.success), results };
240536
240854
  }
240537
240855
 
240856
+ // package.json
240857
+ var package_default = {
240858
+ name: "@patterkit/cli",
240859
+ version: "0.3.1",
240860
+ description: "The `patter` CLI: validate, format, export, and play a Patter project.",
240861
+ type: "module",
240862
+ license: "MIT",
240863
+ author: "Ian Thomas",
240864
+ homepage: "https://patterkit.dev",
240865
+ repository: {
240866
+ type: "git",
240867
+ url: "git+https://github.com/patterkit/patter.git",
240868
+ directory: "packages/cli"
240869
+ },
240870
+ bugs: "https://github.com/patterkit/patter/issues",
240871
+ publishConfig: {
240872
+ access: "public"
240873
+ },
240874
+ bin: {
240875
+ patter: "./dist/cli.js"
240876
+ },
240877
+ files: [
240878
+ "dist",
240879
+ "README.md"
240880
+ ],
240881
+ scripts: {
240882
+ build: "tsup",
240883
+ "build:standalone": "node scripts/build-standalone.mjs",
240884
+ "build:standalone:mac": "node scripts/build-standalone.mjs --targets=darwin-arm64,darwin-x64",
240885
+ "build:standalone:others": "node scripts/build-standalone.mjs --targets=linux-x64,linux-arm64,windows-x64"
240886
+ },
240887
+ dependencies: {
240888
+ "@patterkit/core": "0.2.2",
240889
+ "@patterkit/ops": "0.6.0",
240890
+ "@wildwinter/simple-vc-lib": "^0.4.1"
240891
+ }
240892
+ };
240893
+
240538
240894
  // src/main.ts
240539
240895
  var isPatterSource = (path) => SHARD_EXTENSIONS.some((ext) => path.endsWith(ext));
240540
240896
  function writeMergeResult(result, out, announce) {
@@ -240554,6 +240910,8 @@ function writeMergeResult(result, out, announce) {
240554
240910
  var USAGE = `patter - Patter CLI
240555
240911
 
240556
240912
  Usage:
240913
+ patter --version Print the version (also -v / version)
240914
+ patter --help Print this usage (also -h / help)
240557
240915
  patter init [dir] Scaffold a new project (the <dir>.patter folder, starter scene, VCS config)
240558
240916
  [--name X] [--vcs git|perforce|plastic|svn] [--bundle commit|ignore]
240559
240917
  patter validate [path] Validate a project (structural + expressions + encoding + bundle)
@@ -240671,6 +241029,14 @@ async function main(argv) {
240671
241029
  console.log(USAGE);
240672
241030
  return 0;
240673
241031
  }
241032
+ if (cmd === "--version" || cmd === "-v" || cmd === "version") {
241033
+ console.log(package_default.version);
241034
+ return 0;
241035
+ }
241036
+ if (cmd === "--help" || cmd === "-h" || cmd === "help") {
241037
+ console.log(USAGE);
241038
+ return 0;
241039
+ }
240674
241040
  const canonical = cmd === "fmt" ? "format" : cmd === "stats" ? "report" : cmd;
240675
241041
  if (!(canonical in FLAGS)) {
240676
241042
  console.log(USAGE);
@@ -240757,7 +241123,7 @@ async function run(cmd, positionals, flags) {
240757
241123
  }
240758
241124
  case "validate": {
240759
241125
  const loaded = loadProject(positionals[0] ?? ".");
240760
- const { structural, conditions, interpolation, hygiene, staleBundles, unresolvedMerges, orphans, ok } = runValidate(loaded);
241126
+ const { structural, conditions, interpolation, hygiene, staleBundles, unresolvedMerges, orphans, reachability, ok } = runValidate(loaded);
240761
241127
  for (const i of structural) console.error(` [${i.code}] ${i.message}`);
240762
241128
  for (const i of conditions) console.error(` [${i.field}] ${i.nodeId}: ${i.message} (${i.src})`);
240763
241129
  for (const i of interpolation) console.error(` [${i.field}] ${i.nodeId}: ${i.message} (${i.src})`);
@@ -240765,8 +241131,10 @@ async function run(cmd, positionals, flags) {
240765
241131
  for (const i of staleBundles) console.error(` [stale-bundle] ${i.file}: ${i.message}`);
240766
241132
  for (const i of unresolvedMerges) console.error(` [unresolved-merge] ${i.file}: ${i.message}`);
240767
241133
  for (const i of orphans) console.error(` [not-in-project] ${i.file}: ${i.message}`);
241134
+ for (const i of reachability) console.error(` [unreachable] ${i.nodeId}: ${i.message} (${i.src})`);
240768
241135
  const count = structural.length + conditions.length + interpolation.length + hygiene.length + staleBundles.length + unresolvedMerges.length + orphans.length;
240769
- if (ok) console.log(`ok - ${loaded.scenes.length} scene(s), no issues`);
241136
+ const advisory = reachability.length ? `, ${reachability.length} warning(s) above` : "";
241137
+ if (ok) console.log(`ok - ${loaded.scenes.length} scene(s), no issues${advisory}`);
240770
241138
  else console.error(`
240771
241139
  ${count} issue(s)`);
240772
241140
  return ok ? 0 : 1;