@fuaran-ui/ops 0.19.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -386,9 +386,12 @@ var binding = (b, staticEnc = objValue) => {
386
386
  }
387
387
  case "Computed":
388
388
  return caseObj("Computed", [["fn", CLOSURE]]);
389
- // No wire fields: the instant is host-furnished at resolve time.
389
+ // Phase 765 the INSTANT is never on the wire: it is host-furnished at
390
+ // resolve time. Phase 1533 — the declared GRAIN is, and only when it is not
391
+ // the `Second` default, so a grain-less `Now` is the same bytes it has
392
+ // always been.
390
393
  case "Now":
391
- return caseObj("Now", []);
394
+ return caseObj("Now", b.grain !== void 0 ? [["grain", str(b.grain)]] : []);
392
395
  case "I18n": {
393
396
  const fields = [];
394
397
  if (b.args !== void 0) {
@@ -400,14 +403,18 @@ var binding = (b, staticEnc = objValue) => {
400
403
  fields.push(["key", str(b.key)]);
401
404
  return caseObj("I18n", fields);
402
405
  }
403
- case "Local":
404
- return caseObj("Local", [
406
+ case "Local": {
407
+ const localFields = [
405
408
  ["flushOn", flushTrigger(b.local.flushOn)],
406
409
  ["format", CLOSURE],
407
410
  ["initialFrom", binding(b.local.initialFrom, staticEnc)],
408
- ["onCommit", CLOSURE],
409
411
  ["parse", CLOSURE]
410
- ]);
412
+ ];
413
+ if (b.local.codec !== void 0) localFields.push(["codec", formatIntent(b.local.codec)]);
414
+ if (b.local.commitTo !== void 0) localFields.push(["commitTo", str(b.local.commitTo)]);
415
+ if (b.local.onCommit !== void 0) localFields.push(["onCommit", CLOSURE]);
416
+ return caseObj("Local", localFields);
417
+ }
411
418
  case "Format":
412
419
  return caseObj("Format", [
413
420
  ["format", formatIntent(b.format)],
@@ -437,6 +444,22 @@ var binding = (b, staticEnc = objValue) => {
437
444
  ]
438
445
  ]);
439
446
  }
447
+ case "Expr": {
448
+ const exprParams = b.params !== void 0 && b.params.length > 0 ? [
449
+ [
450
+ "params",
451
+ jArray(
452
+ b.params.map(
453
+ (p) => jObject([
454
+ ["from", binding(p.from)],
455
+ ["name", str(p.name)]
456
+ ])
457
+ )
458
+ )
459
+ ]
460
+ ] : [];
461
+ return caseObj("Expr", [["expr", colExpr(b.expr)], ...exprParams]);
462
+ }
440
463
  case "Invoke":
441
464
  return caseObj("Invoke", [
442
465
  ["args", invokeArgs(b.args)],
@@ -466,8 +489,11 @@ var action = (a) => {
466
489
  ["channel", str(a.channel)],
467
490
  ["payload", jsonValue(a.payload)]
468
491
  ]);
469
- case "Navigate":
470
- return caseObj("Navigate", [["route", str(a.route)]]);
492
+ case "Navigate": {
493
+ const fields = [["route", textSource(a.route)]];
494
+ if (a.target !== "Self") fields.push(["target", str(a.target)]);
495
+ return caseObj("Navigate", fields);
496
+ }
471
497
  case "SetState": {
472
498
  const fields = [["key", str(a.key)]];
473
499
  if (a.value !== void 0) fields.push(["value", jsonValue(a.value)]);
@@ -484,7 +510,18 @@ var action = (a) => {
484
510
  case "CommitLocal":
485
511
  return caseObj("CommitLocal", [["nodeId", str(a.nodeId)]]);
486
512
  case "WriteToClipboard":
487
- return caseObj("WriteToClipboard", [["text", str(a.text)]]);
513
+ return caseObj("WriteToClipboard", [["text", textSource(a.text)]]);
514
+ case "Print":
515
+ return caseObj("Print", []);
516
+ case "Confirm": {
517
+ const fields = [];
518
+ if (a.onCancel !== void 0) fields.push(["onCancel", action(a.onCancel)]);
519
+ fields.push(["onConfirm", action(a.onConfirm)]);
520
+ fields.push(["prompt", textSource(a.prompt)]);
521
+ return caseObj("Confirm", fields);
522
+ }
523
+ case "Focus":
524
+ return caseObj("Focus", [["nodeId", str(a.nodeId)]]);
488
525
  case "ReadFileBody":
489
526
  return caseObj("ReadFileBody", [
490
527
  ["encoding", str(a.encoding)],
@@ -559,6 +596,10 @@ var formatIntent = (f) => {
559
596
  ["style", str(f.style)],
560
597
  ["unit", str(f.unit)]
561
598
  ]);
599
+ // Phase 1533 — `unit` omitted when absent: its absence is the
600
+ // auto-selection request, not a default that could be spelled out.
601
+ case "Since":
602
+ return caseObj("Since", f.unit !== void 0 ? [["unit", str(f.unit)]] : []);
562
603
  default:
563
604
  return assertNever(f);
564
605
  }
@@ -693,6 +734,42 @@ var mediaSpec = (s) => {
693
734
  fields.push(["label", textSource(s.label)]);
694
735
  if (s.loop) fields.push(["loop", bool(true)]);
695
736
  fields.push(["src", binding(s.src)]);
737
+ if (s.tracks.length > 0) fields.push(["tracks", jArray(s.tracks.map(trackEntry))]);
738
+ if (s.transcript !== void 0) fields.push(["transcript", textSource(s.transcript)]);
739
+ return jObject(fields);
740
+ };
741
+ var trackEntry = (t) => {
742
+ const fields = [];
743
+ if (t.default) fields.push(["default", bool(true)]);
744
+ fields.push(["kind", str(t.kind)]);
745
+ fields.push(["label", textSource(t.label)]);
746
+ fields.push(["src", binding(t.src)]);
747
+ fields.push(["srcLang", str(t.srcLang)]);
748
+ return jObject(fields);
749
+ };
750
+ var treeSpec = (s) => {
751
+ const fields = [["items", jArray(s.items.map(treeItem))]];
752
+ if (s.expandedStateKey !== void 0) fields.push(["expandedStateKey", str(s.expandedStateKey)]);
753
+ if (s.onSelect !== void 0) fields.push(["onSelect", CLOSURE]);
754
+ if (s.selectionStateKey !== void 0)
755
+ fields.push(["selectionStateKey", str(s.selectionStateKey)]);
756
+ return jObject(fields);
757
+ };
758
+ var treeItem = (t) => {
759
+ const fields = [];
760
+ if (t.children.length > 0) fields.push(["children", jArray(t.children.map(treeItem))]);
761
+ if (t.icon !== void 0) fields.push(["icon", str(t.icon)]);
762
+ fields.push(["id", str(t.id)]);
763
+ fields.push(["label", textSource(t.label)]);
764
+ return jObject(fields);
765
+ };
766
+ var embedSpec = (s) => {
767
+ const fields = [];
768
+ if (s.aspectRatio !== "Natural") fields.push(["aspectRatio", str(s.aspectRatio)]);
769
+ if (s.permissions.length > 0)
770
+ fields.push(["permissions", jArray(s.permissions.map((p) => str(p)))]);
771
+ fields.push(["src", binding(s.src)]);
772
+ fields.push(["title", textSource(s.title)]);
696
773
  return jObject(fields);
697
774
  };
698
775
  var listSpec = (s) => jObject([
@@ -905,6 +982,10 @@ var displayKind = (d) => {
905
982
  return hoistSpec("Image", imageSpec(d.spec));
906
983
  case "Media":
907
984
  return hoistSpec("Media", mediaSpec(d.spec));
985
+ case "Tree":
986
+ return hoistSpec("Tree", treeSpec(d.spec));
987
+ case "Embed":
988
+ return hoistSpec("Embed", embedSpec(d.spec));
908
989
  case "List":
909
990
  return hoistSpec("List", listSpec(d.spec));
910
991
  case "Toast":
@@ -992,6 +1073,40 @@ var formFieldKind = (autoBind, k) => {
992
1073
  ["orientation", str(k.orientation)],
993
1074
  ...valueField(k.value, schema.controlValueDefaults.choice, (v) => binding(v, staticStringOpt))
994
1075
  ]);
1076
+ case "Combobox": {
1077
+ const fields = [];
1078
+ if (k.allowFreeText) fields.push(["allowFreeText", bool(true)]);
1079
+ fields.push(...handlerField("onChange", k.onChange));
1080
+ fields.push(["options", binding(k.options, staticSelectOptions)]);
1081
+ fields.push(
1082
+ ...valueField(k.value, schema.controlValueDefaults.choice, (v) => binding(v, staticStringOpt))
1083
+ );
1084
+ return caseObj("Combobox", fields);
1085
+ }
1086
+ case "Tokens": {
1087
+ const fields = [];
1088
+ if (!k.allowFreeText) fields.push(["allowFreeText", bool(false)]);
1089
+ fields.push(...handlerField("onChange", k.onChange));
1090
+ if (k.suggestions !== void 0)
1091
+ fields.push(["suggestions", binding(k.suggestions, staticSelectOptions)]);
1092
+ fields.push(
1093
+ ...valueField(k.value, schema.controlValueDefaults.tokens, (v) => binding(v, staticStringList))
1094
+ );
1095
+ return caseObj("Tokens", fields);
1096
+ }
1097
+ case "Rating": {
1098
+ const fields = [];
1099
+ if (k.allowHalf) fields.push(["allowHalf", bool(true)]);
1100
+ fields.push(["max", num(k.max)]);
1101
+ fields.push(...handlerField("onChange", k.onChange));
1102
+ fields.push(...valueField(k.value, schema.controlValueDefaults.number, (v) => binding(v)));
1103
+ return caseObj("Rating", fields);
1104
+ }
1105
+ case "Color":
1106
+ return caseObj("Color", [
1107
+ ...handlerField("onChange", k.onChange),
1108
+ ...valueField(k.value, schema.controlValueDefaults.color, (v) => binding(v))
1109
+ ]);
995
1110
  case "TextArea":
996
1111
  return caseObj("TextArea", [
997
1112
  ...handlerField("onChange", k.onChange),
@@ -1108,6 +1223,10 @@ var fileUploadSpec = (s) => {
1108
1223
  ["onSelect", CLOSURE]
1109
1224
  ];
1110
1225
  if (s.disabled !== void 0) fields.push(["disabled", binding(s.disabled)]);
1226
+ if (s.acceptPaste) fields.push(["acceptPaste", bool(true)]);
1227
+ if (s.dropTarget) fields.push(["dropTarget", bool(true)]);
1228
+ if (s.capture !== void 0) fields.push(["capture", str(s.capture)]);
1229
+ if (s.destination !== void 0) fields.push(["destination", str(s.destination)]);
1111
1230
  return jObject(fields);
1112
1231
  };
1113
1232
  var inputKind = (i) => {
@@ -1245,6 +1364,11 @@ var gridSpec = (s) => {
1245
1364
  if (s.pageStateKey !== void 0) fields.push(["pageStateKey", str(s.pageStateKey)]);
1246
1365
  if (s.defaultSort !== void 0) fields.push(["defaultSort", defaultSortJson(s.defaultSort)]);
1247
1366
  if (s.editStateKey !== void 0) fields.push(["editStateKey", str(s.editStateKey)]);
1367
+ if (s.transferOutKey !== void 0) fields.push(["transferOutKey", str(s.transferOutKey)]);
1368
+ if (s.transferInKey !== void 0) fields.push(["transferInKey", str(s.transferInKey)]);
1369
+ if (s.exportable) fields.push(["exportable", bool(true)]);
1370
+ if (s.keepRowsTogether) fields.push(["keepRowsTogether", bool(true)]);
1371
+ if (s.repeatHeader) fields.push(["repeatHeader", bool(true)]);
1248
1372
  if (s.staticRows !== void 0) {
1249
1373
  const sr = s.staticRows;
1250
1374
  const srFields = [
@@ -1258,6 +1382,25 @@ var gridSpec = (s) => {
1258
1382
  }
1259
1383
  return jObject(fields);
1260
1384
  };
1385
+ var chartAnnotationX = (a) => a.kind === "Category" ? caseObj("Category", [["key", str(a.key)]]) : caseObj("Date", [["iso", str(a.iso)]]);
1386
+ var chartAnnotationRange = (r) => r.kind === "ValueRange" ? caseObj("ValueRange", [
1387
+ ["from", num(r.from)],
1388
+ ["to", num(r.to)]
1389
+ ]) : caseObj("XRange", [
1390
+ ["from", chartAnnotationX(r.from)],
1391
+ ["to", chartAnnotationX(r.to)]
1392
+ ]);
1393
+ var chartAnnotation = (a) => {
1394
+ const label = a.label !== void 0 ? [["label", textSource(a.label)]] : [];
1395
+ switch (a.kind) {
1396
+ case "ReferenceLine":
1397
+ return caseObj("ReferenceLine", [["value", num(a.value)], ...label]);
1398
+ case "EventMarker":
1399
+ return caseObj("EventMarker", [["at", chartAnnotationX(a.at)], ...label]);
1400
+ default:
1401
+ return caseObj("RangeBand", [["range", chartAnnotationRange(a.range)], ...label]);
1402
+ }
1403
+ };
1261
1404
  var chartSpec = (s) => {
1262
1405
  const fields = [
1263
1406
  ["kind", str(s.kind)],
@@ -1275,6 +1418,8 @@ var chartSpec = (s) => {
1275
1418
  if (s.legendPosition !== void 0) fields.push(["legendPosition", str(s.legendPosition)]);
1276
1419
  if (s.dataLabels !== void 0) fields.push(["dataLabels", str(s.dataLabels)]);
1277
1420
  if (s.xScale !== void 0) fields.push(["xScale", str(s.xScale)]);
1421
+ if (s.annotations !== void 0)
1422
+ fields.push(["annotations", jArray(s.annotations.map(chartAnnotation))]);
1278
1423
  if (s.onPointClick !== void 0) fields.push(["onPointClick", CLOSURE]);
1279
1424
  return jObject(fields);
1280
1425
  };
@@ -1338,6 +1483,8 @@ var boxSpec = (s) => {
1338
1483
  if (s.heading !== void 0) fields.push(["heading", textSource(s.heading)]);
1339
1484
  fields.push(["layout", boxLayout(s.layout)]);
1340
1485
  fields.push(["role", str(s.role)]);
1486
+ if (s.keepTogether) fields.push(["keepTogether", bool(true)]);
1487
+ if (s.breakBefore) fields.push(["breakBefore", bool(true)]);
1341
1488
  return jObject(fields);
1342
1489
  };
1343
1490
  var splitPanelSpec = (s) => jObject([
@@ -1392,6 +1539,8 @@ var modalSpec = (s) => {
1392
1539
  ];
1393
1540
  if (s.onDismiss !== void 0) fields.push(["onDismiss", action(s.onDismiss)]);
1394
1541
  if (s.heading !== void 0) fields.push(["heading", textSource(s.heading)]);
1542
+ if (s.modality !== "Modal") fields.push(["modality", str(s.modality)]);
1543
+ if (s.anchor !== void 0) fields.push(["anchor", str(s.anchor)]);
1395
1544
  return jObject(fields);
1396
1545
  };
1397
1546
  var scrollAreaSpec = (s) => {
@@ -1547,13 +1696,20 @@ var nodeKind = (k) => {
1547
1696
  ]);
1548
1697
  case "Switch":
1549
1698
  return caseObj("Switch", [
1699
+ // Phase 1122 — omitted when absent, so every pre-1122 switch stays
1700
+ // byte-identical.
1701
+ ...k.spec.autoAdvanceMs !== void 0 ? [["autoAdvanceMs", num(k.spec.autoAdvanceMs)]] : [],
1550
1702
  [
1551
1703
  "cases",
1552
1704
  jArray(
1705
+ // Phase 1535 — exactly one of `match` and `when` is present, so
1706
+ // exactly one is emitted. `jObject` sorts, so the pair's relative
1707
+ // order here is immaterial.
1553
1708
  k.spec.cases.map(
1554
1709
  (c) => jObject([
1555
1710
  ["child", node(c.child)],
1556
- ["match", str(c.match)]
1711
+ ...c.match !== void 0 ? [["match", str(c.match)]] : [],
1712
+ ...c.when !== void 0 ? [["when", binding(c.when, bool)]] : []
1557
1713
  ])
1558
1714
  )
1559
1715
  )
@@ -1621,6 +1777,8 @@ var semanticStyle = (s) => {
1621
1777
  if (s.weight !== void 0 && s.weight !== "Standard") fields.push(["weight", str(s.weight)]);
1622
1778
  if (s.role !== void 0 && s.role !== "None") fields.push(["role", str(s.role)]);
1623
1779
  if (s.voice !== void 0 && s.voice !== "Default") fields.push(["voice", str(s.voice)]);
1780
+ if (s.direction !== void 0 && s.direction !== "auto")
1781
+ fields.push(["direction", str(s.direction)]);
1624
1782
  return jObject(fields);
1625
1783
  };
1626
1784
  var accessibility = (a) => {
@@ -1634,7 +1792,9 @@ var accessibility = (a) => {
1634
1792
  return jObject(fields);
1635
1793
  };
1636
1794
  var isEmptyState = (s) => s.onLoading === void 0 && s.onEmpty === void 0 && s.onError === void 0;
1637
- var isDefaultStyle = (s) => (s.emphasis === void 0 || s.emphasis === "Normal") && (s.tone === void 0 || s.tone === "Default") && (s.weight === void 0 || s.weight === "Standard") && (s.role === void 0 || s.role === "None") && (s.voice === void 0 || s.voice === "Default");
1795
+ var isDefaultStyle = (s) => (s.emphasis === void 0 || s.emphasis === "Normal") && (s.tone === void 0 || s.tone === "Default") && (s.weight === void 0 || s.weight === "Standard") && (s.role === void 0 || s.role === "None") && (s.voice === void 0 || s.voice === "Default") && // Phase 1472 — `auto` is this member's identity, so a style that declares only
1796
+ // a direction is NOT all-default and the envelope must carry it.
1797
+ (s.direction === void 0 || s.direction === "auto");
1638
1798
  var node = (n) => {
1639
1799
  const fields = [
1640
1800
  ["id", str(n.id)],
@@ -1643,6 +1803,8 @@ var node = (n) => {
1643
1803
  if (!isEmptyState(n.state)) fields.push(["state", stateBehaviour(n.state)]);
1644
1804
  if (!isDefaultStyle(n.style)) fields.push(["style", semanticStyle(n.style)]);
1645
1805
  if (n.accessibility !== void 0) fields.push(["accessibility", accessibility(n.accessibility)]);
1806
+ if (n.tooltip !== void 0) fields.push(["tooltip", textSource(n.tooltip)]);
1807
+ if (n.visible !== void 0) fields.push(["visible", binding(n.visible, bool)]);
1646
1808
  return jObject(fields);
1647
1809
  };
1648
1810
  var treeOp = (op) => {
@@ -2739,6 +2901,110 @@ var stepParams = (t) => {
2739
2901
  var pipelineParams = (pipeline) => [
2740
2902
  ...new Set(pipeline.flatMap((t) => stepParams(t)))
2741
2903
  ];
2904
+ var substituteListParamsExpr = (listEnv, e) => {
2905
+ switch (e.kind) {
2906
+ case "col":
2907
+ case "lit":
2908
+ case "param":
2909
+ return e;
2910
+ case "binary":
2911
+ return {
2912
+ kind: "binary",
2913
+ op: e.op,
2914
+ left: substituteListParamsExpr(listEnv, e.left),
2915
+ right: substituteListParamsExpr(listEnv, e.right)
2916
+ };
2917
+ case "not":
2918
+ return { kind: "not", expr: substituteListParamsExpr(listEnv, e.expr) };
2919
+ case "coalesce":
2920
+ return { kind: "coalesce", exprs: e.exprs.map((x) => substituteListParamsExpr(listEnv, x)) };
2921
+ case "case":
2922
+ return {
2923
+ kind: "case",
2924
+ cases: e.cases.map((br) => ({
2925
+ when: substituteListParamsExpr(listEnv, br.when),
2926
+ then: substituteListParamsExpr(listEnv, br.then)
2927
+ })),
2928
+ else: substituteListParamsExpr(listEnv, e.else)
2929
+ };
2930
+ case "cast":
2931
+ return { kind: "cast", type: e.type, expr: substituteListParamsExpr(listEnv, e.expr) };
2932
+ case "apply":
2933
+ return {
2934
+ kind: "apply",
2935
+ fn: e.fn,
2936
+ args: e.args.map((x) => substituteListParamsExpr(listEnv, x))
2937
+ };
2938
+ case "in":
2939
+ return {
2940
+ kind: "in",
2941
+ expr: substituteListParamsExpr(listEnv, e.expr),
2942
+ items: e.items.map((x) => substituteListParamsExpr(listEnv, x))
2943
+ };
2944
+ case "isNull":
2945
+ return { kind: "isNull", expr: substituteListParamsExpr(listEnv, e.expr) };
2946
+ case "inParam": {
2947
+ const expr = substituteListParamsExpr(listEnv, e.expr);
2948
+ const items = Object.prototype.hasOwnProperty.call(listEnv, e.param) ? listEnv[e.param] : void 0;
2949
+ return items === void 0 ? { kind: "inParam", expr, param: e.param } : { kind: "in", expr, items: items.map((c) => ({ kind: "lit", cell: c })) };
2950
+ }
2951
+ }
2952
+ };
2953
+ var substituteListParams = (listEnv, pipeline) => pipeline.map((t) => {
2954
+ switch (t.kind) {
2955
+ case "filter":
2956
+ return { kind: "filter", pred: substituteListParamsExpr(listEnv, t.pred) };
2957
+ case "derive":
2958
+ return { kind: "derive", name: t.name, expr: substituteListParamsExpr(listEnv, t.expr) };
2959
+ default:
2960
+ return t;
2961
+ }
2962
+ });
2963
+
2964
+ // src/localCodec.ts
2965
+ var identityFormat = (v) => {
2966
+ if (v === null || v === void 0) return "";
2967
+ if (typeof v === "string") return v;
2968
+ if (typeof v === "boolean") return v ? "true" : "false";
2969
+ if (typeof v === "number") {
2970
+ if (Number.isNaN(v)) return "NaN";
2971
+ if (v === Infinity) return "Infinity";
2972
+ if (v === -Infinity) return "-Infinity";
2973
+ return formatFiniteDouble(v);
2974
+ }
2975
+ return String(v);
2976
+ };
2977
+ var tryNumberText = (text) => {
2978
+ const s = text.replace(/^[ \t\n\r]+|[ \t\n\r]+$/g, "");
2979
+ if (!/^-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?$/.test(s)) return void 0;
2980
+ const v = Number(s);
2981
+ return Number.isFinite(v) ? v : void 0;
2982
+ };
2983
+ var scalarOfText = (text) => {
2984
+ if (text === "true") return true;
2985
+ if (text === "false") return false;
2986
+ return tryNumberText(text);
2987
+ };
2988
+ var fixedText = (decimals, v) => {
2989
+ if (!Number.isFinite(v)) return identityFormat(v);
2990
+ const d = decimals < 0 ? 0 : Math.trunc(decimals);
2991
+ const neg = v < 0;
2992
+ const scaled = Math.floor(Math.abs(v) * Math.pow(10, d) + 0.5);
2993
+ const whole = formatFiniteDouble(scaled);
2994
+ const body = d === 0 ? whole : (() => {
2995
+ const padded = whole.length <= d ? "0".repeat(d + 1 - whole.length) + whole : whole;
2996
+ return padded.slice(0, padded.length - d) + "." + padded.slice(padded.length - d);
2997
+ })();
2998
+ return neg && scaled !== 0 ? "-" + body : body;
2999
+ };
3000
+ var numberText = (decimals, v) => decimals !== void 0 && typeof v === "number" ? fixedText(decimals, v) : identityFormat(v);
3001
+ var WireSurvivabilityError = class extends Error {
3002
+ constructor(message) {
3003
+ super(message);
3004
+ this.name = "WireSurvivabilityError";
3005
+ }
3006
+ };
3007
+ var DECODED_COMPUTED_MESSAGE = "Binding.Computed has no wire projection (decoded from a '<closure>' sentinel) \u2014 use Binding.Expr / Transform / State";
2742
3008
  var peek = (s) => s.pos < s.text.length ? s.text[s.pos] : " ";
2743
3009
  var advance = (s) => {
2744
3010
  s.pos += 1;
@@ -2769,51 +3035,94 @@ var expectChar = (s, ch) => {
2769
3035
  return fail(s, `expected '${ch}' but found '${peek(s)}'`);
2770
3036
  };
2771
3037
  var HEX_DIGIT = /[0-9a-fA-F]/;
3038
+ var HIGH_SURROGATE_FIRST = 55296;
3039
+ var HIGH_SURROGATE_LAST = 56319;
3040
+ var LOW_SURROGATE_FIRST = 56320;
3041
+ var LOW_SURROGATE_LAST = 57343;
2772
3042
  var parseStringRaw = (s) => {
2773
3043
  const open = expectChar(s, '"');
2774
3044
  if (!open.ok) return open;
2775
3045
  let out = "";
3046
+ let codePoints = 0;
3047
+ let pendingHigh = false;
3048
+ const append = (unit) => {
3049
+ const code = unit.charCodeAt(0);
3050
+ const isHigh = code >= HIGH_SURROGATE_FIRST && code <= HIGH_SURROGATE_LAST;
3051
+ const isLow = code >= LOW_SURROGATE_FIRST && code <= LOW_SURROGATE_LAST;
3052
+ if (isHigh) {
3053
+ if (pendingHigh) {
3054
+ return {
3055
+ message: "unpaired high surrogate: it must be followed by a low surrogate",
3056
+ offset: s.pos
3057
+ };
3058
+ }
3059
+ pendingHigh = true;
3060
+ codePoints += 1;
3061
+ } else if (isLow) {
3062
+ if (!pendingHigh) {
3063
+ return {
3064
+ message: "unpaired low surrogate: it must be preceded by a high surrogate",
3065
+ offset: s.pos
3066
+ };
3067
+ }
3068
+ pendingHigh = false;
3069
+ } else if (pendingHigh) {
3070
+ return {
3071
+ message: "unpaired high surrogate: it must be followed by a low surrogate",
3072
+ offset: s.pos
3073
+ };
3074
+ } else {
3075
+ codePoints += 1;
3076
+ }
3077
+ if (codePoints > schema.MAX_STRING_LENGTH) {
3078
+ return {
3079
+ message: `string is longer than the wire limit MAX_STRING_LENGTH = ${schema.MAX_STRING_LENGTH}`,
3080
+ offset: s.pos,
3081
+ limit: true
3082
+ };
3083
+ }
3084
+ out += unit;
3085
+ return void 0;
3086
+ };
2776
3087
  for (; ; ) {
2777
3088
  if (s.pos >= s.text.length) return fail(s, "unterminated string");
2778
3089
  const c = s.text[s.pos];
2779
3090
  advance(s);
2780
3091
  if (c === '"') {
3092
+ if (pendingHigh) {
3093
+ return fail(s, "unpaired high surrogate at the end of a string");
3094
+ }
2781
3095
  return { ok: true, value: out };
2782
3096
  }
2783
- if (out.length > schema.MAX_STRING_LENGTH) {
2784
- return failLimit(
2785
- s,
2786
- `string is longer than the wire limit MAX_STRING_LENGTH = ${schema.MAX_STRING_LENGTH}`
2787
- );
2788
- }
2789
3097
  if (c === "\\") {
2790
3098
  if (s.pos >= s.text.length) return fail(s, "unterminated escape");
2791
3099
  const esc = s.text[s.pos];
2792
3100
  advance(s);
3101
+ let unit;
2793
3102
  switch (esc) {
2794
3103
  case '"':
2795
- out += '"';
3104
+ unit = '"';
2796
3105
  break;
2797
3106
  case "\\":
2798
- out += "\\";
3107
+ unit = "\\";
2799
3108
  break;
2800
3109
  case "/":
2801
- out += "/";
3110
+ unit = "/";
2802
3111
  break;
2803
3112
  case "b":
2804
- out += "\b";
3113
+ unit = "\b";
2805
3114
  break;
2806
3115
  case "f":
2807
- out += "\f";
3116
+ unit = "\f";
2808
3117
  break;
2809
3118
  case "n":
2810
- out += "\n";
3119
+ unit = "\n";
2811
3120
  break;
2812
3121
  case "r":
2813
- out += "\r";
3122
+ unit = "\r";
2814
3123
  break;
2815
3124
  case "t":
2816
- out += " ";
3125
+ unit = " ";
2817
3126
  break;
2818
3127
  case "u": {
2819
3128
  if (s.pos + 4 > s.text.length) return fail(s, "incomplete \\u escape");
@@ -2822,26 +3131,58 @@ var parseStringRaw = (s) => {
2822
3131
  return fail(s, `invalid \\u escape '${hex}'`);
2823
3132
  }
2824
3133
  s.pos += 4;
2825
- out += String.fromCharCode(parseInt(hex, 16));
3134
+ unit = String.fromCharCode(parseInt(hex, 16));
2826
3135
  break;
2827
3136
  }
2828
3137
  default:
2829
3138
  return fail(s, `unknown escape '\\${esc}'`);
2830
3139
  }
3140
+ const bad = append(unit);
3141
+ if (bad) return { ok: false, error: bad };
3142
+ } else if (c.charCodeAt(0) < 32) {
3143
+ return fail(
3144
+ s,
3145
+ `raw control character U+${c.charCodeAt(0).toString(16).padStart(4, "0").toUpperCase()} in a string must be escaped`
3146
+ );
2831
3147
  } else {
2832
- out += c;
3148
+ const bad = append(c);
3149
+ if (bad) return { ok: false, error: bad };
2833
3150
  }
2834
3151
  }
2835
3152
  };
2836
3153
  var isNumberChar = (c) => c === "-" || c === "+" || c === "." || c === "e" || c === "E" || c >= "0" && c <= "9";
3154
+ var isRfc8259Number = (slice) => {
3155
+ const n = slice.length;
3156
+ let i = 0;
3157
+ const digit = (k) => k < n && slice[k] >= "0" && slice[k] <= "9";
3158
+ if (i < n && slice[i] === "-") i += 1;
3159
+ if (!digit(i)) return false;
3160
+ if (slice[i] === "0") {
3161
+ i += 1;
3162
+ } else {
3163
+ while (digit(i)) i += 1;
3164
+ }
3165
+ if (i < n && slice[i] === ".") {
3166
+ i += 1;
3167
+ if (!digit(i)) return false;
3168
+ while (digit(i)) i += 1;
3169
+ }
3170
+ if (i < n && (slice[i] === "e" || slice[i] === "E")) {
3171
+ i += 1;
3172
+ if (i < n && (slice[i] === "+" || slice[i] === "-")) i += 1;
3173
+ if (!digit(i)) return false;
3174
+ while (digit(i)) i += 1;
3175
+ }
3176
+ return i === n;
3177
+ };
2837
3178
  var parseNumberRaw = (s) => {
2838
3179
  const start = s.pos;
2839
3180
  while (s.pos < s.text.length && isNumberChar(s.text[s.pos])) {
2840
3181
  advance(s);
2841
3182
  }
2842
3183
  const slice = s.text.substring(start, s.pos);
2843
- if (slice.length === 0) {
2844
- return fail(s, `invalid number '${slice}'`);
3184
+ if (!isRfc8259Number(slice)) {
3185
+ return fail(s, `'${slice}' is not a JSON number (RFC 8259 grammar)`);
2845
3186
  }
2846
3187
  const n = Number(slice);
2847
3188
  if (Number.isNaN(n)) {
@@ -2928,6 +3269,10 @@ var parseObjectValue = (s) => {
2928
3269
  `object has more members than the wire limit MAX_ARRAY_LENGTH = ${schema.MAX_ARRAY_LENGTH}`
2929
3270
  );
2930
3271
  }
3272
+ if (fields.has(keyR.value)) {
3273
+ s.depth -= 1;
3274
+ return fail(s, `duplicate object member '${keyR.value}'`);
3275
+ }
2931
3276
  fields.set(keyR.value, valR.value);
2932
3277
  skipWs(s);
2933
3278
  const c = peek(s);
@@ -2987,13 +3332,52 @@ var parseArrayValue = (s) => {
2987
3332
  }
2988
3333
  }
2989
3334
  };
3335
+ var documentBytes = (input) => {
3336
+ if (input.length > schema.MAX_DOCUMENT_BYTES) return input.length;
3337
+ if (input.length <= schema.MAX_DOCUMENT_BYTES / 3) return input.length;
3338
+ let total = 0;
3339
+ for (let i = 0; i < input.length; i += 1) {
3340
+ const c = input.charCodeAt(i);
3341
+ if (c < 128) {
3342
+ total += 1;
3343
+ } else if (c < 2048) {
3344
+ total += 2;
3345
+ } else if (c >= HIGH_SURROGATE_FIRST && c <= HIGH_SURROGATE_LAST && i + 1 < input.length) {
3346
+ total += 4;
3347
+ i += 1;
3348
+ } else {
3349
+ total += 3;
3350
+ }
3351
+ }
3352
+ return total;
3353
+ };
2990
3354
  var parse = (input) => {
3355
+ const bytes = documentBytes(input);
3356
+ if (bytes > schema.MAX_DOCUMENT_BYTES) {
3357
+ return {
3358
+ ok: false,
3359
+ error: {
3360
+ message: `document of ${bytes} UTF-8 bytes exceeds the wire limit MAX_DOCUMENT_BYTES = ${schema.MAX_DOCUMENT_BYTES}`,
3361
+ offset: 0,
3362
+ limit: true
3363
+ }
3364
+ };
3365
+ }
2991
3366
  const s = { text: input, pos: 0, depth: 0 };
2992
3367
  skipWs(s);
2993
3368
  if (s.pos >= s.text.length) {
2994
3369
  return { ok: false, error: { message: "input is empty", offset: 0 } };
2995
3370
  }
2996
- return parseValue(s);
3371
+ const value = parseValue(s);
3372
+ if (!value.ok) return value;
3373
+ skipWs(s);
3374
+ if (s.pos < s.text.length) {
3375
+ return fail(
3376
+ s,
3377
+ `unexpected content after the root value ('${s.text[s.pos]}'); a wire artefact is a single JSON document`
3378
+ );
3379
+ }
3380
+ return value;
2997
3381
  };
2998
3382
  var field = (fields, key) => fields.get(key);
2999
3383
 
@@ -3038,9 +3422,31 @@ var requireFloat = (path, jRaw) => {
3038
3422
  }
3039
3423
  return wrongType(path, "JSON number (or 'NaN' / 'Infinity' / '-Infinity' sentinel string)");
3040
3424
  };
3425
+ var INT32_MIN = -2147483648;
3426
+ var INT32_MAX = 2147483647;
3427
+ var isInt32Slot = (n) => Number.isFinite(n) && Number.isInteger(n) && n >= INT32_MIN && n <= INT32_MAX;
3041
3428
  var requireInt = (path, jRaw) => {
3042
3429
  const j = unwrapStaticEnvelope(jRaw);
3043
- return j.kind === "JNumber" ? ok(Math.trunc(j.value)) : wrongType(path, "JSON number (integer)");
3430
+ if (j.kind !== "JNumber") return wrongType(path, "JSON number (integer)");
3431
+ if (!Number.isFinite(j.value)) {
3432
+ return wrongType(
3433
+ path,
3434
+ "JSON number (a finite 32-bit integer; the non-finite sentinels are a float slot's, not an integer slot's)"
3435
+ );
3436
+ }
3437
+ if (!Number.isInteger(j.value)) {
3438
+ return wrongType(
3439
+ path,
3440
+ "JSON number (a 32-bit integer; a fractional value is not truncated at an integer slot)"
3441
+ );
3442
+ }
3443
+ if (!isInt32Slot(j.value)) {
3444
+ return wrongType(
3445
+ path,
3446
+ "JSON number (a 32-bit integer; the value is outside the range this slot can hold)"
3447
+ );
3448
+ }
3449
+ return ok(j.value);
3044
3450
  };
3045
3451
  var requireArray = (path, j) => j.kind === "JArray" ? ok(j.items) : wrongType(path, "JSON array");
3046
3452
  var tryField = (fields, key) => fields.get(key);
@@ -3198,6 +3604,8 @@ var decodeHeadingVariant = (p, j) => {
3198
3604
  };
3199
3605
  var decodeImageVariant = (p, j) => bareEnum(p, j, ["Default", "Avatar", "Rounded"], "ImageVariant");
3200
3606
  var decodeImageFit = (p, j) => bareEnum(p, j, ["Natural", "Cover", "Contain"], "ImageFit");
3607
+ var decodeModalityKind = (p, j) => bareEnum(p, j, ["Modal", "Popover"], "ModalityKind");
3608
+ var decodeNavigateTarget = (p, j) => bareEnum(p, j, ["Self", "Blank"], "NavigateTarget");
3201
3609
  var decodeImageAspect = (p, j) => bareEnum(
3202
3610
  p,
3203
3611
  j,
@@ -3205,7 +3613,16 @@ var decodeImageAspect = (p, j) => bareEnum(
3205
3613
  "ImageAspect"
3206
3614
  );
3207
3615
  var decodeImageLoading = (p, j) => bareEnum(p, j, ["Eager", "Lazy"], "ImageLoading");
3616
+ var decodeEmbedPermission = (p, j) => bareEnum(
3617
+ p,
3618
+ j,
3619
+ ["AllowScripts", "AllowSameOrigin", "AllowForms", "AllowFullscreen"],
3620
+ "EmbedPermission"
3621
+ );
3208
3622
  var decodeScrollOrientation = (p, j) => bareEnum(p, j, ["Vertical", "Horizontal", "Both"], "ScrollOrientation");
3623
+ var decodeTrackKind = (p, j) => bareEnum(p, j, ["Subtitles", "Captions", "Descriptions", "Chapters"], "TrackKind");
3624
+ var decodeCaptureSource = (p, j) => bareEnum(p, j, ["Camera", "Microphone"], "CaptureSource");
3625
+ var decodeTextDirection = (p, j) => bareEnum(p, j, ["auto", "ltr", "rtl"], "TextDirection");
3209
3626
  var decodeDateVariant = (p, j) => bareEnum(p, j, ["Date", "Time", "DateTime"], "DateVariant");
3210
3627
  var decodeMathDisplay = (p, j) => bareEnum(p, j, ["Inline", "Block"], "MathDisplay");
3211
3628
  var TONE_ALIASES = {
@@ -3266,6 +3683,149 @@ var decodeChartKind = (p, j) => bareEnum(p, j, ["Line", "Bar", "Area", "Pie", "S
3266
3683
  var decodeChartLegendPosition = (p, j) => bareEnum(p, j, ["Top", "Right", "Bottom", "None"], "ChartLegendPosition");
3267
3684
  var decodeChartDataLabels = (p, j) => bareEnum(p, j, ["Off", "Ends"], "ChartDataLabels");
3268
3685
  var decodeChartXScale = (p, j) => bareEnum(p, j, ["Category", "Temporal"], "ChartXScale");
3686
+ var annotationIsLeapYear = (y) => y % 4 === 0 && y % 100 !== 0 || y % 400 === 0;
3687
+ var annotationDaysInMonth = (y, m) => m === 2 ? annotationIsLeapYear(y) ? 29 : 28 : m === 4 || m === 6 || m === 9 || m === 11 ? 30 : 31;
3688
+ var isCanonicalIsoDay = (text) => {
3689
+ if (text.length < 10) return false;
3690
+ if (text[4] !== "-" || text[7] !== "-") return false;
3691
+ if (text.length > 10 && text[10] !== "T") return false;
3692
+ const digits = (start, len) => {
3693
+ let acc = 0;
3694
+ for (let k = start; k < start + len; k += 1) {
3695
+ const c = text.charCodeAt(k);
3696
+ if (c < 48 || c > 57) return void 0;
3697
+ acc = acc * 10 + (c - 48);
3698
+ }
3699
+ return acc;
3700
+ };
3701
+ const y = digits(0, 4);
3702
+ const m = digits(5, 2);
3703
+ const d = digits(8, 2);
3704
+ if (y === void 0 || m === void 0 || d === void 0) return false;
3705
+ return m >= 1 && m <= 12 && d >= 1 && d <= annotationDaysInMonth(y, m);
3706
+ };
3707
+ var decodeChartAnnotationX = (path, j) => {
3708
+ const fo = requireObject(path, j);
3709
+ if (!fo.ok) return fo;
3710
+ const f = fo.value;
3711
+ const disc = requireDiscriminator(path, f);
3712
+ if (!disc.ok) return disc;
3713
+ switch (disc.value) {
3714
+ case "Category": {
3715
+ const key = reqField(path, f, "key", "category key (the band's own label)", requireString);
3716
+ if (!key.ok) return key;
3717
+ return ok({ kind: "Category", key: key.value });
3718
+ }
3719
+ case "Date": {
3720
+ const iso = reqField(path, f, "iso", "ISO-8601 date (YYYY-MM-DD)", requireString);
3721
+ if (!iso.ok) return iso;
3722
+ if (!isCanonicalIsoDay(iso.value))
3723
+ return wrongType(
3724
+ `${path}.iso`,
3725
+ "a canonical ISO-8601 date (YYYY-MM-DD, optionally followed by a time) naming a real calendar day \u2014 an event marker\u2019s date is the address it is drawn at, and an unreadable one would place the marker at 1970-01-01 and drag the axis back with it"
3726
+ );
3727
+ return ok({ kind: "Date", iso: iso.value });
3728
+ }
3729
+ default:
3730
+ return unknownDuCase(path, disc.value, "Category, Date");
3731
+ }
3732
+ };
3733
+ var decodeChartAnnotationRange = (path, j) => {
3734
+ const finite = (slot, v) => {
3735
+ const r = requireFloat(`${path}.${slot}`, v);
3736
+ if (!r.ok) return r;
3737
+ return Number.isFinite(r.value) ? r : wrongType(
3738
+ `${path}.${slot}`,
3739
+ "a FINITE JSON number \u2014 a range band's end names a place on the value axis, and NaN / Infinity names none; give the value in the axis's own units, or drop the annotation"
3740
+ );
3741
+ };
3742
+ const fo = requireObject(path, j);
3743
+ if (!fo.ok) return fo;
3744
+ const f = fo.value;
3745
+ const disc = requireDiscriminator(path, f);
3746
+ if (!disc.ok) return disc;
3747
+ switch (disc.value) {
3748
+ case "ValueRange": {
3749
+ const fromJ = requireField(path, f, "from", "range-band lower value (a finite JSON number)");
3750
+ if (!fromJ.ok) return fromJ;
3751
+ const from = finite("from", fromJ.value);
3752
+ if (!from.ok) return from;
3753
+ const toJ = requireField(path, f, "to", "range-band upper value (a finite JSON number)");
3754
+ if (!toJ.ok) return toJ;
3755
+ const to = finite("to", toJ.value);
3756
+ if (!to.ok) return to;
3757
+ if (from.value > to.value)
3758
+ return wrongType(
3759
+ path,
3760
+ "an ORDERED pair \u2014 a range band runs from its lower value to its upper one, and this pair runs backwards; swapping the ends silently would draw a band the author did not describe"
3761
+ );
3762
+ return ok({ kind: "ValueRange", from: from.value, to: to.value });
3763
+ }
3764
+ case "XRange": {
3765
+ const fromJ = requireField(
3766
+ path,
3767
+ f,
3768
+ "from",
3769
+ "range-band lower x address (a ChartAnnotationX)"
3770
+ );
3771
+ if (!fromJ.ok) return fromJ;
3772
+ const from = decodeChartAnnotationX(`${path}.from`, fromJ.value);
3773
+ if (!from.ok) return from;
3774
+ const toJ = requireField(path, f, "to", "range-band upper x address (a ChartAnnotationX)");
3775
+ if (!toJ.ok) return toJ;
3776
+ const to = decodeChartAnnotationX(`${path}.to`, toJ.value);
3777
+ if (!to.ok) return to;
3778
+ if (from.value.kind === "Date" && to.value.kind === "Date" && from.value.iso > to.value.iso)
3779
+ return wrongType(
3780
+ path,
3781
+ "an ORDERED pair \u2014 a range band runs from its earlier date to its later one, and this pair runs backwards; swapping the ends silently would draw a band the author did not describe"
3782
+ );
3783
+ return ok({ kind: "XRange", from: from.value, to: to.value });
3784
+ }
3785
+ default:
3786
+ return unknownDuCase(path, disc.value, "ValueRange, XRange");
3787
+ }
3788
+ };
3789
+ var decodeChartAnnotation = (path, j) => {
3790
+ const fo = requireObject(path, j);
3791
+ if (!fo.ok) return fo;
3792
+ const f = fo.value;
3793
+ const disc = requireDiscriminator(path, f);
3794
+ if (!disc.ok) return disc;
3795
+ const label = optField(path, f, "label", decodeTextSource);
3796
+ if (!label.ok) return label;
3797
+ const withLabel = label.value !== void 0 ? { label: label.value } : {};
3798
+ switch (disc.value) {
3799
+ case "ReferenceLine": {
3800
+ const valueJ = requireField(path, f, "value", "reference-line value (a finite JSON number)");
3801
+ if (!valueJ.ok) return valueJ;
3802
+ const value = requireFloat(`${path}.value`, valueJ.value);
3803
+ if (!value.ok) return value;
3804
+ if (!Number.isFinite(value.value))
3805
+ return wrongType(
3806
+ `${path}.value`,
3807
+ "a FINITE JSON number \u2014 a reference line names a place on the value axis, and NaN / Infinity names none; give the value in the axis's own units, or drop the annotation"
3808
+ );
3809
+ return ok({ kind: "ReferenceLine", value: value.value, ...withLabel });
3810
+ }
3811
+ case "EventMarker": {
3812
+ const atJ = requireField(path, f, "at", "event-marker x address (a ChartAnnotationX)");
3813
+ if (!atJ.ok) return atJ;
3814
+ const at = decodeChartAnnotationX(`${path}.at`, atJ.value);
3815
+ if (!at.ok) return at;
3816
+ return ok({ kind: "EventMarker", at: at.value, ...withLabel });
3817
+ }
3818
+ case "RangeBand": {
3819
+ const rangeJ = requireField(path, f, "range", "range-band pair (a ChartAnnotationRange)");
3820
+ if (!rangeJ.ok) return rangeJ;
3821
+ const range = decodeChartAnnotationRange(`${path}.range`, rangeJ.value);
3822
+ if (!range.ok) return range;
3823
+ return ok({ kind: "RangeBand", range: range.value, ...withLabel });
3824
+ }
3825
+ default:
3826
+ return unknownDuCase(path, disc.value, "ReferenceLine, EventMarker, RangeBand");
3827
+ }
3828
+ };
3269
3829
  var decodeFileReadEncoding = (p, j) => bareEnum(p, j, ["Text", "Base64", "DataUrl"], "FileReadEncoding");
3270
3830
  var decodeAriaRole = (p, j) => {
3271
3831
  if (j.kind !== "JString") return wrongType(p, "JSON string (ARIA role)");
@@ -3280,6 +3840,7 @@ var decodeRelativeTimeUnit = (p, j) => bareEnum(
3280
3840
  ["Second", "Minute", "Hour", "Day", "Week", "Month", "Year"],
3281
3841
  "RelativeTimeUnit"
3282
3842
  );
3843
+ var decodeTimeGrain = (p, j) => bareEnum(p, j, ["Second", "Minute", "Hour", "Day"], "TimeGrain");
3283
3844
  var decodeCellFormat = (path, j) => {
3284
3845
  const fo = requireObject(path, j);
3285
3846
  if (!fo.ok) return fo;
@@ -3379,11 +3940,17 @@ var decodeFormat = (path, j) => {
3379
3940
  if (!style.ok) return style;
3380
3941
  return ok({ kind: "Duration", unit: unit.value, style: style.value });
3381
3942
  }
3943
+ case "Since": {
3944
+ const u = tryField(f, "unit");
3945
+ if (u === void 0) return ok({ kind: "Since" });
3946
+ const r = decodeRelativeTimeUnit(`${path}.unit`, u);
3947
+ return r.ok ? ok({ kind: "Since", unit: r.value }) : r;
3948
+ }
3382
3949
  default:
3383
3950
  return unknownDuCase(
3384
3951
  path,
3385
3952
  d.value,
3386
- "Number | Currency | Percent | Date | RelativeTime | Duration"
3953
+ "Number | Currency | Percent | Date | RelativeTime | Duration | Since"
3387
3954
  );
3388
3955
  }
3389
3956
  };
@@ -3537,7 +4104,13 @@ var cFieldAliased = (f, canonical, alias) => {
3537
4104
  };
3538
4105
  var cStr = (j) => j.kind === "JString" ? cok(j.value) : cerr("malformed: expected string, got " + astKind(j));
3539
4106
  var cArr = (j) => j.kind === "JArray" ? cok(j.items) : cerr("malformed: expected array, got " + astKind(j));
3540
- var cInt = (j) => j.kind === "JNumber" ? cok(Math.trunc(j.value)) : cerr("malformed: expected int, got " + astKind(j));
4107
+ var cInt = (j) => {
4108
+ if (j.kind !== "JNumber") return cerr("malformed: expected int, got " + astKind(j));
4109
+ if (!isInt32Slot(j.value)) {
4110
+ return cerr(`malformed: expected a 32-bit integer, got ${j.value}`);
4111
+ }
4112
+ return cok(j.value);
4113
+ };
3541
4114
  var cMapM = (xs, fn) => {
3542
4115
  const out = [];
3543
4116
  for (const x of xs) {
@@ -3568,7 +4141,7 @@ var decodeCellLit = (j) => {
3568
4141
  if (v === void 0) return mismatch;
3569
4142
  switch (t) {
3570
4143
  case "Int":
3571
- return v.kind === "JNumber" ? cok({ kind: "Int", value: Math.trunc(v.value) }) : mismatch;
4144
+ return v.kind === "JNumber" && isInt32Slot(v.value) ? cok({ kind: "Int", value: v.value }) : mismatch;
3572
4145
  case "Float":
3573
4146
  return v.kind === "JNumber" ? cok({ kind: "Float", value: v.value }) : mismatch;
3574
4147
  case "Bool":
@@ -4271,6 +4844,137 @@ var decodeInvokeArgs = (path, j) => {
4271
4844
  return ok({ addr: addr.value, value: value.value });
4272
4845
  });
4273
4846
  };
4847
+ var exprAdmissible = (root) => {
4848
+ let count = 0;
4849
+ let sawCol = false;
4850
+ const walk = (e) => {
4851
+ count += 1;
4852
+ if (sawCol || count > schema.MAX_EXPR_NODES) return;
4853
+ switch (e.kind) {
4854
+ case "col":
4855
+ sawCol = true;
4856
+ return;
4857
+ case "lit":
4858
+ case "param":
4859
+ return;
4860
+ case "binary":
4861
+ walk(e.left);
4862
+ walk(e.right);
4863
+ return;
4864
+ case "not":
4865
+ case "cast":
4866
+ case "isNull":
4867
+ walk(e.expr);
4868
+ return;
4869
+ case "coalesce":
4870
+ e.exprs.forEach(walk);
4871
+ return;
4872
+ case "apply":
4873
+ e.args.forEach(walk);
4874
+ return;
4875
+ case "case":
4876
+ for (const c of e.cases) {
4877
+ walk(c.when);
4878
+ walk(c.then);
4879
+ }
4880
+ walk(e.else);
4881
+ return;
4882
+ case "in":
4883
+ walk(e.expr);
4884
+ e.items.forEach(walk);
4885
+ return;
4886
+ case "inParam":
4887
+ walk(e.expr);
4888
+ return;
4889
+ }
4890
+ };
4891
+ walk(root);
4892
+ if (sawCol) return "col";
4893
+ if (count > schema.MAX_EXPR_NODES) return "limit";
4894
+ return "ok";
4895
+ };
4896
+ var colExprParamNames = (root) => {
4897
+ const seen = [];
4898
+ const push = (n) => {
4899
+ if (!seen.includes(n)) seen.push(n);
4900
+ };
4901
+ const walk = (e) => {
4902
+ switch (e.kind) {
4903
+ case "col":
4904
+ case "lit":
4905
+ return;
4906
+ case "param":
4907
+ push(e.name);
4908
+ return;
4909
+ case "binary":
4910
+ walk(e.left);
4911
+ walk(e.right);
4912
+ return;
4913
+ case "not":
4914
+ case "cast":
4915
+ case "isNull":
4916
+ walk(e.expr);
4917
+ return;
4918
+ case "coalesce":
4919
+ e.exprs.forEach(walk);
4920
+ return;
4921
+ case "apply":
4922
+ e.args.forEach(walk);
4923
+ return;
4924
+ case "case":
4925
+ for (const c of e.cases) {
4926
+ walk(c.when);
4927
+ walk(c.then);
4928
+ }
4929
+ walk(e.else);
4930
+ return;
4931
+ case "in":
4932
+ walk(e.expr);
4933
+ e.items.forEach(walk);
4934
+ return;
4935
+ case "inParam":
4936
+ walk(e.expr);
4937
+ push(e.param);
4938
+ return;
4939
+ }
4940
+ };
4941
+ walk(root);
4942
+ return seen;
4943
+ };
4944
+ var decodeExprParams = (path, f) => {
4945
+ const paramsField = tryField(f, "params");
4946
+ if (paramsField === void 0) return ok(void 0);
4947
+ if (paramsField.kind === "JObject") {
4948
+ const entries = [...paramsField.fields.entries()].sort(
4949
+ ([a], [b]) => a < b ? -1 : a > b ? 1 : 0
4950
+ );
4951
+ const out = [];
4952
+ for (const [name, v] of entries) {
4953
+ const from = decodeBinding(`${path}.params.${name}.from`, v);
4954
+ if (!from.ok) return from;
4955
+ out.push({ name, from: from.value });
4956
+ }
4957
+ return ok(out);
4958
+ }
4959
+ const arr = requireArray(`${path}.params`, paramsField);
4960
+ if (!arr.ok) return arr;
4961
+ return traverseIndexed(arr.value, (_i, el) => {
4962
+ const po = requireObject(`${path}.params[]`, el);
4963
+ if (!po.ok) return po;
4964
+ const name = reqField(`${path}.params[]`, po.value, "name", "param name string", requireString);
4965
+ if (!name.ok) return name;
4966
+ const from = reqFieldAliased(
4967
+ `${path}.params[]`,
4968
+ po.value,
4969
+ "from",
4970
+ ["value"],
4971
+ "param source Binding",
4972
+ decodeBinding
4973
+ );
4974
+ if (!from.ok) return from;
4975
+ return ok({ name: name.value, from: from.value });
4976
+ });
4977
+ };
4274
4978
  var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), placeholder = OPAQUE2) => {
4275
4979
  if (j.kind === "JArray" || j.kind === "JString" || j.kind === "JNumber" || j.kind === "JBool") {
4276
4980
  const parsed = parseStatic(path, j);
@@ -4361,23 +5065,31 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4361
5065
  case "State": {
4362
5066
  const key = reqField(path, f, "key", "state key string", requireString);
4363
5067
  if (!key.ok) return key;
4364
- const dv = fieldAliased(f, "defaultValue", ["initialValue", "default"]) ?? { kind: "JNull" };
4365
- let defaultValue = placeholder;
4366
- if (dv !== void 0) {
4367
- const parsed = parseStatic(`${path}.defaultValue`, dv);
4368
- if (parsed.ok) defaultValue = parsed.value;
4369
- }
5068
+ const dvRaw = fieldAliased(f, "defaultValue", ["initialValue", "default"]);
5069
+ const dv = dvRaw ?? { kind: "JNull" };
5070
+ let defaultValue = dvRaw === void 0 ? void 0 : placeholder;
5071
+ const parsed = parseStatic(`${path}.defaultValue`, dv);
5072
+ if (parsed.ok) defaultValue = parsed.value;
4370
5073
  return ok({ kind: "State", key: key.value, defaultValue });
4371
5074
  }
4372
5075
  case "Computed":
4373
- return ok({ kind: "Computed", compute: () => void 0 });
5076
+ return ok({
5077
+ kind: "Computed",
5078
+ compute: () => {
5079
+ throw new WireSurvivabilityError(DECODED_COMPUTED_MESSAGE);
5080
+ }
5081
+ });
4374
5082
  // The projection decodes to the IDENTITY (the Phase 427 Selection fix
4375
5083
  // replayed): the host-furnished instant is already the wire-shaped string,
4376
5084
  // so a decoded reader receives it as-is. A value-discarding placeholder
4377
5085
  // here would make every decoded `Now` resolve to nothing even when the
4378
5086
  // host furnishes the instant.
4379
- case "Now":
4380
- return ok({ kind: "Now", project: (iso) => iso });
5087
+ case "Now": {
5088
+ const g = tryField(f, "grain");
5089
+ if (g === void 0) return ok({ kind: "Now", project: (iso) => iso });
5090
+ const r = decodeTimeGrain(`${path}.grain`, g);
5091
+ return r.ok ? ok({ kind: "Now", project: (iso) => iso, grain: r.value }) : r;
5092
+ }
4381
5093
  case "I18n": {
4382
5094
  const key = reqField(path, f, "key", "i18n key string", requireString);
4383
5095
  if (!key.ok) return key;
@@ -4392,6 +5104,37 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4392
5104
  return ok(b);
4393
5105
  }
4394
5106
  case "Local": {
5107
+ const codecJ = tryField(f, "codec");
5108
+ let codec;
5109
+ if (codecJ !== void 0) {
5110
+ const c = decodeFormat(`${path}.codec`, codecJ);
5111
+ if (!c.ok) return c;
5112
+ if (c.value.kind !== "Number") {
5113
+ return makeError(
5114
+ "WRONG_TYPE",
5115
+ `${path}.codec`,
5116
+ "Binding.Local 'codec' must be a Format case with a total, locale-independent inverse \u2014 only 'Number' has one",
5117
+ 'use {"$type":"Number","decimals":2}, or drop the codec and let the buffer use the identity; a locale-rendered format (Currency / Date / RelativeTime / Since / Duration) cannot be parsed back from what the reader typed'
5118
+ );
5119
+ }
5120
+ codec = c.value;
5121
+ }
5122
+ const onCommitPresent = tryField(f, "onCommit") !== void 0;
5123
+ const commitToJ = tryField(f, "commitTo");
5124
+ let commitTo;
5125
+ if (commitToJ !== void 0) {
5126
+ if (onCommitPresent) {
5127
+ return makeError(
5128
+ "WRONG_TYPE",
5129
+ `${path}.commitTo`,
5130
+ "Binding.Local carries both 'onCommit' and 'commitTo' \u2014 exactly one commit destination is allowed",
5131
+ "either onCommit (a host closure, which crosses the wire only as the closure sentinel) or commitTo (the State key the flush writes); a decoding host can honour only the second, so keeping both makes the same document commit to two different places depending on who read it"
5132
+ );
5133
+ }
5134
+ const ct = requireString(`${path}.commitTo`, commitToJ);
5135
+ if (!ct.ok) return ct;
5136
+ commitTo = ct.value;
5137
+ }
4395
5138
  const initial = reqField(
4396
5139
  path,
4397
5140
  f,
@@ -4403,15 +5146,35 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4403
5146
  const flushJ = tryField(f, "flushOn");
4404
5147
  const flush = flushJ === void 0 ? ok({ kind: "OnBlur" }) : decodeLocalFlushTrigger(`${path}.flushOn`, flushJ);
4405
5148
  if (!flush.ok) return flush;
4406
- const b = {
4407
- kind: "Local",
4408
- local: {
4409
- initialFrom: initial.value,
4410
- flushOn: flush.value,
4411
- onCommit: () => void 0,
4412
- parse: () => ({ ok: false, error: CLOSURE2 })
4413
- }
5149
+ const refusalOf = (raw) => `Binding.Local: '${raw}' is not a value this field accepts`;
5150
+ const identityParse = (raw) => {
5151
+ const asText = parseStatic(`${path}.parse`, { kind: "JString", value: raw });
5152
+ if (asText.ok) return { ok: true, value: asText.value };
5153
+ const scalar = scalarOfText(raw);
5154
+ if (scalar === void 0) return { ok: false, error: refusalOf(raw) };
5155
+ const asScalar = parseStatic(
5156
+ `${path}.parse`,
5157
+ typeof scalar === "number" ? { kind: "JNumber", value: scalar } : { kind: "JBool", value: scalar }
5158
+ );
5159
+ return asScalar.ok ? { ok: true, value: asScalar.value } : { ok: false, error: refusalOf(raw) };
4414
5160
  };
5161
+ const decimals = codec !== void 0 && codec.kind === "Number" ? codec.decimals : void 0;
5162
+ const codecParse = (raw) => {
5163
+ const n = tryNumberText(raw);
5164
+ if (n === void 0) return { ok: false, error: refusalOf(raw) };
5165
+ const parsed = parseStatic(`${path}.parse`, { kind: "JNumber", value: n });
5166
+ return parsed.ok ? { ok: true, value: parsed.value } : { ok: false, error: refusalOf(raw) };
5167
+ };
5168
+ const local = {
5169
+ initialFrom: initial.value,
5170
+ flushOn: flush.value,
5171
+ format: codec !== void 0 ? (v) => numberText(decimals, v) : (v) => identityFormat(v),
5172
+ parse: codec !== void 0 ? codecParse : identityParse,
5173
+ ...onCommitPresent ? { onCommit: () => void 0 } : {},
5174
+ ...codec !== void 0 ? { codec } : {},
5175
+ ...commitTo !== void 0 ? { commitTo } : {}
5176
+ };
5177
+ const b = { kind: "Local", local };
4415
5178
  return ok(b);
4416
5179
  }
4417
5180
  case "Format": {
@@ -4483,52 +5246,9 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4483
5246
  }
4484
5247
  const pipe = decodePipelineCore(pipeJ.value);
4485
5248
  if (!pipe.ok) return makeError("WRONG_TYPE", `${path}.pipeline`, pipe.error);
4486
- const paramsField = tryField(f, "params");
4487
- let params;
4488
- if (paramsField !== void 0 && paramsField.kind === "JObject") {
4489
- const entries = [...paramsField.fields.entries()].sort(
4490
- ([a], [b2]) => a < b2 ? -1 : a > b2 ? 1 : 0
4491
- );
4492
- const out = [];
4493
- let coerceErr;
4494
- for (const [name, v] of entries) {
4495
- const from = decodeBinding(`${path}.params.${name}.from`, v);
4496
- if (!from.ok) {
4497
- coerceErr = from;
4498
- break;
4499
- }
4500
- out.push({ name, from: from.value });
4501
- }
4502
- if (coerceErr !== void 0) return coerceErr;
4503
- params = out;
4504
- } else if (paramsField !== void 0) {
4505
- const arr = requireArray(`${path}.params`, paramsField);
4506
- if (!arr.ok) return arr;
4507
- const decoded = traverseIndexed(arr.value, (_i, el) => {
4508
- const po = requireObject(`${path}.params[]`, el);
4509
- if (!po.ok) return po;
4510
- const name = reqField(
4511
- `${path}.params[]`,
4512
- po.value,
4513
- "name",
4514
- "param name string",
4515
- requireString
4516
- );
4517
- if (!name.ok) return name;
4518
- const from = reqFieldAliased(
4519
- `${path}.params[]`,
4520
- po.value,
4521
- "from",
4522
- ["value"],
4523
- "param source Binding",
4524
- decodeBinding
4525
- );
4526
- if (!from.ok) return from;
4527
- return ok({ name: name.value, from: from.value });
4528
- });
4529
- if (!decoded.ok) return decoded;
4530
- params = decoded.value;
4531
- }
5249
+ const paramsR = decodeExprParams(path, f);
5250
+ if (!paramsR.ok) return paramsR;
5251
+ const params = paramsR.value;
4532
5252
  const b = {
4533
5253
  kind: "Transform",
4534
5254
  source,
@@ -4537,6 +5257,47 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4537
5257
  };
4538
5258
  return ok(b);
4539
5259
  }
5260
+ case "Expr": {
5261
+ const exprJ = requireField(path, f, "expr", "ColExpr object");
5262
+ if (!exprJ.ok) return exprJ;
5263
+ const expr = decodeColExprCore(exprJ.value);
5264
+ if (!expr.ok) return makeError("WRONG_TYPE", `${path}.expr`, expr.error);
5265
+ const verdict = exprAdmissible(expr.value);
5266
+ if (verdict === "col") {
5267
+ return makeError(
5268
+ "WRONG_TYPE",
5269
+ `${path}.expr`,
5270
+ "a `col` reference is not admitted inside an Expr binding \u2014 an Expr evaluates against its params alone and has no row for a column name to read. Use `Binding.Transform`, whose source supplies the frame, and put the column expression in a `derive` step",
5271
+ "a ColExpr over `param` / `lit` / operators only (no `col`)"
5272
+ );
5273
+ }
5274
+ if (verdict === "limit") {
5275
+ return makeError(
5276
+ "LIMIT_EXCEEDED",
5277
+ `${path}.expr`,
5278
+ `expression exceeds the maximum of ${schema.MAX_EXPR_NODES} expression nodes (WIRE_FORMAT 21)`,
5279
+ `at most ${schema.MAX_EXPR_NODES} ColExpr nodes in one Expr binding`
5280
+ );
5281
+ }
5282
+ const exprParams = decodeExprParams(path, f);
5283
+ if (!exprParams.ok) return exprParams;
5284
+ const bound = new Set((exprParams.value ?? []).map((p) => p.name));
5285
+ const missing = colExprParamNames(expr.value).filter((n) => !bound.has(n));
5286
+ if (missing.length > 0) {
5287
+ return makeError(
5288
+ "WRONG_TYPE",
5289
+ `${path}.expr`,
5290
+ `the expression reads param(s) ${missing.map((n) => `'${n}'`).join(", ")} that this binding's \`params\` does not bind \u2014 an Expr has no rows and no filter to prune, so an unbound param has no value to take; add a params entry naming each, or drop the reference`,
5291
+ '{"$type":"Expr","expr":{\u2026},"params":[{"name":"<name>","from":<Binding>}]}'
5292
+ );
5293
+ }
5294
+ const b = {
5295
+ kind: "Expr",
5296
+ expr: expr.value,
5297
+ ...exprParams.value !== void 0 ? { params: exprParams.value } : {}
5298
+ };
5299
+ return ok(b);
5300
+ }
4540
5301
  case "Invoke": {
4541
5302
  const cid = reqField(path, f, "capabilityId", "capability id string", requireString);
4542
5303
  if (!cid.ok) return cid;
@@ -4820,7 +5581,7 @@ var decodeAction = (path, j) => {
4820
5581
  const s = j.value.length > 24 ? j.value.slice(0, 24) + "\u2026" : j.value;
4821
5582
  return wrongType(
4822
5583
  path,
4823
- `JSON object, got the string '${s}' \u2014 an action is a $type-discriminated object (SetState | Navigate | Call | Notify | Chain | AiTool | WriteToClipboard | Invoke); "<closure>" is not authorable. Pick a real action, e.g. {"$type":"SetState","key":\u2026,"value":\u2026}`
5584
+ `JSON object, got the string '${s}' \u2014 an action is a $type-discriminated object (SetState | Navigate | Call | Notify | Chain | AiTool | WriteToClipboard | Print | Invoke); "<closure>" is not authorable. Pick a real action, e.g. {"$type":"SetState","key":\u2026,"value":\u2026}`
4824
5585
  );
4825
5586
  }
4826
5587
  const fo = requireObject(path, j);
@@ -4880,10 +5641,14 @@ var decodeAction = (path, j) => {
4880
5641
  f,
4881
5642
  "route",
4882
5643
  ["href", "url", "to"],
4883
- "route string",
4884
- requireString
5644
+ "route TextSource",
5645
+ decodeTextSource
4885
5646
  );
4886
- return r.ok ? ok({ kind: "Navigate", route: r.value }) : r;
5647
+ if (!r.ok) return r;
5648
+ const targetJ = tryField(f, "target");
5649
+ const target = targetJ === void 0 ? ok("Self") : decodeNavigateTarget(`${path}.target`, targetJ);
5650
+ if (!target.ok) return target;
5651
+ return ok({ kind: "Navigate", route: r.value, target: target.value });
4887
5652
  }
4888
5653
  case "SetState": {
4889
5654
  const key = reqField(path, f, "key", "state key string", requireString);
@@ -4940,9 +5705,64 @@ var decodeAction = (path, j) => {
4940
5705
  return r.ok ? ok({ kind: "CommitLocal", nodeId: r.value }) : r;
4941
5706
  }
4942
5707
  case "WriteToClipboard": {
4943
- const r = reqField(path, f, "text", "clipboard payload string", requireString);
5708
+ const r = reqField(path, f, "text", "clipboard payload TextSource", decodeTextSource);
4944
5709
  return r.ok ? ok({ kind: "WriteToClipboard", text: r.value }) : r;
4945
5710
  }
5711
+ case "Print": {
5712
+ for (const key of f.keys()) {
5713
+ if (key !== "$type")
5714
+ return wrongType(
5715
+ `${path}.${key}`,
5716
+ "no member beside $type \u2014 Print takes no payload (WIRE_FORMAT.md \xA73.6.14)"
5717
+ );
5718
+ }
5719
+ return ok({ kind: "Print" });
5720
+ }
5721
+ case "Confirm": {
5722
+ const nestedConfirmPath = (p, a) => {
5723
+ if (a.kind === "Confirm") return p;
5724
+ if (a.kind === "Chain") {
5725
+ for (let i = 0; i < a.actions.length; i++) {
5726
+ const found = nestedConfirmPath(`${p}.ops[${i}]`, a.actions[i]);
5727
+ if (found !== void 0) return found;
5728
+ }
5729
+ }
5730
+ return void 0;
5731
+ };
5732
+ const prompt = reqField(path, f, "prompt", "confirm prompt TextSource", decodeTextSource);
5733
+ if (!prompt.ok) return prompt;
5734
+ const confirmJ = requireField(path, f, "onConfirm", "Action to dispatch on acceptance");
5735
+ if (!confirmJ.ok) return confirmJ;
5736
+ const onConfirm = decodeAction(`${path}.onConfirm`, confirmJ.value);
5737
+ if (!onConfirm.ok) return onConfirm;
5738
+ const nestedInConfirm = nestedConfirmPath(`${path}.onConfirm`, onConfirm.value);
5739
+ if (nestedInConfirm !== void 0)
5740
+ return wrongType(
5741
+ nestedInConfirm,
5742
+ "any action but Confirm \u2014 confirmation is bounded at one question (WIRE_FORMAT.md \xA73.6.22)"
5743
+ );
5744
+ const cancelJ = f.get("onCancel");
5745
+ if (cancelJ === void 0)
5746
+ return ok({ kind: "Confirm", prompt: prompt.value, onConfirm: onConfirm.value });
5747
+ const onCancel = decodeAction(`${path}.onCancel`, cancelJ);
5748
+ if (!onCancel.ok) return onCancel;
5749
+ const nestedInCancel = nestedConfirmPath(`${path}.onCancel`, onCancel.value);
5750
+ if (nestedInCancel !== void 0)
5751
+ return wrongType(
5752
+ nestedInCancel,
5753
+ "any action but Confirm \u2014 confirmation is bounded at one question (WIRE_FORMAT.md \xA73.6.22)"
5754
+ );
5755
+ return ok({
5756
+ kind: "Confirm",
5757
+ prompt: prompt.value,
5758
+ onConfirm: onConfirm.value,
5759
+ onCancel: onCancel.value
5760
+ });
5761
+ }
5762
+ case "Focus": {
5763
+ const r = reqField(path, f, "nodeId", "NodeId string of the node to focus", requireString);
5764
+ return r.ok ? ok({ kind: "Focus", nodeId: r.value }) : r;
5765
+ }
4946
5766
  case "ReadFileBody": {
4947
5767
  const fileId = reqField(path, f, "fileRef", "FileRef id string", requireString);
4948
5768
  if (!fileId.ok) return fileId;
@@ -4967,7 +5787,7 @@ var decodeAction = (path, j) => {
4967
5787
  return unknownDuCase(
4968
5788
  path,
4969
5789
  d.value,
4970
- "Dispatch | Call | Notify | Navigate | SetState | AiTool | Chain | CommitLocal | WriteToClipboard | ReadFileBody | Invoke"
5790
+ "Dispatch | Call | Notify | Navigate | SetState | AiTool | Chain | CommitLocal | WriteToClipboard | Print | ReadFileBody | Invoke"
4971
5791
  );
4972
5792
  }
4973
5793
  };
@@ -5248,12 +6068,139 @@ var decodeMediaSpec = (path, j) => {
5248
6068
  const loopJ = tryField(f, "loop");
5249
6069
  const loop = loopJ === void 0 ? ok(false) : requireBool(`${path}.loop`, loopJ);
5250
6070
  if (!loop.ok) return loop;
6071
+ const tracksJ = tryField(f, "tracks");
6072
+ const tracks = tracksJ === void 0 ? ok([]) : (() => {
6073
+ const arr = requireArray(`${path}.tracks`, tracksJ);
6074
+ if (!arr.ok) return arr;
6075
+ return traverseIndexed(
6076
+ arr.value,
6077
+ (i, el) => decodeTrackEntry(`${path}.tracks[${i}]`, el)
6078
+ );
6079
+ })();
6080
+ if (!tracks.ok) return tracks;
6081
+ const transcript = optField(path, f, "transcript", decodeTextSource);
6082
+ if (!transcript.ok) return transcript;
5251
6083
  return ok({
5252
6084
  src: src.value,
5253
6085
  label: label.value,
5254
6086
  controls: controls.value,
5255
6087
  loop: loop.value,
5256
- kind: kind.value
6088
+ kind: kind.value,
6089
+ tracks: tracks.value,
6090
+ ...transcript.value !== void 0 ? { transcript: transcript.value } : {}
6091
+ });
6092
+ };
6093
+ var decodeTrackEntry = (path, j) => {
6094
+ const fo = requireObject(path, j);
6095
+ if (!fo.ok) return fo;
6096
+ const f = fo.value;
6097
+ const kind = reqField(path, f, "kind", "TrackKind", decodeTrackKind);
6098
+ if (!kind.ok) return kind;
6099
+ const src = reqField(path, f, "src", "track Binding<string> Src", decodeBindingString);
6100
+ if (!src.ok) return src;
6101
+ const srcLang = reqField(path, f, "srcLang", "track srcLang string", requireString);
6102
+ if (!srcLang.ok) return srcLang;
6103
+ const label = reqField(path, f, "label", "track label TextSource", decodeTextSource);
6104
+ if (!label.ok) return label;
6105
+ const defaultJ = tryField(f, "default");
6106
+ const dflt = defaultJ === void 0 ? ok(false) : requireBool(`${path}.default`, defaultJ);
6107
+ if (!dflt.ok) return dflt;
6108
+ return ok({
6109
+ kind: kind.value,
6110
+ src: src.value,
6111
+ srcLang: srcLang.value,
6112
+ label: label.value,
6113
+ default: dflt.value
6114
+ });
6115
+ };
6116
+ var decodeTreeSpec = (path, j) => {
6117
+ const fo = requireObject(path, j);
6118
+ if (!fo.ok) return fo;
6119
+ const f = fo.value;
6120
+ const itemsJ = requireField(path, f, "items", "Tree items list");
6121
+ if (!itemsJ.ok) return itemsJ;
6122
+ const arr = requireArray(`${path}.items`, itemsJ.value);
6123
+ if (!arr.ok) return arr;
6124
+ const items = traverseIndexed(arr.value, (i, el) => decodeTreeItem(`${path}.items[${i}]`, el));
6125
+ if (!items.ok) return items;
6126
+ const expandedStateKey = optField(path, f, "expandedStateKey", requireString);
6127
+ if (!expandedStateKey.ok) return expandedStateKey;
6128
+ const selectionStateKey = optField(path, f, "selectionStateKey", requireString);
6129
+ if (!selectionStateKey.ok) return selectionStateKey;
6130
+ return ok({
6131
+ items: items.value,
6132
+ ...expandedStateKey.value !== void 0 ? { expandedStateKey: expandedStateKey.value } : {},
6133
+ ...selectionStateKey.value !== void 0 ? { selectionStateKey: selectionStateKey.value } : {},
6134
+ // Emitted only when present (rule 4); the value is the closure sentinel.
6135
+ ...tryField(f, "onSelect") !== void 0 ? { onSelect: () => placeholderAction } : {}
6136
+ });
6137
+ };
6138
+ var decodeTreeItem = (path, j) => {
6139
+ if (itemDepth >= schema.MAX_NODE_DEPTH) {
6140
+ return limitError(
6141
+ path,
6142
+ `tree-item nesting deeper than the wire limit MAX_NODE_DEPTH = ${schema.MAX_NODE_DEPTH}`,
6143
+ `a tree nesting items no more than ${schema.MAX_NODE_DEPTH} levels deep`
6144
+ );
6145
+ }
6146
+ itemDepth += 1;
6147
+ const r = decodeTreeItemInner(path, j);
6148
+ itemDepth -= 1;
6149
+ return r;
6150
+ };
6151
+ var decodeTreeItemInner = (path, j) => {
6152
+ const fo = requireObject(path, j);
6153
+ if (!fo.ok) return fo;
6154
+ const f = fo.value;
6155
+ const id = reqField(path, f, "id", "TreeItem id string", requireString);
6156
+ if (!id.ok) return id;
6157
+ const label = reqField(path, f, "label", "TreeItem label TextSource", decodeTextSource);
6158
+ if (!label.ok) return label;
6159
+ const childrenJ = tryField(f, "children");
6160
+ const children = childrenJ === void 0 ? ok([]) : (() => {
6161
+ const carr = requireArray(`${path}.children`, childrenJ);
6162
+ if (!carr.ok) return carr;
6163
+ return traverseIndexed(
6164
+ carr.value,
6165
+ (i, el) => decodeTreeItem(`${path}.children[${i}]`, el)
6166
+ );
6167
+ })();
6168
+ if (!children.ok) return children;
6169
+ const icon = optField(path, f, "icon", requireString);
6170
+ if (!icon.ok) return icon;
6171
+ return ok({
6172
+ id: id.value,
6173
+ label: label.value,
6174
+ children: children.value,
6175
+ ...icon.value !== void 0 ? { icon: icon.value } : {}
6176
+ });
6177
+ };
6178
+ var decodeEmbedSpec = (path, j) => {
6179
+ const fo = requireObject(path, j);
6180
+ if (!fo.ok) return fo;
6181
+ const f = fo.value;
6182
+ const src = reqField(path, f, "src", "Embed Binding<string> Src", decodeBindingString);
6183
+ if (!src.ok) return src;
6184
+ const title = reqField(path, f, "title", "Embed accessible title TextSource", decodeTextSource);
6185
+ if (!title.ok) return title;
6186
+ const aspectJ = tryField(f, "aspectRatio");
6187
+ const aspectRatio = aspectJ === void 0 ? ok("Natural") : decodeImageAspect(`${path}.aspectRatio`, aspectJ);
6188
+ if (!aspectRatio.ok) return aspectRatio;
6189
+ const permissionsJ = tryField(f, "permissions");
6190
+ const permissions = permissionsJ === void 0 ? ok([]) : (() => {
6191
+ const arr = requireArray(`${path}.permissions`, permissionsJ);
6192
+ if (!arr.ok) return arr;
6193
+ return traverseIndexed(
6194
+ arr.value,
6195
+ (i, el) => decodeEmbedPermission(`${path}.permissions[${i}]`, el)
6196
+ );
6197
+ })();
6198
+ if (!permissions.ok) return permissions;
6199
+ return ok({
6200
+ src: src.value,
6201
+ title: title.value,
6202
+ aspectRatio: aspectRatio.value,
6203
+ permissions: permissions.value
5257
6204
  });
5258
6205
  };
5259
6206
  var decodeListSpec = (path, j) => {
@@ -5729,10 +6676,18 @@ var decodeDisplayKind = (path, j) => {
5729
6676
  const r = decodeImageSpec(path, j);
5730
6677
  return r.ok ? ok({ kind: "Image", spec: r.value }) : r;
5731
6678
  }
6679
+ case "Embed": {
6680
+ const r = decodeEmbedSpec(path, j);
6681
+ return r.ok ? ok({ kind: "Embed", spec: r.value }) : r;
6682
+ }
5732
6683
  case "Media": {
5733
6684
  const r = decodeMediaSpec(path, j);
5734
6685
  return r.ok ? ok({ kind: "Media", spec: r.value }) : r;
5735
6686
  }
6687
+ case "Tree": {
6688
+ const r = decodeTreeSpec(path, j);
6689
+ return r.ok ? ok({ kind: "Tree", spec: r.value }) : r;
6690
+ }
5736
6691
  case "List": {
5737
6692
  const r = decodeListSpec(path, j);
5738
6693
  return r.ok ? ok({ kind: "List", spec: r.value }) : r;
@@ -5757,7 +6712,7 @@ var decodeDisplayKind = (path, j) => {
5757
6712
  return unknownDuCase(
5758
6713
  path,
5759
6714
  d.value,
5760
- "Heading | Markdown | Metric | Badge | Link | Image | List | Toast | CodeBlock | Math | Drawing | Sparkline | Callout | Progress | Skeleton | LabelValueRow"
6715
+ "Heading | Markdown | Metric | Badge | Link | Image | Media | Embed | Tree | List | Toast | CodeBlock | Math | Drawing | Sparkline | Callout | Progress | Skeleton | LabelValueRow | Fact"
5761
6716
  );
5762
6717
  }
5763
6718
  };
@@ -5888,6 +6843,95 @@ var decodeFormFieldKind = (autoBind, path, j) => {
5888
6843
  orientation: orientation.value
5889
6844
  });
5890
6845
  }
6846
+ case "Combobox": {
6847
+ const options = reqField(
6848
+ path,
6849
+ f,
6850
+ "options",
6851
+ "Combobox options binding",
6852
+ decodeBindingSelectOptions
6853
+ );
6854
+ if (!options.ok) return options;
6855
+ const allowFreeTextJ = tryField(f, "allowFreeText");
6856
+ const allowFreeText = allowFreeTextJ === void 0 ? ok(false) : requireBool(`${path}.allowFreeText`, allowFreeTextJ);
6857
+ if (!allowFreeText.ok) return allowFreeText;
6858
+ const value = valueOr(
6859
+ decodeBindingStringOpt,
6860
+ schema.controlValueDefaults.choice,
6861
+ "Combobox value binding"
6862
+ );
6863
+ if (!value.ok) return value;
6864
+ return ok({
6865
+ kind: "Combobox",
6866
+ allowFreeText: allowFreeText.value,
6867
+ options: options.value,
6868
+ value: value.value,
6869
+ ...onChangeField
6870
+ });
6871
+ }
6872
+ case "Tokens": {
6873
+ const allowFreeTextJ = tryField(f, "allowFreeText");
6874
+ const allowFreeText = allowFreeTextJ === void 0 ? ok(true) : requireBool(`${path}.allowFreeText`, allowFreeTextJ);
6875
+ if (!allowFreeText.ok) return allowFreeText;
6876
+ const suggestions = optField(path, f, "suggestions", decodeBindingSelectOptions);
6877
+ if (!suggestions.ok) return suggestions;
6878
+ if (!allowFreeText.value && suggestions.value === void 0)
6879
+ return wrongType(
6880
+ `${path}.allowFreeText`,
6881
+ "a suggestion source alongside allowFreeText:false \u2014 a closed token field with nothing to pick from admits no token at all (WIRE_FORMAT.md \xA73.6.19)"
6882
+ );
6883
+ const value = valueOr(
6884
+ decodeBindingStringList,
6885
+ schema.controlValueDefaults.tokens,
6886
+ "Tokens Binding<string list> value"
6887
+ );
6888
+ if (!value.ok) return value;
6889
+ return ok({
6890
+ kind: "Tokens",
6891
+ allowFreeText: allowFreeText.value,
6892
+ value: value.value,
6893
+ ...suggestions.value !== void 0 ? { suggestions: suggestions.value } : {},
6894
+ ...onChangeField
6895
+ });
6896
+ }
6897
+ case "Rating": {
6898
+ const maxJ = requireField(path, f, "max", "Rating max integer of 1 or more");
6899
+ if (!maxJ.ok) return maxJ;
6900
+ if (maxJ.value.kind !== "JNumber" || maxJ.value.value < 1 || !Number.isInteger(maxJ.value.value))
6901
+ return wrongType(`${path}.max`, "JSON number (an integer scale of 1 or more)");
6902
+ const max = maxJ.value.value;
6903
+ const allowHalfJ = tryField(f, "allowHalf");
6904
+ const allowHalf = allowHalfJ === void 0 ? ok(false) : requireBool(`${path}.allowHalf`, allowHalfJ);
6905
+ if (!allowHalf.ok) return allowHalf;
6906
+ const value = valueOr(
6907
+ decodeBindingFloat,
6908
+ schema.controlValueDefaults.number,
6909
+ "Rating value binding"
6910
+ );
6911
+ if (!value.ok) return value;
6912
+ return ok({
6913
+ kind: "Rating",
6914
+ max,
6915
+ allowHalf: allowHalf.value,
6916
+ value: value.value,
6917
+ ...onChangeField
6918
+ });
6919
+ }
6920
+ case "Color": {
6921
+ const value = valueOr(
6922
+ decodeBinding,
6923
+ schema.controlValueDefaults.color,
6924
+ "Color value binding"
6925
+ );
6926
+ if (!value.ok) return value;
6927
+ const bound = value.value;
6928
+ if (bound.kind === "Static" && !(typeof bound.value === "string" && /^#[0-9a-fA-F]{6}$/.test(bound.value)))
6929
+ return wrongType(
6930
+ `${path}.value`,
6931
+ "a #rrggbb colour literal \u2014 six hexadecimal digits after a #, the one form a native colour input can hold (WIRE_FORMAT.md \xA73.6.17)"
6932
+ );
6933
+ return ok({ kind: "Color", value: value.value, ...onChangeField });
6934
+ }
5891
6935
  case "TextArea": {
5892
6936
  const rows = reqField(path, f, "rows", "textarea row count integer", requireInt);
5893
6937
  if (!rows.ok) return rows;
@@ -6184,12 +7228,31 @@ var decodeFileUploadSpec = (path, j) => {
6184
7228
  if (!multiple.ok) return multiple;
6185
7229
  const disabled = optField(path, f, "disabled", decodeBindingBool);
6186
7230
  if (!disabled.ok) return disabled;
7231
+ const dropTargetJ = tryField(f, "dropTarget");
7232
+ const dropTarget = dropTargetJ === void 0 ? ok(false) : requireBool(`${path}.dropTarget`, dropTargetJ);
7233
+ if (!dropTarget.ok) return dropTarget;
7234
+ const acceptPasteJ = tryField(f, "acceptPaste");
7235
+ const acceptPaste = acceptPasteJ === void 0 ? ok(false) : requireBool(`${path}.acceptPaste`, acceptPasteJ);
7236
+ if (!acceptPaste.ok) return acceptPaste;
7237
+ const capture = optField(path, f, "capture", decodeCaptureSource);
7238
+ if (!capture.ok) return capture;
7239
+ const destinationJ = tryField(f, "destination");
7240
+ const destination = destinationJ === void 0 ? ok(void 0) : (() => {
7241
+ const str3 = requireString(`${path}.destination`, destinationJ);
7242
+ if (!str3.ok) return str3;
7243
+ return str3.value === "" ? wrongType(`${path}.destination`, "a non-empty host-registered destination id") : ok(str3.value);
7244
+ })();
7245
+ if (!destination.ok) return destination;
6187
7246
  return ok({
6188
7247
  accept: accept.value,
6189
7248
  label: label.value,
6190
7249
  multiple: multiple.value,
6191
7250
  onSelect: () => placeholderAction,
6192
- ...disabled.value !== void 0 ? { disabled: disabled.value } : {}
7251
+ ...disabled.value !== void 0 ? { disabled: disabled.value } : {},
7252
+ dropTarget: dropTarget.value,
7253
+ acceptPaste: acceptPaste.value,
7254
+ ...capture.value !== void 0 ? { capture: capture.value } : {},
7255
+ ...destination.value !== void 0 ? { destination: destination.value } : {}
6193
7256
  });
6194
7257
  };
6195
7258
  var decodeInputKind = (path, j) => {
@@ -6607,6 +7670,16 @@ var decodeGridSpec = (path, j) => {
6607
7670
  if (!pk.ok) return pk;
6608
7671
  pageStateKey = pk.value;
6609
7672
  }
7673
+ const transferOutKey = optField(path, f, "transferOutKey", requireString);
7674
+ if (!transferOutKey.ok) return transferOutKey;
7675
+ const transferInKey = optField(path, f, "transferInKey", requireString);
7676
+ if (!transferInKey.ok) return transferInKey;
7677
+ const exportable = optField(path, f, "exportable", requireBool);
7678
+ if (!exportable.ok) return exportable;
7679
+ const keepRowsTogether = optField(path, f, "keepRowsTogether", requireBool);
7680
+ if (!keepRowsTogether.ok) return keepRowsTogether;
7681
+ const repeatHeader = optField(path, f, "repeatHeader", requireBool);
7682
+ if (!repeatHeader.ok) return repeatHeader;
6610
7683
  const staticRowsJ = tryField(f, "staticRows");
6611
7684
  let staticRows;
6612
7685
  if (staticRowsJ !== void 0) {
@@ -6627,6 +7700,11 @@ var decodeGridSpec = (path, j) => {
6627
7700
  ...pageStateKey !== void 0 ? { pageStateKey } : {},
6628
7701
  ...defaultSort !== void 0 ? { defaultSort } : {},
6629
7702
  ...editStateKey !== void 0 ? { editStateKey } : {},
7703
+ ...transferOutKey.value !== void 0 ? { transferOutKey: transferOutKey.value } : {},
7704
+ ...transferInKey.value !== void 0 ? { transferInKey: transferInKey.value } : {},
7705
+ exportable: exportable.value ?? false,
7706
+ keepRowsTogether: keepRowsTogether.value ?? false,
7707
+ repeatHeader: repeatHeader.value ?? false,
6630
7708
  ...staticRows !== void 0 ? { staticRows } : {}
6631
7709
  });
6632
7710
  };
@@ -6672,6 +7750,18 @@ var decodeChartSpec = (path, j) => {
6672
7750
  if (!dataLabels.ok) return dataLabels;
6673
7751
  const xScale = optField(path, f, "xScale", decodeChartXScale);
6674
7752
  if (!xScale.ok) return xScale;
7753
+ const annotationsJ = tryField(f, "annotations");
7754
+ let annotations;
7755
+ if (annotationsJ !== void 0) {
7756
+ const arr2 = requireArray(`${path}.annotations`, annotationsJ);
7757
+ if (!arr2.ok) return arr2;
7758
+ const decoded = traverseIndexed(
7759
+ arr2.value,
7760
+ (i, item) => decodeChartAnnotation(`${path}.annotations[${i}]`, item)
7761
+ );
7762
+ if (!decoded.ok) return decoded;
7763
+ annotations = decoded.value;
7764
+ }
6675
7765
  const hasPointClick = tryField(f, "onPointClick") !== void 0;
6676
7766
  const stacked = optField(path, f, "stacked", requireBool);
6677
7767
  if (!stacked.ok) return stacked;
@@ -6689,6 +7779,7 @@ var decodeChartSpec = (path, j) => {
6689
7779
  ...legendPosition.value !== void 0 ? { legendPosition: legendPosition.value } : {},
6690
7780
  ...dataLabels.value !== void 0 ? { dataLabels: dataLabels.value } : {},
6691
7781
  ...xScale.value !== void 0 ? { xScale: xScale.value } : {},
7782
+ ...annotations !== void 0 ? { annotations } : {},
6692
7783
  ...hasPointClick ? { onPointClick: () => placeholderAction } : {}
6693
7784
  });
6694
7785
  };
@@ -6839,11 +7930,17 @@ var decodeBox = (path, j) => {
6839
7930
  if (!layout.ok) return layout;
6840
7931
  const role = reqField(path, f, "role", "role string", decodeBoxRole);
6841
7932
  if (!role.ok) return role;
7933
+ const keepTogether = optField(path, f, "keepTogether", requireBool);
7934
+ if (!keepTogether.ok) return keepTogether;
7935
+ const breakBefore = optField(path, f, "breakBefore", requireBool);
7936
+ if (!breakBefore.ok) return breakBefore;
6842
7937
  return ok({
6843
7938
  children: children.value,
6844
7939
  ...heading.value !== void 0 ? { heading: heading.value } : {},
6845
7940
  layout: layout.value,
6846
- role: role.value
7941
+ role: role.value,
7942
+ keepTogether: keepTogether.value ?? false,
7943
+ breakBefore: breakBefore.value ?? false
6847
7944
  });
6848
7945
  };
6849
7946
  var decodeSplitPanelSpec = (path, j) => {
@@ -6990,12 +8087,19 @@ var decodeModalSpec = (path, j) => {
6990
8087
  if (!open.ok) return open;
6991
8088
  const heading = optFieldAliased(path, f, "heading", ["title"], decodeTextSource);
6992
8089
  if (!heading.ok) return heading;
8090
+ const modalityJ = tryField(f, "modality");
8091
+ const modality = modalityJ === void 0 ? ok("Modal") : decodeModalityKind(`${path}.modality`, modalityJ);
8092
+ if (!modality.ok) return modality;
8093
+ const anchor = optField(path, f, "anchor", requireString);
8094
+ if (!anchor.ok) return anchor;
6993
8095
  return ok({
6994
8096
  children: children.value,
6995
8097
  dismissable: dismissable.value,
6996
8098
  ...onDismiss.value !== void 0 ? { onDismiss: onDismiss.value } : {},
6997
8099
  open: open.value,
6998
- ...heading.value !== void 0 ? { heading: heading.value } : {}
8100
+ ...heading.value !== void 0 ? { heading: heading.value } : {},
8101
+ modality: modality.value,
8102
+ ...anchor.value !== void 0 ? { anchor: anchor.value } : {}
6999
8103
  });
7000
8104
  };
7001
8105
  var decodeScrollAreaSpec = (path, j) => {
@@ -7282,6 +8386,8 @@ var decodeNodeKind = (path, j) => {
7282
8386
  case "Link":
7283
8387
  case "Image":
7284
8388
  case "Media":
8389
+ case "Embed":
8390
+ case "Tree":
7285
8391
  case "List":
7286
8392
  case "Toast":
7287
8393
  case "CodeBlock":
@@ -7372,18 +8478,51 @@ var decodeNodeKind = (path, j) => {
7372
8478
  const cp = `${path}.cases[${i}]`;
7373
8479
  const co = requireObject(cp, item);
7374
8480
  if (!co.ok) return co;
7375
- const m = reqField(cp, co.value, "match", "Switch case match string", requireString);
7376
- if (!m.ok) return m;
8481
+ const mJ = tryField(co.value, "match");
8482
+ const wJ = tryField(co.value, "when");
8483
+ if (mJ !== void 0 && wJ !== void 0)
8484
+ return wrongType(
8485
+ `${cp}.when`,
8486
+ "either 'match' (a literal string compared against the switch's `on` selector) or 'when' (a Binding<bool> predicate evaluated at render time, needing no selector); remove one"
8487
+ );
8488
+ if (mJ === void 0 && wJ === void 0)
8489
+ return missingField(
8490
+ cp,
8491
+ "match",
8492
+ "a literal string under 'match' (compared against the switch's `on` selector), or a Binding<bool> under 'when' (a predicate evaluated at render time)"
8493
+ );
7377
8494
  const c = reqField(cp, co.value, "child", "Switch case child Node", decodeNodeAst);
7378
8495
  if (!c.ok) return c;
7379
- return ok({ match: m.value, child: c.value });
8496
+ if (mJ !== void 0) {
8497
+ const m = requireString(`${cp}.match`, mJ);
8498
+ if (!m.ok) return m;
8499
+ return ok({ match: m.value, child: c.value });
8500
+ }
8501
+ const w = decodeBindingBool(`${cp}.when`, wJ);
8502
+ if (!w.ok) return w;
8503
+ return ok({ when: w.value, child: c.value });
7380
8504
  });
7381
8505
  if (!cases.ok) return cases;
7382
8506
  const def = reqField(path, f, "default", "Switch default Node", decodeNodeAst);
7383
8507
  if (!def.ok) return def;
8508
+ const autoAdvanceMsJ = tryField(f, "autoAdvanceMs");
8509
+ let autoAdvanceMs;
8510
+ if (autoAdvanceMsJ !== void 0) {
8511
+ if (autoAdvanceMsJ.kind !== "JNumber" || autoAdvanceMsJ.value < 1 || !Number.isInteger(autoAdvanceMsJ.value))
8512
+ return wrongType(
8513
+ `${path}.autoAdvanceMs`,
8514
+ "JSON number (a positive whole number of milliseconds)"
8515
+ );
8516
+ autoAdvanceMs = autoAdvanceMsJ.value;
8517
+ }
7384
8518
  return ok({
7385
8519
  kind: "Switch",
7386
- spec: { on: on.value, cases: cases.value, default: def.value }
8520
+ spec: {
8521
+ on: on.value,
8522
+ cases: cases.value,
8523
+ default: def.value,
8524
+ ...autoAdvanceMs !== void 0 ? { autoAdvanceMs } : {}
8525
+ }
7387
8526
  });
7388
8527
  }
7389
8528
  case "FragmentDecl": {
@@ -7549,12 +8688,15 @@ var decodeSemanticStyle = (path, j) => {
7549
8688
  if (!role.ok) return role;
7550
8689
  const voice = optField(path, f, "voice", decodeFontVoice);
7551
8690
  if (!voice.ok) return voice;
8691
+ const direction = optField(path, f, "direction", decodeTextDirection);
8692
+ if (!direction.ok) return direction;
7552
8693
  return ok({
7553
8694
  tone: tone.value ?? "Default",
7554
8695
  weight: weight.value ?? "Standard",
7555
8696
  emphasis: emphasis.value ?? "Normal",
7556
8697
  role: role.value ?? "None",
7557
- voice: voice.value ?? "Default"
8698
+ voice: voice.value ?? "Default",
8699
+ direction: direction.value ?? "auto"
7558
8700
  });
7559
8701
  };
7560
8702
  var A11Y_NEAR_MISSES = [
@@ -7652,11 +8794,13 @@ var placeholderClosureNode = {
7652
8794
  var walkDepth = 0;
7653
8795
  var walkNodes = 0;
7654
8796
  var opDepth = 0;
8797
+ var itemDepth = 0;
7655
8798
  var walkPolicy = schema.admitAll;
7656
8799
  var resetWalk = (policy = schema.admitAll) => {
7657
8800
  walkDepth = 0;
7658
8801
  walkNodes = 0;
7659
8802
  opDepth = 0;
8803
+ itemDepth = 0;
7660
8804
  walkPolicy = policy;
7661
8805
  };
7662
8806
  var limitError = (path, message, expected) => makeError("LIMIT_EXCEEDED", path, message, expected);
@@ -7700,12 +8844,18 @@ var decodeNodeAstInner = (path, j) => {
7700
8844
  if (!style.ok) return style;
7701
8845
  const accessibility2 = optField(path, f, "accessibility", decodeAccessibility);
7702
8846
  if (!accessibility2.ok) return accessibility2;
8847
+ const tooltip = optField(path, f, "tooltip", decodeTextSource);
8848
+ if (!tooltip.ok) return tooltip;
8849
+ const visible = optField(path, f, "visible", decodeBindingBool);
8850
+ if (!visible.ok) return visible;
7703
8851
  return ok({
7704
8852
  id: idStr.value,
7705
8853
  kind: kind.value,
7706
8854
  state: state.value,
7707
8855
  style: style.value,
7708
- ...accessibility2.value !== void 0 ? { accessibility: accessibility2.value } : {}
8856
+ ...accessibility2.value !== void 0 ? { accessibility: accessibility2.value } : {},
8857
+ ...tooltip.value !== void 0 ? { tooltip: tooltip.value } : {},
8858
+ ...visible.value !== void 0 ? { visible: visible.value } : {}
7709
8859
  });
7710
8860
  };
7711
8861
  var decodeTreeOpAst = (path, j) => {
@@ -7914,10 +9064,238 @@ var decodeOp = (json, policy) => {
7914
9064
  resetWalk(policy);
7915
9065
  return decodeTreeOpAst("$", parsed.value);
7916
9066
  };
9067
+ var decodeOps = (json, policy) => {
9068
+ const parsed = parse(json);
9069
+ if (!parsed.ok) return parseFailure(parsed.error);
9070
+ resetWalk(policy);
9071
+ const entries = parsed.value.kind === "JArray" ? parsed.value.items : [parsed.value];
9072
+ const ops = [];
9073
+ for (let i = 0; i < entries.length; i += 1) {
9074
+ const path = parsed.value.kind === "JArray" ? `$[${i}]` : "$";
9075
+ const decoded = decodeTreeOpAst(path, entries[i]);
9076
+ if (!decoded.ok) return decoded;
9077
+ ops.push(decoded.value);
9078
+ }
9079
+ return ok(ops);
9080
+ };
9081
+
9082
+ // src/capabilityDecl.ts
9083
+ var dok2 = (value) => ({ ok: true, value });
9084
+ var derr2 = (error) => ({ ok: false, error });
9085
+ var HOST_WIRE = {
9086
+ Pure: "pure",
9087
+ ReadsHost: "readsHost",
9088
+ WritesHost: "writesHost"
9089
+ };
9090
+ var DETERMINISM_WIRE = {
9091
+ Deterministic: "deterministic",
9092
+ Clock: "clock",
9093
+ Random: "random",
9094
+ Network: "network"
9095
+ };
9096
+ var PLACEMENT_WIRE = {
9097
+ BuildTime: "buildTime",
9098
+ Server: "server",
9099
+ ClientDeclarative: "clientDeclarative",
9100
+ ClientIsland: "clientIsland",
9101
+ Precomputed: "precomputed"
9102
+ };
9103
+ var SPACE_WIRE = {
9104
+ IntRange: "intRange",
9105
+ FloatRange: "floatRange",
9106
+ StringLen: "stringLen",
9107
+ Enum: "enum",
9108
+ AnyString: "anyString"
9109
+ };
9110
+ var ISLANDS = ["pyodide", "fable", "js"];
9111
+ var invert = (m) => Object.fromEntries(Object.entries(m).map(([k, v]) => [v, k]));
9112
+ var HOST_OF = invert(HOST_WIRE);
9113
+ var DETERMINISM_OF = invert(DETERMINISM_WIRE);
9114
+ var PLACEMENT_OF = invert(PLACEMENT_WIRE);
9115
+ var SPACE_OF = invert(SPACE_WIRE);
9116
+ var spaceJson = (s) => {
9117
+ switch (s.kind) {
9118
+ case "IntRange":
9119
+ return caseObj(SPACE_WIRE[s.kind], [
9120
+ ["min", num(s.min)],
9121
+ ["max", num(s.max)]
9122
+ ]);
9123
+ case "FloatRange":
9124
+ return caseObj(SPACE_WIRE[s.kind], [
9125
+ ["min", num(s.min)],
9126
+ ["max", num(s.max)]
9127
+ ]);
9128
+ case "StringLen":
9129
+ return caseObj(SPACE_WIRE[s.kind], [
9130
+ ["min", num(s.minLen)],
9131
+ ["max", num(s.maxLen)]
9132
+ ]);
9133
+ case "Enum":
9134
+ return caseObj(SPACE_WIRE[s.kind], [["values", jArray(s.choices.map(str))]]);
9135
+ case "AnyString":
9136
+ return caseObj(SPACE_WIRE[s.kind], []);
9137
+ }
9138
+ };
9139
+ var entryJson = (e) => {
9140
+ const fields = [
9141
+ ["addr", str(e.addr)],
9142
+ ["name", str(e.name)],
9143
+ ["kind", str(e.kind)],
9144
+ ["required", bool(e.required)]
9145
+ ];
9146
+ if (e.space !== void 0) fields.push(["space", spaceJson(e.space)]);
9147
+ if (e.slotKind !== void 0) fields.push(["slotKind", str(e.slotKind)]);
9148
+ return jObject(fields);
9149
+ };
9150
+ var placementJson = (p) => p.kind === "ClientIsland" ? caseObj(PLACEMENT_WIRE[p.kind], [["island", str(p.island)]]) : caseObj(PLACEMENT_WIRE[p.kind], []);
9151
+ var signatureJson = (sg) => jObject([
9152
+ ["name", str(sg.name)],
9153
+ [
9154
+ "effect",
9155
+ jObject([
9156
+ ["host", str(HOST_WIRE[sg.effect.hostEffect])],
9157
+ ["determinism", str(DETERMINISM_WIRE[sg.effect.determinism])]
9158
+ ])
9159
+ ],
9160
+ ["holes", jArray(sg.holes.map(entryJson))]
9161
+ ]);
9162
+ var encodeCapabilityDeclaration = (cap) => caseObj("capability", [
9163
+ ["id", str(cap.id)],
9164
+ ["signature", signatureJson(cap.signature)],
9165
+ ["determinism", str(DETERMINISM_WIRE[cap.determinism])],
9166
+ ["placement", placementJson(cap.placement)]
9167
+ ]);
9168
+ var DeclError = class extends Error {
9169
+ };
9170
+ var fail2 = (message) => {
9171
+ throw new DeclError(message);
9172
+ };
9173
+ var asObject = (v, what) => typeof v !== "object" || v === null || Array.isArray(v) ? fail2(`${what} is not an object`) : v;
9174
+ var strAt = (o, k) => {
9175
+ const v = o[k];
9176
+ return typeof v === "string" ? v : fail2(`missing or non-string field: ${k}`);
9177
+ };
9178
+ var numAt = (o, k) => {
9179
+ const v = o[k];
9180
+ return typeof v === "number" && Number.isFinite(v) ? v : fail2(`missing or non-finite numeric field: ${k}`);
9181
+ };
9182
+ var spaceOf = (raw) => {
9183
+ const o = asObject(raw, "value-space");
9184
+ const tag = strAt(o, "$type");
9185
+ const kind = SPACE_OF[tag];
9186
+ switch (kind) {
9187
+ case "IntRange":
9188
+ return { kind, min: numAt(o, "min"), max: numAt(o, "max") };
9189
+ case "FloatRange":
9190
+ return { kind, min: numAt(o, "min"), max: numAt(o, "max") };
9191
+ case "StringLen":
9192
+ return { kind, minLen: numAt(o, "min"), maxLen: numAt(o, "max") };
9193
+ case "Enum": {
9194
+ const values = o["values"];
9195
+ if (!Array.isArray(values) || values.some((x) => typeof x !== "string"))
9196
+ fail2("enum values must be a string array");
9197
+ return { kind, choices: values };
9198
+ }
9199
+ case "AnyString":
9200
+ return { kind };
9201
+ default:
9202
+ return fail2(
9203
+ `unknown value-space kind: ${tag}; expected one of: ${Object.values(SPACE_WIRE).join(", ")}`
9204
+ );
9205
+ }
9206
+ };
9207
+ var entryOf = (raw) => {
9208
+ const o = asObject(raw, "signature hole");
9209
+ if ("actionEffect" in o) {
9210
+ fail2(
9211
+ "this host's signature entry carries no action-effect axis, so a hole declaring `actionEffect` cannot round-trip"
9212
+ );
9213
+ }
9214
+ const kind = strAt(o, "kind");
9215
+ if (kind !== "value" && kind !== "slot" && kind !== "repeat")
9216
+ fail2(`unknown hole kind: ${kind}; expected one of: value, slot, repeat`);
9217
+ const required = o["required"];
9218
+ if (typeof required !== "boolean") fail2("missing or non-boolean field: required");
9219
+ return {
9220
+ addr: strAt(o, "addr"),
9221
+ name: strAt(o, "name"),
9222
+ kind,
9223
+ required,
9224
+ ..."space" in o ? { space: spaceOf(o["space"]) } : {},
9225
+ ..."slotKind" in o ? { slotKind: strAt(o, "slotKind") } : {}
9226
+ };
9227
+ };
9228
+ var placementOf = (raw) => {
9229
+ const o = asObject(raw, "placement");
9230
+ const tag = strAt(o, "$type");
9231
+ const kind = PLACEMENT_OF[tag];
9232
+ if (kind === void 0)
9233
+ fail2(`unknown placement: ${tag}; expected one of: ${Object.values(PLACEMENT_WIRE).join(", ")}`);
9234
+ if (kind === "ClientIsland") {
9235
+ const island = strAt(o, "island");
9236
+ if (!ISLANDS.includes(island))
9237
+ fail2(`unknown island kind: ${island}; expected one of: ${ISLANDS.join(", ")}`);
9238
+ return { kind, island };
9239
+ }
9240
+ return { kind };
9241
+ };
9242
+ var declarationOf = (json) => {
9243
+ let parsed;
9244
+ try {
9245
+ parsed = JSON.parse(json);
9246
+ } catch {
9247
+ return fail2("capability declaration is not well-formed JSON");
9248
+ }
9249
+ const o = asObject(parsed, "capability declaration");
9250
+ const tag = o["$type"];
9251
+ if (tag !== void 0 && tag !== "capability")
9252
+ fail2(`not a capability declaration: $type '${String(tag)}'`);
9253
+ const sigObj = asObject(o["signature"], "signature");
9254
+ const effectObj = asObject(sigObj["effect"], "effect");
9255
+ const hostTag = strAt(effectObj, "host");
9256
+ const hostEffect = HOST_OF[hostTag];
9257
+ if (hostEffect === void 0)
9258
+ fail2(
9259
+ `unknown host effect: ${hostTag}; expected one of: ${Object.values(HOST_WIRE).join(", ")}`
9260
+ );
9261
+ const detTag = strAt(effectObj, "determinism");
9262
+ const determinism = DETERMINISM_OF[detTag];
9263
+ if (determinism === void 0)
9264
+ fail2(
9265
+ `unknown determinism: ${detTag}; expected one of: ${Object.values(DETERMINISM_WIRE).join(", ")}`
9266
+ );
9267
+ const holes = sigObj["holes"];
9268
+ if (!Array.isArray(holes)) fail2("missing or non-array field: holes");
9269
+ const signature = {
9270
+ name: strAt(sigObj, "name"),
9271
+ holes: holes.map(entryOf),
9272
+ effect: { hostEffect, determinism }
9273
+ };
9274
+ const wireTag = strAt(o, "determinism");
9275
+ const expectedTag = DETERMINISM_WIRE[determinism];
9276
+ if (wireTag !== expectedTag)
9277
+ fail2(
9278
+ `capability determinism disagrees with signature effect: wire '${wireTag}' vs signature '${expectedTag}'`
9279
+ );
9280
+ return {
9281
+ id: strAt(o, "id"),
9282
+ signature,
9283
+ determinism,
9284
+ placement: placementOf(o["placement"])
9285
+ };
9286
+ };
9287
+ var decodeCapabilityDeclaration = (json) => {
9288
+ try {
9289
+ return dok2(declarationOf(json));
9290
+ } catch (e) {
9291
+ if (e instanceof DeclError) return derr2(e.message);
9292
+ throw e;
9293
+ }
9294
+ };
7917
9295
 
7918
9296
  // src/apply.ts
7919
9297
  var ok2 = (value) => ({ ok: true, value });
7920
- var fail2 = (code, message, batchIndex) => ({
9298
+ var fail3 = (code, message, batchIndex) => ({
7921
9299
  ok: false,
7922
9300
  error: batchIndex === void 0 ? { code, message } : { code, message, batchIndex }
7923
9301
  });
@@ -8754,22 +10132,22 @@ var applyOne = (op, root, telem) => {
8754
10132
  case "EditNode": {
8755
10133
  const updatedTree = mapNode(op.target, (n) => ({ ...n, kind: op.newKind }), root);
8756
10134
  if (updatedTree === void 0)
8757
- return fail2("NodeNotFound", `Node '${op.target}' not found in tree.`);
10135
+ return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
8758
10136
  telem.push({ op: "EditNode", targetId: op.target });
8759
10137
  return ok2(updatedTree);
8760
10138
  }
8761
10139
  case "UpdateProp": {
8762
10140
  const parsed = parsePath(op.path);
8763
10141
  if (!parsed.ok)
8764
- return fail2("PathInvalid", `Path '${op.path}' is structurally invalid: ${parsed.error}.`);
10142
+ return fail3("PathInvalid", `Path '${op.path}' is structurally invalid: ${parsed.error}.`);
8765
10143
  const targetNode = findNode(op.target, root);
8766
10144
  if (targetNode === void 0)
8767
- return fail2("NodeNotFound", `Node '${op.target}' not found in tree.`);
10145
+ return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
8768
10146
  const segs = parsed.value;
8769
10147
  const finish = (kind) => {
8770
10148
  const newTree = mapNode(op.target, (n) => ({ ...n, kind }), root);
8771
10149
  if (newTree === void 0)
8772
- return fail2("NodeNotFound", `Node '${op.target}' not found in tree.`);
10150
+ return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
8773
10151
  telem.push({ op: "UpdateProp", targetId: op.target });
8774
10152
  return ok2(newTree);
8775
10153
  };
@@ -8779,14 +10157,14 @@ var applyOne = (op, root, telem) => {
8779
10157
  case "updated":
8780
10158
  return finish(outcome2.kind);
8781
10159
  case "unknownField":
8782
- return fail2("FieldNotFound", `Field '${op.path}' not found on node '${op.target}'.`);
10160
+ return fail3("FieldNotFound", `Field '${op.path}' not found on node '${op.target}'.`);
8783
10161
  case "notSupported":
8784
- return fail2(
10162
+ return fail3(
8785
10163
  "PathNotSupportedYet",
8786
10164
  `Path '${op.path}' on node '${op.target}' is not yet supported by the apply engine.`
8787
10165
  );
8788
10166
  case "typeMismatch":
8789
- return fail2(
10167
+ return fail3(
8790
10168
  "KindMismatch",
8791
10169
  `UpdateProp value for '${op.path}' on node '${op.target}' does not match the field's expected type: ${outcome2.detail}`
8792
10170
  );
@@ -8798,27 +10176,27 @@ var applyOne = (op, root, telem) => {
8798
10176
  case "updated":
8799
10177
  return finish(outcome.kind);
8800
10178
  case "missingIndex":
8801
- return fail2(
10179
+ return fail3(
8802
10180
  "PathInvalid",
8803
10181
  `Field '${outcome.listField}' on node '${op.target}' is a list \u2014 address an element with a 0-based index (the list has ${outcome.count} element(s)).`
8804
10182
  );
8805
10183
  case "indexOutOfRange":
8806
- return fail2(
10184
+ return fail3(
8807
10185
  "PositionOutOfRange",
8808
10186
  `Index ${outcome.requested} is out of range for '${outcome.listField}' on node '${op.target}' (${outcome.count === 0 ? "the list is empty" : `valid: 0..${outcome.count - 1}`}).`
8809
10187
  );
8810
10188
  case "fieldNotFound":
8811
- return fail2(
10189
+ return fail3(
8812
10190
  "FieldNotFound",
8813
10191
  `Field '${outcome.segment}' (in path '${op.path}') not found on node '${op.target}'. Available at this segment: ${outcome.available.join(", ")}.`
8814
10192
  );
8815
10193
  case "notSupported":
8816
- return fail2(
10194
+ return fail3(
8817
10195
  "PathNotSupportedYet",
8818
10196
  `Path '${op.path}' on node '${op.target}' is not yet supported by the apply engine.`
8819
10197
  );
8820
10198
  case "typeMismatch":
8821
- return fail2(
10199
+ return fail3(
8822
10200
  "KindMismatch",
8823
10201
  `UpdateProp value for '${op.path}' on node '${op.target}' does not match the field's expected type: ${outcome.detail}`
8824
10202
  );
@@ -8828,20 +10206,20 @@ var applyOne = (op, root, telem) => {
8828
10206
  case "ReplaceBinding": {
8829
10207
  const targetNode = findNode(op.target, root);
8830
10208
  if (targetNode === void 0)
8831
- return fail2("NodeNotFound", `Node '${op.target}' not found in tree.`);
10209
+ return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
8832
10210
  const newKind = replaceBinding(op.slot, op.binding, targetNode.kind);
8833
10211
  if (newKind === void 0)
8834
- return fail2("SlotNotFound", `Binding slot '${op.slot}' not found on node '${op.target}'.`);
10212
+ return fail3("SlotNotFound", `Binding slot '${op.slot}' not found on node '${op.target}'.`);
8835
10213
  const newTree = mapNode(op.target, (n) => ({ ...n, kind: newKind }), root);
8836
10214
  if (newTree === void 0)
8837
- return fail2("NodeNotFound", `Node '${op.target}' not found in tree.`);
10215
+ return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
8838
10216
  telem.push({ op: "ReplaceBinding", targetId: op.target });
8839
10217
  return ok2(newTree);
8840
10218
  }
8841
10219
  case "UpdateStyle": {
8842
10220
  const newTree = mapNode(op.target, (n) => ({ ...n, style: op.style }), root);
8843
10221
  if (newTree === void 0)
8844
- return fail2("NodeNotFound", `Node '${op.target}' not found in tree.`);
10222
+ return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
8845
10223
  telem.push({ op: "UpdateStyle", targetId: op.target });
8846
10224
  return ok2(newTree);
8847
10225
  }
@@ -8852,39 +10230,39 @@ var applyOne = (op, root, telem) => {
8852
10230
  root
8853
10231
  );
8854
10232
  if (newTree === void 0)
8855
- return fail2("NodeNotFound", `Node '${op.target}' not found in tree.`);
10233
+ return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
8856
10234
  telem.push({ op: "UpdateState", targetId: op.target });
8857
10235
  return ok2(newTree);
8858
10236
  }
8859
10237
  case "InsertChild": {
8860
10238
  const parent = findNode(op.parentId, root);
8861
10239
  if (parent === void 0)
8862
- return fail2("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
10240
+ return fail3("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
8863
10241
  const children = layoutChildren(parent);
8864
10242
  if (children === void 0)
8865
- return fail2(
10243
+ return fail3(
8866
10244
  "ChildlessKind",
8867
10245
  `Node '${op.parentId}' (kind=${parent.kind.kind}) has no children field \u2014 only Layout kinds accept structural child ops.`
8868
10246
  );
8869
10247
  const existing = new Set(allNodeIds(root));
8870
10248
  const duplicate = allNodeIds(op.child).find((id) => existing.has(id));
8871
10249
  if (duplicate !== void 0)
8872
- return fail2(
10250
+ return fail3(
8873
10251
  "DuplicateNodeId",
8874
10252
  `NodeId '${duplicate}' is already present in the tree; ids must be unique.`
8875
10253
  );
8876
10254
  const newChildren = [...children, op.child];
8877
10255
  const newTree = mapNode(op.parentId, (n) => withLayoutChildren(n, newChildren), root);
8878
10256
  if (newTree === void 0)
8879
- return fail2("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
10257
+ return fail3("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
8880
10258
  telem.push({ op: "InsertChild", targetId: op.parentId });
8881
10259
  return ok2(newTree);
8882
10260
  }
8883
10261
  case "RemoveNode": {
8884
- if (idOf(root) === op.target) return fail2("KindMismatch", "Cannot RemoveNode the root.");
10262
+ if (idOf(root) === op.target) return fail3("KindMismatch", "Cannot RemoveNode the root.");
8885
10263
  const parent = findLayoutParent(op.target, root);
8886
10264
  if (parent === void 0)
8887
- return fail2("NodeNotFound", `Node '${op.target}' not found in tree.`);
10265
+ return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
8888
10266
  const children = layoutChildren(parent);
8889
10267
  const newTree = mapNode(
8890
10268
  idOf(parent),
@@ -8895,26 +10273,26 @@ var applyOne = (op, root, telem) => {
8895
10273
  root
8896
10274
  );
8897
10275
  if (newTree === void 0)
8898
- return fail2("ParentNotFound", `Parent node '${idOf(parent)}' not found in tree.`);
10276
+ return fail3("ParentNotFound", `Parent node '${idOf(parent)}' not found in tree.`);
8899
10277
  telem.push({ op: "RemoveNode", targetId: op.target });
8900
10278
  return ok2(newTree);
8901
10279
  }
8902
10280
  case "MoveNode": {
8903
10281
  if (op.target === op.newParentId)
8904
- return fail2("KindMismatch", "Cannot move a node into itself.");
10282
+ return fail3("KindMismatch", "Cannot move a node into itself.");
8905
10283
  if (isAncestor(op.target, op.newParentId, root))
8906
- return fail2(
10284
+ return fail3(
8907
10285
  "KindMismatch",
8908
10286
  "Cannot move a node into its own descendant (would create a cycle)."
8909
10287
  );
8910
10288
  const moving = findNode(op.target, root);
8911
10289
  if (moving === void 0)
8912
- return fail2("NodeNotFound", `Node '${op.target}' not found in tree.`);
10290
+ return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
8913
10291
  const newParent = findNode(op.newParentId, root);
8914
10292
  if (newParent === void 0)
8915
- return fail2("ParentNotFound", `Parent node '${op.newParentId}' not found in tree.`);
10293
+ return fail3("ParentNotFound", `Parent node '${op.newParentId}' not found in tree.`);
8916
10294
  if (layoutChildren(newParent) === void 0)
8917
- return fail2(
10295
+ return fail3(
8918
10296
  "ChildlessKind",
8919
10297
  `Node '${op.newParentId}' (kind=${newParent.kind.kind}) has no children field.`
8920
10298
  );
@@ -8932,10 +10310,10 @@ var applyOne = (op, root, telem) => {
8932
10310
  case "ReorderChildren": {
8933
10311
  const parent = findNode(op.parentId, root);
8934
10312
  if (parent === void 0)
8935
- return fail2("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
10313
+ return fail3("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
8936
10314
  const children = layoutChildren(parent);
8937
10315
  if (children === void 0)
8938
- return fail2(
10316
+ return fail3(
8939
10317
  "ChildlessKind",
8940
10318
  `Node '${op.parentId}' (kind=${parent.kind.kind}) has no children field.`
8941
10319
  );
@@ -8943,7 +10321,7 @@ var applyOne = (op, root, telem) => {
8943
10321
  const sortedCurrent = [...currentIds].sort();
8944
10322
  const sortedNew = [...op.newOrder].map((x) => x).sort();
8945
10323
  if (sortedCurrent.length !== sortedNew.length || sortedCurrent.some((id, i) => id !== sortedNew[i]))
8946
- return fail2(
10324
+ return fail3(
8947
10325
  "OrderingMismatch",
8948
10326
  `ReorderChildren for '${op.parentId}' did not list exactly the current child ids.`
8949
10327
  );
@@ -8951,7 +10329,7 @@ var applyOne = (op, root, telem) => {
8951
10329
  const reordered = op.newOrder.map((id) => byId.get(id)).filter((c) => c !== void 0);
8952
10330
  const newTree = mapNode(op.parentId, (n) => withLayoutChildren(n, reordered), root);
8953
10331
  if (newTree === void 0)
8954
- return fail2("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
10332
+ return fail3("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
8955
10333
  telem.push({ op: "ReorderChildren", targetId: op.parentId });
8956
10334
  return ok2(newTree);
8957
10335
  }
@@ -8976,7 +10354,7 @@ var applyOne = (op, root, telem) => {
8976
10354
  return ok2(state);
8977
10355
  }
8978
10356
  }
8979
- return fail2("KindMismatch", "unreachable apply branch");
10357
+ return fail3("KindMismatch", "unreachable apply branch");
8980
10358
  };
8981
10359
  var apply = (tree, op) => {
8982
10360
  const telem = [];
@@ -9160,10 +10538,12 @@ var str2 = (s) => {
9160
10538
  }
9161
10539
  return out + '"';
9162
10540
  };
10541
+ var encodeActorValue = (a) => a.kind === "human" ? `{"kind":"human","id":${str2(a.id)}}` : `{"kind":"agent","model":${str2(a.model)},"version":${str2(a.version)},"id":${str2(a.id)}}`;
9163
10542
  var encodeEnvelope = (e) => e.$type === "Success" ? '{"$type":"Success"}' : `{"$type":"Failure","code":${str2(e.code)},"message":${str2(e.message)}}`;
9164
10543
  var encodeDagRecord = (record) => {
9165
10544
  let out = "{";
9166
- out += `"hash":${str2(record.hash)}`;
10545
+ out += `"actor":${encodeActorValue(record.actor)}`;
10546
+ out += `,"hash":${str2(record.hash)}`;
9167
10547
  out += `,"op":${encodeOp(record.op)}`;
9168
10548
  if (record.outcomeHash !== void 0) out += `,"outcomeHash":${str2(record.outcomeHash)}`;
9169
10549
  out += `,"parents":[${record.parents.map(str2).join(",")}]`;
@@ -9172,7 +10552,6 @@ var encodeDagRecord = (record) => {
9172
10552
  out += `,"streamId":${str2(record.streamId)}`;
9173
10553
  out += `,"timestamp":${record.timestamp}`;
9174
10554
  out += `,"tombstoned":${record.tombstoned ? "true" : "false"}`;
9175
- out += `,"userId":${str2(record.userId)}`;
9176
10555
  return out + "}";
9177
10556
  };
9178
10557
  var astToJson = (ast) => {
@@ -9195,6 +10574,20 @@ var astToJson = (ast) => {
9195
10574
  }
9196
10575
  };
9197
10576
  var asString = (ast) => ast !== void 0 && ast.kind === "JString" ? ast.value : void 0;
10577
+ var decodeActor = (ast) => {
10578
+ if (ast === void 0 || ast.kind !== "JObject") return void 0;
10579
+ const kind = asString(field(ast.fields, "kind"));
10580
+ const id = asString(field(ast.fields, "id"));
10581
+ if (id === void 0) return void 0;
10582
+ if (kind === "human") return { kind: "human", id };
10583
+ if (kind === "agent") {
10584
+ const model = asString(field(ast.fields, "model"));
10585
+ const version = asString(field(ast.fields, "version"));
10586
+ if (model === void 0 || version === void 0) return void 0;
10587
+ return { kind: "agent", model, version, id };
10588
+ }
10589
+ return void 0;
10590
+ };
9198
10591
  var decodeDagRecord = (json) => {
9199
10592
  const parsed = parse(json);
9200
10593
  if (!parsed.ok) return { ok: false, error: `dag envelope parse: ${parsed.error.message}` };
@@ -9203,12 +10596,19 @@ var decodeDagRecord = (json) => {
9203
10596
  const f = root.fields;
9204
10597
  const hash = asString(field(f, "hash"));
9205
10598
  const streamId = asString(field(f, "streamId"));
9206
- const userId = asString(field(f, "userId"));
10599
+ const actorAst = field(f, "actor");
9207
10600
  const opAst = field(f, "op");
9208
10601
  const parentsAst = field(f, "parents");
9209
10602
  const tsAst = field(f, "timestamp");
9210
- if (hash === void 0 || streamId === void 0 || userId === void 0)
9211
- return { ok: false, error: "dag envelope: missing hash/streamId/userId" };
10603
+ if (actorAst === void 0 && field(f, "userId") !== void 0)
10604
+ return {
10605
+ ok: false,
10606
+ error: "dag envelope: pre-1144 record \u2014 'userId' was replaced by the typed 'actor', and DAG content addresses do not carry forward"
10607
+ };
10608
+ if (hash === void 0 || streamId === void 0)
10609
+ return { ok: false, error: "dag envelope: missing hash/streamId" };
10610
+ const actor = decodeActor(actorAst);
10611
+ if (actor === void 0) return { ok: false, error: "dag envelope: missing/malformed 'actor'" };
9212
10612
  if (opAst === void 0) return { ok: false, error: "dag envelope: missing op" };
9213
10613
  if (parentsAst === void 0 || parentsAst.kind !== "JArray")
9214
10614
  return { ok: false, error: "dag envelope: missing/!array parents" };
@@ -9244,7 +10644,7 @@ var decodeDagRecord = (json) => {
9244
10644
  op: opResult.value,
9245
10645
  ...outcomeHash !== void 0 ? { outcomeHash } : {},
9246
10646
  ...promptId !== void 0 ? { promptId } : {},
9247
- userId,
10647
+ actor,
9248
10648
  timestamp: tsAst.value,
9249
10649
  resultEnvelope,
9250
10650
  tombstoned: tombAst !== void 0 && tombAst.kind === "JBool" && tombAst.value
@@ -9277,11 +10677,20 @@ var isPureAddition = (baseIds, headIds) => {
9277
10677
  return survive.length === baseIds.length && survive.every((v, i) => v === baseIds[i]) && headKept.length === baseIds.length && headKept.every((v, i) => v === baseIds[i]);
9278
10678
  };
9279
10679
  var eqOpt = (x, y) => (x ?? null) === (y ?? null);
9280
- var pickField = (conflicts, nodeId, facet, baseV, aV, bV) => {
10680
+ var refusal = (nodeId, facet, cls, base, aValue, bValue) => ({
10681
+ nodeId,
10682
+ facet,
10683
+ class: cls,
10684
+ base,
10685
+ a: { value: aValue },
10686
+ b: { value: bValue },
10687
+ primacyHeld: false
10688
+ });
10689
+ var pickField = (conflicts, nodeId, facet, dflt, baseV, aV, bV) => {
9281
10690
  const aCh = !eqOpt(aV, baseV);
9282
10691
  const bCh = !eqOpt(bV, baseV);
9283
10692
  if (aCh && bCh && !eqOpt(aV, bV)) {
9284
- conflicts.push({ nodeId, facet });
10693
+ conflicts.push(refusal(nodeId, facet, "ConcurrentEdit", baseV ?? dflt, aV ?? dflt, bV ?? dflt));
9285
10694
  return baseV;
9286
10695
  }
9287
10696
  if (aCh) return aV;
@@ -9292,7 +10701,7 @@ var pickCanonical = (conflicts, nodeId, facet, baseC, aC, bC) => {
9292
10701
  const aCh = aC !== baseC;
9293
10702
  const bCh = bC !== baseC;
9294
10703
  if (aCh && bCh && aC !== bC) {
9295
- conflicts.push({ nodeId, facet });
10704
+ conflicts.push(refusal(nodeId, facet, "ConcurrentEdit", baseC, aC, bC));
9296
10705
  return 0;
9297
10706
  }
9298
10707
  if (aCh) return 1;
@@ -9303,18 +10712,28 @@ var mergeStyle = (conflicts, id, base, a, b) => {
9303
10712
  const bs = base.style;
9304
10713
  const as_ = a.style;
9305
10714
  const bsB = b.style;
9306
- const tone = pickField(conflicts, id, "style.tone", bs.tone, as_.tone, bsB.tone);
9307
- const weight = pickField(conflicts, id, "style.weight", bs.weight, as_.weight, bsB.weight);
10715
+ const d = schema.defaults.style;
10716
+ const tone = pickField(conflicts, id, "style.tone", d.tone, bs.tone, as_.tone, bsB.tone);
10717
+ const weight = pickField(
10718
+ conflicts,
10719
+ id,
10720
+ "style.weight",
10721
+ d.weight,
10722
+ bs.weight,
10723
+ as_.weight,
10724
+ bsB.weight
10725
+ );
9308
10726
  const emphasis = pickField(
9309
10727
  conflicts,
9310
10728
  id,
9311
10729
  "style.emphasis",
10730
+ d.emphasis,
9312
10731
  bs.emphasis,
9313
10732
  as_.emphasis,
9314
10733
  bsB.emphasis
9315
10734
  );
9316
- const role = pickField(conflicts, id, "style.role", bs.role, as_.role, bsB.role);
9317
- const voice = pickField(conflicts, id, "style.voice", bs.voice, as_.voice, bsB.voice);
10735
+ const role = pickField(conflicts, id, "style.role", d.role, bs.role, as_.role, bsB.role);
10736
+ const voice = pickField(conflicts, id, "style.voice", d.voice, bs.voice, as_.voice, bsB.voice);
9318
10737
  const style = { tone, weight, emphasis };
9319
10738
  return {
9320
10739
  ...style,
@@ -9370,8 +10789,15 @@ var merge3 = (conflicts, base, aOpt, bOpt) => {
9370
10789
  const bc = baseMap.get(cid);
9371
10790
  if (bc !== void 0) return merge3(conflicts, bc, aMap.get(cid), bMap.get(cid));
9372
10791
  const ac = aMap.get(cid);
9373
- if (ac !== void 0) return ac;
9374
10792
  const bb = bMap.get(cid);
10793
+ if (ac !== void 0 && bb !== void 0) {
10794
+ const acC = encodeNode(ac);
10795
+ const bcC = encodeNode(bb);
10796
+ if (acC === bcC) return ac;
10797
+ conflicts.push(refusal(cid, "insert", "ConcurrentEdit", "", acC, bcC));
10798
+ return ordinal(acC, bcC) <= 0 ? ac : bb;
10799
+ }
10800
+ if (ac !== void 0) return ac;
9375
10801
  if (bb !== void 0) return bb;
9376
10802
  throw new Error(`merge3: child id ${cid} vanished`);
9377
10803
  };
@@ -9382,6 +10808,8 @@ var merge3 = (conflicts, base, aOpt, bOpt) => {
9382
10808
  mergedChildren = aIds.map(recurseChild);
9383
10809
  } else if (!aStruct && bStruct) {
9384
10810
  mergedChildren = bIds.map(recurseChild);
10811
+ } else if (JSON.stringify(aIds) === JSON.stringify(bIds)) {
10812
+ mergedChildren = aIds.map(recurseChild);
9385
10813
  } else {
9386
10814
  const baseSet = new Set(baseIds);
9387
10815
  const aNew = aIds.filter((i) => !baseSet.has(i));
@@ -9393,7 +10821,16 @@ var merge3 = (conflicts, base, aOpt, bOpt) => {
9393
10821
  const newIds = [.../* @__PURE__ */ new Set([...aNew, ...bNew])].sort(ordinal);
9394
10822
  mergedChildren = [...survivors, ...newIds.map(recurseChild)];
9395
10823
  } else {
9396
- conflicts.push({ nodeId: id, facet: "children" });
10824
+ conflicts.push(
10825
+ refusal(
10826
+ id,
10827
+ "children",
10828
+ "ReorderVsStructural",
10829
+ baseIds.join(","),
10830
+ aIds.join(","),
10831
+ bIds.join(",")
10832
+ )
10833
+ );
9397
10834
  mergedChildren = baseIds.map(recurseChild);
9398
10835
  }
9399
10836
  }
@@ -9405,6 +10842,21 @@ var merge3Way = (base, a, b) => {
9405
10842
  const merged = merge3(conflicts, base, a, b);
9406
10843
  return conflicts.length === 0 ? { ok: true, tree: merged } : { ok: false, conflicts };
9407
10844
  };
10845
+ var sortConflictsCanonical = (conflicts) => [...conflicts].sort((x, y) => ordinal(x.nodeId, y.nodeId) || ordinal(x.facet, y.facet));
10846
+ var escapeJson = (s) => {
10847
+ let out = '"';
10848
+ for (const ch of s) {
10849
+ if (ch === '"') out += '\\"';
10850
+ else if (ch === "\\") out += "\\\\";
10851
+ else if (ch < " ") out += `\\u${ch.charCodeAt(0).toString(16).padStart(4, "0")}`;
10852
+ else out += ch;
10853
+ }
10854
+ return out + '"';
10855
+ };
10856
+ var encodeSide = (side) => `{"tag":${side.tag === void 0 ? "null" : escapeJson(side.tag)},"value":${escapeJson(side.value)}}`;
10857
+ var encodeMergeEnvelope = (conflicts) => "[" + sortConflictsCanonical(conflicts).map(
10858
+ (c) => `{"a":${encodeSide(c.a)},"b":${encodeSide(c.b)},"base":${escapeJson(c.base)},"class":${escapeJson(c.class)},"facet":${escapeJson(c.facet)},"nodeId":${escapeJson(c.nodeId)},"primacyHeld":${c.primacyHeld ? "true" : "false"}}`
10859
+ ).join(",") + "]";
9408
10860
 
9409
10861
  // src/versioning.ts
9410
10862
  var renderProfile = (p) => `${p.name}@${p.major}.${p.minor}`;
@@ -10292,19 +11744,23 @@ var withStateSeeds = (tree, sources) => {
10292
11744
  return { ...sources, state: { ...seeds, ...sources.state ?? {} } };
10293
11745
  };
10294
11746
 
11747
+ exports.DECODED_COMPUTED_MESSAGE = DECODED_COMPUTED_MESSAGE;
10295
11748
  exports.ELICITATION_KEY = ELICITATION_KEY;
10296
11749
  exports.ELICITATION_VERSION = ELICITATION_VERSION;
10297
11750
  exports.HOST_RESERVED_PREFIX = HOST_RESERVED_PREFIX;
10298
11751
  exports.PAYLOAD_KEY = PAYLOAD_KEY;
10299
11752
  exports.PROFILE_KEY = PROFILE_KEY;
10300
11753
  exports.REQUIRED_PROFILE_KEY = REQUIRED_PROFILE_KEY;
11754
+ exports.WireSurvivabilityError = WireSurvivabilityError;
10301
11755
  exports.apply = apply;
10302
11756
  exports.canPlace = canPlace;
10303
11757
  exports.cellString = cellString;
10304
11758
  exports.coerce = coerce;
10305
11759
  exports.collectStateSeeds = collectStateSeeds;
10306
11760
  exports.coreV1 = coreV1;
11761
+ exports.decodeCapabilityDeclaration = decodeCapabilityDeclaration;
10307
11762
  exports.decodeDagRecord = decodeDagRecord;
11763
+ exports.decodeDataSource = decodeDataSource;
10308
11764
  exports.decodeElicitation = decodeElicitation;
10309
11765
  exports.decodeElicitationOutcome = decodeElicitationOutcome;
10310
11766
  exports.decodeEnvelope = decodeEnvelope;
@@ -10312,10 +11768,13 @@ exports.decodeEnvelopeAst = decodeEnvelopeAst;
10312
11768
  exports.decodeNode = decodeNode;
10313
11769
  exports.decodeNodeTolerant = decodeNodeTolerant;
10314
11770
  exports.decodeOp = decodeOp;
11771
+ exports.decodeOps = decodeOps;
11772
+ exports.decodePipeline = decodePipelineCore;
10315
11773
  exports.decodeTolerant = decodeTolerant;
10316
11774
  exports.derivedFreshIds = derivedFreshIds;
10317
11775
  exports.duplicateOp = duplicateOp;
10318
11776
  exports.duplicateOpWith = duplicateOpWith;
11777
+ exports.encodeCapabilityDeclaration = encodeCapabilityDeclaration;
10319
11778
  exports.encodeCell = encodeCell;
10320
11779
  exports.encodeColExpr = encodeColExpr;
10321
11780
  exports.encodeDagRecord = encodeDagRecord;
@@ -10323,6 +11782,7 @@ exports.encodeDataSource = encodeDataSource;
10323
11782
  exports.encodeElicitation = encodeElicitation;
10324
11783
  exports.encodeElicitationOutcome = encodeElicitationOutcome;
10325
11784
  exports.encodeEnvelope = encodeEnvelope2;
11785
+ exports.encodeMergeEnvelope = encodeMergeEnvelope;
10326
11786
  exports.encodeNode = encodeNode;
10327
11787
  exports.encodeOp = encodeOp;
10328
11788
  exports.encodePipeline = encodePipeline;
@@ -10332,6 +11792,8 @@ exports.evalPipelineInEnv = evalPipelineInEnv;
10332
11792
  exports.evalPipelineWith = evalPipelineWith;
10333
11793
  exports.evalPipelineWithInEnv = evalPipelineWithInEnv;
10334
11794
  exports.evalSource = evalSource;
11795
+ exports.fixedText = fixedText;
11796
+ exports.identityFormat = identityFormat;
10335
11797
  exports.jsonField = field;
10336
11798
  exports.liveValueToTable = liveValueToTable;
10337
11799
  exports.merge3Way = merge3Way;
@@ -10340,6 +11802,7 @@ exports.negotiate = negotiate;
10340
11802
  exports.negotiateEnvelope = negotiateEnvelope;
10341
11803
  exports.noResolve = noResolve;
10342
11804
  exports.nudgeOp = nudgeOp;
11805
+ exports.numberText = numberText;
10343
11806
  exports.parse = parse;
10344
11807
  exports.pasteOp = pasteOp;
10345
11808
  exports.pasteOpWith = pasteOpWith;
@@ -10348,8 +11811,12 @@ exports.placeOp = placeOp;
10348
11811
  exports.reencodeNode = reencodeNode;
10349
11812
  exports.renderAstCanonical = renderAstCanonical;
10350
11813
  exports.renderProfile = renderProfile;
11814
+ exports.scalarOfText = scalarOfText;
10351
11815
  exports.sequentialFreshIds = sequentialFreshIds;
11816
+ exports.sortConflictsCanonical = sortConflictsCanonical;
10352
11817
  exports.stepParams = stepParams;
11818
+ exports.substituteListParams = substituteListParams;
11819
+ exports.tryNumberText = tryNumberText;
10353
11820
  exports.tryParseProfile = tryParseProfile;
10354
11821
  exports.validateAnswer = validateAnswer;
10355
11822
  exports.validateAnswerAt = validateAnswerAt;