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