@fuaran-ui/conformance 0.1.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.
Files changed (301) hide show
  1. package/LICENSE +215 -0
  2. package/README.md +85 -0
  3. package/corpus/elicitation/elc-ans-accept-full.json +1 -0
  4. package/corpus/elicitation/elc-ans-accept-int-for-float.json +1 -0
  5. package/corpus/elicitation/elc-ans-accept-minimal.json +1 -0
  6. package/corpus/elicitation/elc-ans-reject-enum.json +1 -0
  7. package/corpus/elicitation/elc-ans-reject-float-range.json +1 -0
  8. package/corpus/elicitation/elc-ans-reject-int-range.json +1 -0
  9. package/corpus/elicitation/elc-ans-reject-missing-required.json +1 -0
  10. package/corpus/elicitation/elc-ans-reject-string-len.json +1 -0
  11. package/corpus/elicitation/elc-ans-reject-type-mismatch.json +1 -0
  12. package/corpus/elicitation/elc-ans-reject-undeclared.json +1 -0
  13. package/corpus/elicitation/elc-full.json +1 -0
  14. package/corpus/elicitation/elc-minimal.json +1 -0
  15. package/corpus/elicitation/elc-out-answered.json +1 -0
  16. package/corpus/elicitation/elc-out-declined.json +1 -0
  17. package/corpus/elicitation/elc-out-reject-empty-id.json +1 -0
  18. package/corpus/elicitation/elc-out-reject-missing-answer.json +1 -0
  19. package/corpus/elicitation/elc-out-reject-stray-key.json +1 -0
  20. package/corpus/elicitation/elc-out-reject-unknown-type.json +1 -0
  21. package/corpus/elicitation/elc-out-superseded-anon.json +1 -0
  22. package/corpus/elicitation/elc-out-superseded-by.json +1 -0
  23. package/corpus/elicitation/elc-out-timedout.json +1 -0
  24. package/corpus/elicitation/elc-reject-bad-space.json +1 -0
  25. package/corpus/elicitation/elc-reject-bad-timeout.json +1 -0
  26. package/corpus/elicitation/elc-reject-bad-version.json +1 -0
  27. package/corpus/elicitation/elc-reject-default-nonconformant.json +1 -0
  28. package/corpus/elicitation/elc-reject-duplicate-field.json +1 -0
  29. package/corpus/elicitation/elc-reject-empty-contract.json +1 -0
  30. package/corpus/elicitation/elc-reject-empty-id.json +1 -0
  31. package/corpus/elicitation/elc-reject-missing-version.json +1 -0
  32. package/corpus/elicitation/elc-reject-stray-key.json +1 -0
  33. package/corpus/elicitation/elc-reject-tree-decode.json +1 -0
  34. package/corpus/elicitation/elc-reject-unknown-node.json +1 -0
  35. package/corpus/envelope/envelope-foreign-major.json +1 -0
  36. package/corpus/envelope/envelope-foreign-namespace.json +1 -0
  37. package/corpus/envelope/envelope-known-current.json +1 -0
  38. package/corpus/envelope/envelope-unknown-behind.json +1 -0
  39. package/corpus/envelope/envelope-unknown-malformed-required-profile.json +1 -0
  40. package/corpus/envelope/envelope-unknown-required-profile.json +1 -0
  41. package/corpus/lenient/legacy-upgrade-card.expected.json +1 -0
  42. package/corpus/lenient/legacy-upgrade-card.json +1 -0
  43. package/corpus/lenient/legacy-upgrade-dashboard.expected.json +1 -0
  44. package/corpus/lenient/legacy-upgrade-dashboard.json +1 -0
  45. package/corpus/lenient/legacy-upgrade-gridlayout.expected.json +1 -0
  46. package/corpus/lenient/legacy-upgrade-gridlayout.json +1 -0
  47. package/corpus/lenient/legacy-upgrade-stack.expected.json +1 -0
  48. package/corpus/lenient/legacy-upgrade-stack.json +1 -0
  49. package/corpus/lenient/legacy-upgrade-table.expected.json +1 -0
  50. package/corpus/lenient/legacy-upgrade-table.json +1 -0
  51. package/corpus/lenient/lenient-022-lvr-emphasis-loud.expected.json +1 -0
  52. package/corpus/lenient/lenient-022-lvr-emphasis-loud.json +1 -0
  53. package/corpus/lenient/lenient-022-lvr-emphasis-normal.expected.json +1 -0
  54. package/corpus/lenient/lenient-022-lvr-emphasis-normal.json +1 -0
  55. package/corpus/lenient/lenient-460-alias-emphasis-muted.expected.json +1 -0
  56. package/corpus/lenient/lenient-460-alias-emphasis-muted.json +1 -0
  57. package/corpus/lenient/lenient-460-alias-emphasis-strong.expected.json +1 -0
  58. package/corpus/lenient/lenient-460-alias-emphasis-strong.json +1 -0
  59. package/corpus/lenient/lenient-460-alias-tone-danger.expected.json +1 -0
  60. package/corpus/lenient/lenient-460-alias-tone-danger.json +1 -0
  61. package/corpus/lenient/lenient-460-alias-tone-positive.expected.json +1 -0
  62. package/corpus/lenient/lenient-460-alias-tone-positive.json +1 -0
  63. package/corpus/lenient/lenient-460-explicit-default-column.expected.json +1 -0
  64. package/corpus/lenient/lenient-460-explicit-default-column.json +1 -0
  65. package/corpus/lenient/lenient-460-explicit-default-metric.expected.json +1 -0
  66. package/corpus/lenient/lenient-460-explicit-default-metric.json +1 -0
  67. package/corpus/lenient/lenient-460-explicit-default-style.expected.json +1 -0
  68. package/corpus/lenient/lenient-460-explicit-default-style.json +1 -0
  69. package/corpus/lenient/lenient-596-form-explicit-auto-state.expected.json +1 -0
  70. package/corpus/lenient/lenient-596-form-explicit-auto-state.json +1 -0
  71. package/corpus/lenient/lenient-alias-call-url.expected.json +1 -0
  72. package/corpus/lenient/lenient-alias-call-url.json +1 -0
  73. package/corpus/lenient/lenient-alias-card-title-metric-value.expected.json +1 -0
  74. package/corpus/lenient/lenient-alias-card-title-metric-value.json +1 -0
  75. package/corpus/lenient/lenient-alias-datagrid-data-column-type.expected.json +1 -0
  76. package/corpus/lenient/lenient-alias-datagrid-data-column-type.json +1 -0
  77. package/corpus/lenient/lenient-alias-form-field-name.expected.json +1 -0
  78. package/corpus/lenient/lenient-alias-form-field-name.json +1 -0
  79. package/corpus/lenient/lenient-alias-grid-columns-row.expected.json +1 -0
  80. package/corpus/lenient/lenient-alias-grid-columns-row.json +1 -0
  81. package/corpus/lenient/lenient-alias-navigate-href.expected.json +1 -0
  82. package/corpus/lenient/lenient-alias-navigate-href.json +1 -0
  83. package/corpus/lenient/lenient-alias-select-options-query-deps.expected.json +1 -0
  84. package/corpus/lenient/lenient-alias-select-options-query-deps.json +1 -0
  85. package/corpus/lenient/lenient-bare-text-button-label.expected.json +1 -0
  86. package/corpus/lenient/lenient-bare-text-button-label.json +1 -0
  87. package/corpus/lenient/lenient-bare-text-callout.expected.json +1 -0
  88. package/corpus/lenient/lenient-bare-text-callout.json +1 -0
  89. package/corpus/lenient/lenient-bare-text-heading.expected.json +1 -0
  90. package/corpus/lenient/lenient-bare-text-heading.json +1 -0
  91. package/corpus/lenient/lenient-bare-text-markdown.expected.json +1 -0
  92. package/corpus/lenient/lenient-bare-text-markdown.json +1 -0
  93. package/corpus/lenient/lenient-binding-bound-wrapper.expected.json +1 -0
  94. package/corpus/lenient/lenient-binding-bound-wrapper.json +1 -0
  95. package/corpus/lenient/lenient-emphasis-cross-vocab.expected.json +1 -0
  96. package/corpus/lenient/lenient-emphasis-cross-vocab.json +1 -0
  97. package/corpus/lenient/lenient-fact-explicit-defaults.expected.json +1 -0
  98. package/corpus/lenient/lenient-fact-explicit-defaults.json +1 -0
  99. package/corpus/lenient/lenient-null-static-options.expected.json +1 -0
  100. package/corpus/lenient/lenient-null-static-options.json +1 -0
  101. package/corpus/lenient/lenient-opaque-static-markers.expected.json +1 -0
  102. package/corpus/lenient/lenient-opaque-static-markers.json +1 -0
  103. package/corpus/lenient/lenient-opaque-static-options.expected.json +1 -0
  104. package/corpus/lenient/lenient-opaque-static-options.json +1 -0
  105. package/corpus/lenient/lenient-opaque-static-series.expected.json +1 -0
  106. package/corpus/lenient/lenient-opaque-static-series.json +1 -0
  107. package/corpus/lenient/lenient-opaque-static-values.expected.json +1 -0
  108. package/corpus/lenient/lenient-opaque-static-values.json +1 -0
  109. package/corpus/lenient/lenient-shape-binding-scalar-fraction.expected.json +1 -0
  110. package/corpus/lenient/lenient-shape-binding-scalar-fraction.json +1 -0
  111. package/corpus/lenient/lenient-shape-grid-no-cols.expected.json +1 -0
  112. package/corpus/lenient/lenient-shape-grid-no-cols.json +1 -0
  113. package/corpus/lenient/lenient-shape-grid-template-no-cols.expected.json +1 -0
  114. package/corpus/lenient/lenient-shape-grid-template-no-cols.json +1 -0
  115. package/corpus/lenient/lenient-shape-options-bare-strings.expected.json +1 -0
  116. package/corpus/lenient/lenient-shape-options-bare-strings.json +1 -0
  117. package/corpus/lenient/lenient-shape-params-map.expected.json +1 -0
  118. package/corpus/lenient/lenient-shape-params-map.json +1 -0
  119. package/corpus/lenient/lenient-shape-segmented-orientation-omitted.expected.json +1 -0
  120. package/corpus/lenient/lenient-shape-segmented-orientation-omitted.json +1 -0
  121. package/corpus/lenient/lenient-shape-static-envelope-plain-scalars.expected.json +1 -0
  122. package/corpus/lenient/lenient-shape-static-envelope-plain-scalars.json +1 -0
  123. package/corpus/lenient/lenient-transform-bare-columns.expected.json +1 -0
  124. package/corpus/lenient/lenient-transform-bare-columns.json +1 -0
  125. package/corpus/lenient/lenient-transform-epoch-timestamps.expected.json +1 -0
  126. package/corpus/lenient/lenient-transform-epoch-timestamps.json +1 -0
  127. package/corpus/lenient/lenient-transform-expr-spellings.expected.json +1 -0
  128. package/corpus/lenient/lenient-transform-expr-spellings.json +1 -0
  129. package/corpus/lenient/lenient-transform-flat-contains.expected.json +1 -0
  130. package/corpus/lenient/lenient-transform-flat-contains.json +1 -0
  131. package/corpus/lenient/lenient-transform-flat-filter.expected.json +1 -0
  132. package/corpus/lenient/lenient-transform-flat-filter.json +1 -0
  133. package/corpus/lenient/lenient-transform-flat-or.expected.json +1 -0
  134. package/corpus/lenient/lenient-transform-flat-or.json +1 -0
  135. package/corpus/lenient/lenient-transform-flat-scalar-fn.expected.json +1 -0
  136. package/corpus/lenient/lenient-transform-flat-scalar-fn.json +1 -0
  137. package/corpus/lenient/lenient-transform-schemaless.expected.json +1 -0
  138. package/corpus/lenient/lenient-transform-schemaless.json +1 -0
  139. package/corpus/lenient/lenient-transform-step-aliases.expected.json +1 -0
  140. package/corpus/lenient/lenient-transform-step-aliases.json +1 -0
  141. package/corpus/lenient/lenient-transform-values-only-columns.expected.json +1 -0
  142. package/corpus/lenient/lenient-transform-values-only-columns.json +1 -0
  143. package/corpus/lenient/lenient-window-cumsum-legacy.expected.json +1 -0
  144. package/corpus/lenient/lenient-window-cumsum-legacy.json +1 -0
  145. package/corpus/manifest.json +2000 -0
  146. package/corpus/nodes/badge-1.json +1 -0
  147. package/corpus/nodes/boundary-1.json +1 -0
  148. package/corpus/nodes/btn-1.json +1 -0
  149. package/corpus/nodes/btn-copy-link.json +1 -0
  150. package/corpus/nodes/btn-invoke.json +1 -0
  151. package/corpus/nodes/btn-read-workbook.json +1 -0
  152. package/corpus/nodes/call-into.json +1 -0
  153. package/corpus/nodes/callout-1.json +1 -0
  154. package/corpus/nodes/card-1.json +1 -0
  155. package/corpus/nodes/chart-1.json +1 -0
  156. package/corpus/nodes/code-1.json +1 -0
  157. package/corpus/nodes/composite-root.json +1 -0
  158. package/corpus/nodes/controls-closure.json +1 -0
  159. package/corpus/nodes/controls-declarative.json +1 -0
  160. package/corpus/nodes/custom-1.json +1 -0
  161. package/corpus/nodes/custom-bounded-1.json +1 -0
  162. package/corpus/nodes/custom-bounded-advisory.json +1 -0
  163. package/corpus/nodes/dash-empty.json +1 -0
  164. package/corpus/nodes/discl-1.json +1 -0
  165. package/corpus/nodes/drawing-1.json +1 -0
  166. package/corpus/nodes/drawing-empty.json +1 -0
  167. package/corpus/nodes/fact-1.json +1 -0
  168. package/corpus/nodes/filterable-static-dashboard.json +1 -0
  169. package/corpus/nodes/filters-1.json +1 -0
  170. package/corpus/nodes/filters-declarative.json +1 -0
  171. package/corpus/nodes/filters-segmented.json +1 -0
  172. package/corpus/nodes/form-1.json +1 -0
  173. package/corpus/nodes/form-date.json +1 -0
  174. package/corpus/nodes/form-declarative-minimal.json +1 -0
  175. package/corpus/nodes/form-declarative.json +1 -0
  176. package/corpus/nodes/form-local-1.json +1 -0
  177. package/corpus/nodes/form-local-debounce.json +1 -0
  178. package/corpus/nodes/form-ranged.json +1 -0
  179. package/corpus/nodes/form-segmented.json +1 -0
  180. package/corpus/nodes/format-bindings.json +1 -0
  181. package/corpus/nodes/frag-decl-1.json +1 -0
  182. package/corpus/nodes/frag-decl-param.json +1 -0
  183. package/corpus/nodes/frag-ref-1.json +1 -0
  184. package/corpus/nodes/frag-ref-args.json +1 -0
  185. package/corpus/nodes/glayout-1.json +1 -0
  186. package/corpus/nodes/glayout-tpl-autofit.json +1 -0
  187. package/corpus/nodes/glayout-tpl-fixed.json +1 -0
  188. package/corpus/nodes/glayout-tpl-ratio.json +1 -0
  189. package/corpus/nodes/grid-1.json +1 -0
  190. package/corpus/nodes/grid-field-named.json +1 -0
  191. package/corpus/nodes/grid-transform-param.json +1 -0
  192. package/corpus/nodes/grid-transform.json +1 -0
  193. package/corpus/nodes/heading-1.json +1 -0
  194. package/corpus/nodes/image-1.json +1 -0
  195. package/corpus/nodes/link-1.json +1 -0
  196. package/corpus/nodes/list-1.json +1 -0
  197. package/corpus/nodes/lvr-1.json +1 -0
  198. package/corpus/nodes/map-1.json +1 -0
  199. package/corpus/nodes/markdown-1.json +1 -0
  200. package/corpus/nodes/master-detail-preselected.json +1 -0
  201. package/corpus/nodes/math-1.json +1 -0
  202. package/corpus/nodes/metric-1.json +1 -0
  203. package/corpus/nodes/metric-float-17sig.json +1 -0
  204. package/corpus/nodes/metric-float-bigint.json +1 -0
  205. package/corpus/nodes/metric-float-exp-neg.json +1 -0
  206. package/corpus/nodes/metric-float-exp-pos.json +1 -0
  207. package/corpus/nodes/metric-invoke.json +1 -0
  208. package/corpus/nodes/modal-1.json +1 -0
  209. package/corpus/nodes/mount-1.json +1 -0
  210. package/corpus/nodes/mount-2.json +1 -0
  211. package/corpus/nodes/multiselect-1.json +1 -0
  212. package/corpus/nodes/progress-1.json +1 -0
  213. package/corpus/nodes/query-dependson.json +1 -0
  214. package/corpus/nodes/scalar-transform-composition.json +1 -0
  215. package/corpus/nodes/scroll-1.json +1 -0
  216. package/corpus/nodes/select-1.json +1 -0
  217. package/corpus/nodes/skel-1.json +1 -0
  218. package/corpus/nodes/spark-1.json +1 -0
  219. package/corpus/nodes/split-1.json +1 -0
  220. package/corpus/nodes/stack-1.json +1 -0
  221. package/corpus/nodes/step-1.json +1 -0
  222. package/corpus/nodes/style-role-voice-1.json +1 -0
  223. package/corpus/nodes/summary-1.json +1 -0
  224. package/corpus/nodes/switch-1.json +1 -0
  225. package/corpus/nodes/table-1.json +1 -0
  226. package/corpus/nodes/tabs-1.json +1 -0
  227. package/corpus/nodes/tabs-explicit-1.json +1 -0
  228. package/corpus/nodes/toast-1.json +1 -0
  229. package/corpus/nodes/upload-1.json +1 -0
  230. package/corpus/ops/op-batch.json +1 -0
  231. package/corpus/ops/op-editnode.json +1 -0
  232. package/corpus/ops/op-insertchild.json +1 -0
  233. package/corpus/ops/op-movenode.json +1 -0
  234. package/corpus/ops/op-removenode.json +1 -0
  235. package/corpus/ops/op-reorderchildren.json +1 -0
  236. package/corpus/ops/op-replacebinding.json +1 -0
  237. package/corpus/ops/op-replaceroot.json +1 -0
  238. package/corpus/ops/op-updateprop-nested-badfield.json +1 -0
  239. package/corpus/ops/op-updateprop-nested-badindex.json +1 -0
  240. package/corpus/ops/op-updateprop-nested-column0-label.json +1 -0
  241. package/corpus/ops/op-updateprop-nested-column1-label.json +1 -0
  242. package/corpus/ops/op-updateprop-nested-field0-required.json +1 -0
  243. package/corpus/ops/op-updateprop-nested-field1-required.json +1 -0
  244. package/corpus/ops/op-updateprop-nested-malformed.json +1 -0
  245. package/corpus/ops/op-updateprop-nested-object-value.json +1 -0
  246. package/corpus/ops/op-updateprop-nested-yfield0.json +1 -0
  247. package/corpus/ops/op-updateprop-nested-yfield1.json +1 -0
  248. package/corpus/ops/op-updateprop.json +1 -0
  249. package/corpus/ops/op-updatestate.json +1 -0
  250. package/corpus/ops/op-updatestyle (phase 147 role=eyebrow + voice=structural).json +1 -0
  251. package/corpus/ops/op-updatestyle.json +1 -0
  252. package/corpus/reject/reject-emptynodeid.json +1 -0
  253. package/corpus/reject/reject-invalid-empty.json +0 -0
  254. package/corpus/reject/reject-invalid-garbage.json +1 -0
  255. package/corpus/reject/reject-invalid-truncated.json +1 -0
  256. package/corpus/reject/reject-missing-binding-type.json +1 -0
  257. package/corpus/reject/reject-missing-custom-moduleid.json +1 -0
  258. package/corpus/reject/reject-missing-markdown-text.json +1 -0
  259. package/corpus/reject/reject-missing-metric-value.json +1 -0
  260. package/corpus/reject/reject-missing-mount-scopeid.json +1 -0
  261. package/corpus/reject/reject-missing-node-id.json +1 -0
  262. package/corpus/reject/reject-missing-node-kind.json +1 -0
  263. package/corpus/reject/reject-missing-switch-cases.json +1 -0
  264. package/corpus/reject/reject-missing-switch-default.json +1 -0
  265. package/corpus/reject/reject-missing-switch-statekey.json +1 -0
  266. package/corpus/reject/reject-null-action-aitool-args.json +1 -0
  267. package/corpus/reject/reject-null-action-notify-payload.json +1 -0
  268. package/corpus/reject/reject-null-action-setstate-value.json +1 -0
  269. package/corpus/reject/reject-null-custom-prop.json +1 -0
  270. package/corpus/reject/reject-null-i18n-arg.json +1 -0
  271. package/corpus/reject/reject-null-updateprop-value.json +1 -0
  272. package/corpus/reject/reject-op-insertchild-empty-childid.json +1 -0
  273. package/corpus/reject/reject-op-insertchild-missing-parentid.json +1 -0
  274. package/corpus/reject/reject-op-missing-type.json +1 -0
  275. package/corpus/reject/reject-op-reorderchildren-wrongtype.json +1 -0
  276. package/corpus/reject/reject-op-unknown-yeet.json +1 -0
  277. package/corpus/reject/reject-op-updateprop-missing-path.json +1 -0
  278. package/corpus/reject/reject-unknown-binding.json +1 -0
  279. package/corpus/reject/reject-unknown-drawing-curve-command.json +1 -0
  280. package/corpus/reject/reject-unknown-drawing-shape.json +1 -0
  281. package/corpus/reject/reject-unknown-mount-direction.json +1 -0
  282. package/corpus/reject/reject-unknown-textsource.json +1 -0
  283. package/corpus/reject/reject-unknown-tone.json +1 -0
  284. package/corpus/reject/reject-wrongnodekind-sparkler.json +1 -0
  285. package/corpus/reject/reject-wrongnodekind-widget.json +1 -0
  286. package/corpus/reject/reject-wrongtype-dashboard-children.json +1 -0
  287. package/corpus/reject/reject-wrongtype-discriminator.json +1 -0
  288. package/corpus/reject/reject-wrongtype-heading-level.json +1 -0
  289. package/corpus/reject/reject-wrongtype-id.json +1 -0
  290. package/corpus/reject/reject-wrongtype-kind.json +1 -0
  291. package/corpus/reject/reject-wrongtype-style-tone.json +1 -0
  292. package/corpus/schema.json +4396 -0
  293. package/dist/cli.js +612 -0
  294. package/dist/cli.js.map +1 -0
  295. package/dist/index.cjs +579 -0
  296. package/dist/index.cjs.map +1 -0
  297. package/dist/index.d.cts +159 -0
  298. package/dist/index.d.ts +159 -0
  299. package/dist/index.js +570 -0
  300. package/dist/index.js.map +1 -0
  301. package/package.json +59 -0
@@ -0,0 +1,2000 @@
1
+ {
2
+ "version": 1,
3
+ "schema": "schema.json",
4
+ "description": "Fuaran canonical wire-format conformance corpus. node-round-trip / op-round-trip fixtures: decode inputFile, re-encode, assert byte-equal to expectedFile. reject fixtures: decode inputFile, assert DecodeError.Code = expectedErrorCode and DecodeError.Path starts with expectedPath. lenient-accept fixtures (WIRE_FORMAT 16): decode the SHORTHAND inputFile, re-encode, assert byte-equal to expectedFile (the verbose canonical form) — a conformant host MUST accept the shorthand and normalise it; rejecting it, or decoding it to different bytes, is non-conformant. envelope-round-trip / envelope-reject fixtures (WIRE_FORMAT 15): read the $profile/$payload envelope, negotiate the authored profile against the host's own core@1.0, then either re-render byte-equal to expectedFile (Current/Behind — unknown kinds preserved verbatim, must-ignore-but-preserve) or refuse a Foreign profile with expectedErrorCode FOREIGN_PROFILE at expectedPath. elicitation-round-trip / elicitation-reject fixtures (WIRE_FORMAT 18): decode with the decoder-named entry point (elicitation = the envelope codec, elicitation-outcome = the outcome codec), then either re-encode byte-equal to expectedFile or assert the structured refusal (expectedErrorCode at a path starting with expectedPath). elicitation-answer-accept / elicitation-answer-reject fixtures (WIRE_FORMAT 18.4): the inputFile pairs {answer, contract}; run the host's answer-conformance validation and assert acceptance or the expected refusal. See fuaran/docs/WIRE_FORMAT.md.",
5
+ "kinds": [
6
+ "Badge",
7
+ "Box",
8
+ "Button",
9
+ "Callout",
10
+ "Chart",
11
+ "CodeBlock",
12
+ "Custom",
13
+ "DataGrid",
14
+ "Disclosure",
15
+ "Drawing",
16
+ "ErrorBoundary",
17
+ "Fact",
18
+ "FileUpload",
19
+ "Filters",
20
+ "Form",
21
+ "FragmentDecl",
22
+ "FragmentRef",
23
+ "Heading",
24
+ "Image",
25
+ "LabelValueRow",
26
+ "Link",
27
+ "List",
28
+ "Map",
29
+ "Markdown",
30
+ "Math",
31
+ "Metric",
32
+ "Modal",
33
+ "Mount",
34
+ "Progress",
35
+ "ScrollArea",
36
+ "Select",
37
+ "Skeleton",
38
+ "Sparkline",
39
+ "SplitPanel",
40
+ "Stepper",
41
+ "SummaryList",
42
+ "Switch",
43
+ "Tabs",
44
+ "Toast"
45
+ ],
46
+ "fixtures": [
47
+ {
48
+ "id": "elc-ans-accept-full",
49
+ "kind": "elicitation-answer-accept",
50
+ "decoder": "elicitation-answer",
51
+ "inputFile": "elicitation/elc-ans-accept-full.json",
52
+ "expectedFile": "elicitation/elc-ans-accept-full.json",
53
+ "description": "every declared field, all in-space (WIRE_FORMAT 18.4)"
54
+ },
55
+ {
56
+ "id": "elc-ans-accept-int-for-float",
57
+ "kind": "elicitation-answer-accept",
58
+ "decoder": "elicitation-answer",
59
+ "inputFile": "elicitation/elc-ans-accept-int-for-float.json",
60
+ "expectedFile": "elicitation/elc-ans-accept-int-for-float.json",
61
+ "description": "a whole-valued number satisfies a floatRange — JSON has one number type (WIRE_FORMAT 18.4)"
62
+ },
63
+ {
64
+ "id": "elc-ans-accept-minimal",
65
+ "kind": "elicitation-answer-accept",
66
+ "decoder": "elicitation-answer",
67
+ "inputFile": "elicitation/elc-ans-accept-minimal.json",
68
+ "expectedFile": "elicitation/elc-ans-accept-minimal.json",
69
+ "description": "required fields only — optional fields may be omitted (WIRE_FORMAT 18.4)"
70
+ },
71
+ {
72
+ "id": "elc-ans-reject-enum",
73
+ "kind": "elicitation-answer-reject",
74
+ "decoder": "elicitation-answer",
75
+ "inputFile": "elicitation/elc-ans-reject-enum.json",
76
+ "expectedErrorCode": "ANSWER_OUT_OF_SPACE",
77
+ "expectedPath": "$.answer.size",
78
+ "description": "string outside its enum (WIRE_FORMAT 18.4)"
79
+ },
80
+ {
81
+ "id": "elc-ans-reject-float-range",
82
+ "kind": "elicitation-answer-reject",
83
+ "decoder": "elicitation-answer",
84
+ "inputFile": "elicitation/elc-ans-reject-float-range.json",
85
+ "expectedErrorCode": "ANSWER_OUT_OF_SPACE",
86
+ "expectedPath": "$.answer.score",
87
+ "description": "number outside its floatRange (WIRE_FORMAT 18.4)"
88
+ },
89
+ {
90
+ "id": "elc-ans-reject-int-range",
91
+ "kind": "elicitation-answer-reject",
92
+ "decoder": "elicitation-answer",
93
+ "inputFile": "elicitation/elc-ans-reject-int-range.json",
94
+ "expectedErrorCode": "ANSWER_OUT_OF_SPACE",
95
+ "expectedPath": "$.answer.rating",
96
+ "description": "integer outside its intRange (WIRE_FORMAT 18.4)"
97
+ },
98
+ {
99
+ "id": "elc-ans-reject-missing-required",
100
+ "kind": "elicitation-answer-reject",
101
+ "decoder": "elicitation-answer",
102
+ "inputFile": "elicitation/elc-ans-reject-missing-required.json",
103
+ "expectedErrorCode": "ANSWER_MISSING_FIELD",
104
+ "expectedPath": "$.answer.rating",
105
+ "description": "required answer field absent (WIRE_FORMAT 18.4)"
106
+ },
107
+ {
108
+ "id": "elc-ans-reject-string-len",
109
+ "kind": "elicitation-answer-reject",
110
+ "decoder": "elicitation-answer",
111
+ "inputFile": "elicitation/elc-ans-reject-string-len.json",
112
+ "expectedErrorCode": "ANSWER_OUT_OF_SPACE",
113
+ "expectedPath": "$.answer.bio",
114
+ "description": "string longer than its stringLen bound (WIRE_FORMAT 18.4)"
115
+ },
116
+ {
117
+ "id": "elc-ans-reject-type-mismatch",
118
+ "kind": "elicitation-answer-reject",
119
+ "decoder": "elicitation-answer",
120
+ "inputFile": "elicitation/elc-ans-reject-type-mismatch.json",
121
+ "expectedErrorCode": "ANSWER_TYPE_MISMATCH",
122
+ "expectedPath": "$.answer.rating",
123
+ "description": "string where the space demands an integer (WIRE_FORMAT 18.4)"
124
+ },
125
+ {
126
+ "id": "elc-ans-reject-undeclared",
127
+ "kind": "elicitation-answer-reject",
128
+ "decoder": "elicitation-answer",
129
+ "inputFile": "elicitation/elc-ans-reject-undeclared.json",
130
+ "expectedErrorCode": "ANSWER_UNDECLARED_FIELD",
131
+ "expectedPath": "$.answer.color",
132
+ "description": "undeclared answer key — default-deny by shape (WIRE_FORMAT 18.4)"
133
+ },
134
+ {
135
+ "id": "elc-out-reject-empty-id",
136
+ "kind": "elicitation-reject",
137
+ "decoder": "elicitation-outcome",
138
+ "inputFile": "elicitation/elc-out-reject-empty-id.json",
139
+ "expectedErrorCode": "WRONG_TYPE",
140
+ "expectedPath": "$.elicitationId",
141
+ "description": "outcome with an empty elicitationId (WIRE_FORMAT 18.3)"
142
+ },
143
+ {
144
+ "id": "elc-out-reject-missing-answer",
145
+ "kind": "elicitation-reject",
146
+ "decoder": "elicitation-outcome",
147
+ "inputFile": "elicitation/elc-out-reject-missing-answer.json",
148
+ "expectedErrorCode": "MISSING_FIELD",
149
+ "expectedPath": "$.answer",
150
+ "description": "Answered outcome without an answer object (WIRE_FORMAT 18.3)"
151
+ },
152
+ {
153
+ "id": "elc-out-reject-stray-key",
154
+ "kind": "elicitation-reject",
155
+ "decoder": "elicitation-outcome",
156
+ "inputFile": "elicitation/elc-out-reject-stray-key.json",
157
+ "expectedErrorCode": "UNDECLARED_FIELD",
158
+ "expectedPath": "$.answer",
159
+ "description": "Declined outcome carrying an answer — undeclared key, default-deny (WIRE_FORMAT 18.3)"
160
+ },
161
+ {
162
+ "id": "elc-out-reject-unknown-type",
163
+ "kind": "elicitation-reject",
164
+ "decoder": "elicitation-outcome",
165
+ "inputFile": "elicitation/elc-out-reject-unknown-type.json",
166
+ "expectedErrorCode": "UNKNOWN_DU_CASE",
167
+ "expectedPath": "$.$type",
168
+ "description": "outcome outside the closed set — the outcome DU is total (WIRE_FORMAT 18.3)"
169
+ },
170
+ {
171
+ "id": "elc-reject-bad-space",
172
+ "kind": "elicitation-reject",
173
+ "decoder": "elicitation",
174
+ "inputFile": "elicitation/elc-reject-bad-space.json",
175
+ "expectedErrorCode": "UNKNOWN_DU_CASE",
176
+ "expectedPath": "$.contract.fields[0].space.$type",
177
+ "description": "unknown value-space discriminator (WIRE_FORMAT 18.3)"
178
+ },
179
+ {
180
+ "id": "elc-reject-bad-timeout",
181
+ "kind": "elicitation-reject",
182
+ "decoder": "elicitation",
183
+ "inputFile": "elicitation/elc-reject-bad-timeout.json",
184
+ "expectedErrorCode": "WRONG_TYPE",
185
+ "expectedPath": "$.timeoutMs",
186
+ "description": "timeoutMs below 1 (WIRE_FORMAT 18.3)"
187
+ },
188
+ {
189
+ "id": "elc-reject-bad-version",
190
+ "kind": "elicitation-reject",
191
+ "decoder": "elicitation",
192
+ "inputFile": "elicitation/elc-reject-bad-version.json",
193
+ "expectedErrorCode": "UNSUPPORTED_VERSION",
194
+ "expectedPath": "$.$elicitation",
195
+ "description": "unknown elicitation format version — hard-refuse, never mis-decode (WIRE_FORMAT 18.3)"
196
+ },
197
+ {
198
+ "id": "elc-reject-default-nonconformant",
199
+ "kind": "elicitation-reject",
200
+ "decoder": "elicitation",
201
+ "inputFile": "elicitation/elc-reject-default-nonconformant.json",
202
+ "expectedErrorCode": "DEFAULT_NONCONFORMANT",
203
+ "expectedPath": "$.default.choice",
204
+ "description": "default answer violating the contract (WIRE_FORMAT 18.3)"
205
+ },
206
+ {
207
+ "id": "elc-reject-duplicate-field",
208
+ "kind": "elicitation-reject",
209
+ "decoder": "elicitation",
210
+ "inputFile": "elicitation/elc-reject-duplicate-field.json",
211
+ "expectedErrorCode": "CONTRACT_DUPLICATE_FIELD",
212
+ "expectedPath": "$.contract.fields[1].name",
213
+ "description": "two answer fields sharing a name (WIRE_FORMAT 18.3)"
214
+ },
215
+ {
216
+ "id": "elc-reject-empty-contract",
217
+ "kind": "elicitation-reject",
218
+ "decoder": "elicitation",
219
+ "inputFile": "elicitation/elc-reject-empty-contract.json",
220
+ "expectedErrorCode": "CONTRACT_EMPTY",
221
+ "expectedPath": "$.contract.fields",
222
+ "description": "contract with no fields — an elicitation must declare its answer (WIRE_FORMAT 18.3)"
223
+ },
224
+ {
225
+ "id": "elc-reject-empty-id",
226
+ "kind": "elicitation-reject",
227
+ "decoder": "elicitation",
228
+ "inputFile": "elicitation/elc-reject-empty-id.json",
229
+ "expectedErrorCode": "WRONG_TYPE",
230
+ "expectedPath": "$.id",
231
+ "description": "empty elicitation id (WIRE_FORMAT 18.3)"
232
+ },
233
+ {
234
+ "id": "elc-reject-missing-version",
235
+ "kind": "elicitation-reject",
236
+ "decoder": "elicitation",
237
+ "inputFile": "elicitation/elc-reject-missing-version.json",
238
+ "expectedErrorCode": "MISSING_FIELD",
239
+ "expectedPath": "$.$elicitation",
240
+ "description": "envelope without the $elicitation format tag (WIRE_FORMAT 18.3)"
241
+ },
242
+ {
243
+ "id": "elc-reject-stray-key",
244
+ "kind": "elicitation-reject",
245
+ "decoder": "elicitation",
246
+ "inputFile": "elicitation/elc-reject-stray-key.json",
247
+ "expectedErrorCode": "UNDECLARED_FIELD",
248
+ "expectedPath": "$.note",
249
+ "description": "undeclared envelope key — default-deny by shape (WIRE_FORMAT 18.3)"
250
+ },
251
+ {
252
+ "id": "elc-reject-tree-decode",
253
+ "kind": "elicitation-reject",
254
+ "decoder": "elicitation",
255
+ "inputFile": "elicitation/elc-reject-tree-decode.json",
256
+ "expectedErrorCode": "MISSING_FIELD",
257
+ "expectedPath": "$.tree",
258
+ "description": "embedded tree fails the standard 3.1 node decode — error re-rooted under $.tree (WIRE_FORMAT 18.3)"
259
+ },
260
+ {
261
+ "id": "elc-reject-unknown-node",
262
+ "kind": "elicitation-reject",
263
+ "decoder": "elicitation",
264
+ "inputFile": "elicitation/elc-reject-unknown-node.json",
265
+ "expectedErrorCode": "CONTRACT_UNKNOWN_NODE",
266
+ "expectedPath": "$.contract.fields[0].nodeId",
267
+ "description": "contract field addressing a node absent from the tree (WIRE_FORMAT 18.3)"
268
+ },
269
+ {
270
+ "id": "elc-full",
271
+ "kind": "elicitation-round-trip",
272
+ "decoder": "elicitation",
273
+ "inputFile": "elicitation/elc-full.json",
274
+ "expectedFile": "elicitation/elc-full.json",
275
+ "description": "full envelope — every value-space kind, optional fields, timeoutMs, conforming default (WIRE_FORMAT 18.2)"
276
+ },
277
+ {
278
+ "id": "elc-minimal",
279
+ "kind": "elicitation-round-trip",
280
+ "decoder": "elicitation",
281
+ "inputFile": "elicitation/elc-minimal.json",
282
+ "expectedFile": "elicitation/elc-minimal.json",
283
+ "description": "minimal envelope — one required enum field, no timeout, no default (WIRE_FORMAT 18.2)"
284
+ },
285
+ {
286
+ "id": "elc-out-answered",
287
+ "kind": "elicitation-round-trip",
288
+ "decoder": "elicitation-outcome",
289
+ "inputFile": "elicitation/elc-out-answered.json",
290
+ "expectedFile": "elicitation/elc-out-answered.json",
291
+ "description": "Answered outcome — canonical typed answer object (WIRE_FORMAT 18.3)"
292
+ },
293
+ {
294
+ "id": "elc-out-declined",
295
+ "kind": "elicitation-round-trip",
296
+ "decoder": "elicitation-outcome",
297
+ "inputFile": "elicitation/elc-out-declined.json",
298
+ "expectedFile": "elicitation/elc-out-declined.json",
299
+ "description": "Declined outcome (WIRE_FORMAT 18.3)"
300
+ },
301
+ {
302
+ "id": "elc-out-superseded-anon",
303
+ "kind": "elicitation-round-trip",
304
+ "decoder": "elicitation-outcome",
305
+ "inputFile": "elicitation/elc-out-superseded-anon.json",
306
+ "expectedFile": "elicitation/elc-out-superseded-anon.json",
307
+ "description": "Superseded outcome without a successor id — 'by' is optional (WIRE_FORMAT 18.3)"
308
+ },
309
+ {
310
+ "id": "elc-out-superseded-by",
311
+ "kind": "elicitation-round-trip",
312
+ "decoder": "elicitation-outcome",
313
+ "inputFile": "elicitation/elc-out-superseded-by.json",
314
+ "expectedFile": "elicitation/elc-out-superseded-by.json",
315
+ "description": "Superseded outcome naming its successor (WIRE_FORMAT 18.3)"
316
+ },
317
+ {
318
+ "id": "elc-out-timedout",
319
+ "kind": "elicitation-round-trip",
320
+ "decoder": "elicitation-outcome",
321
+ "inputFile": "elicitation/elc-out-timedout.json",
322
+ "expectedFile": "elicitation/elc-out-timedout.json",
323
+ "description": "TimedOut outcome — dispatched by the HOST's clock; timeoutMs is data (WIRE_FORMAT 18.3)"
324
+ },
325
+ {
326
+ "id": "envelope-foreign-major",
327
+ "kind": "envelope-reject",
328
+ "decoder": "node",
329
+ "inputFile": "envelope/envelope-foreign-major.json",
330
+ "expectedErrorCode": "FOREIGN_PROFILE",
331
+ "expectedPath": "$.$profile",
332
+ "description": "Foreign (major-ahead core@2.0) — hard-refuse, never silently mis-decode (WIRE_FORMAT 15.2)"
333
+ },
334
+ {
335
+ "id": "envelope-foreign-namespace",
336
+ "kind": "envelope-reject",
337
+ "decoder": "node",
338
+ "inputFile": "envelope/envelope-foreign-namespace.json",
339
+ "expectedErrorCode": "FOREIGN_PROFILE",
340
+ "expectedPath": "$.$profile",
341
+ "description": "Foreign (different namespace music@1.0) — hard-refuse (WIRE_FORMAT 15.2)"
342
+ },
343
+ {
344
+ "id": "envelope-known-current",
345
+ "kind": "envelope-round-trip",
346
+ "decoder": "node",
347
+ "inputFile": "envelope/envelope-known-current.json",
348
+ "expectedFile": "envelope/envelope-known-current.json",
349
+ "description": "enveloped Current (core@1.0) known payload — decode + re-render byte-identical (WIRE_FORMAT 15.1)"
350
+ },
351
+ {
352
+ "id": "envelope-unknown-behind",
353
+ "kind": "envelope-round-trip",
354
+ "decoder": "node",
355
+ "inputFile": "envelope/envelope-unknown-behind.json",
356
+ "expectedFile": "envelope/envelope-unknown-behind.json",
357
+ "description": "Behind (core@1.1) unknown-kind payload — tolerant decode preserves bytes verbatim (WIRE_FORMAT 15.3)"
358
+ },
359
+ {
360
+ "id": "envelope-unknown-malformed-required-profile",
361
+ "kind": "envelope-round-trip",
362
+ "decoder": "node",
363
+ "inputFile": "envelope/envelope-unknown-malformed-required-profile.json",
364
+ "expectedFile": "envelope/envelope-unknown-malformed-required-profile.json",
365
+ "description": "Behind unknown kind with a malformed requiredProfile — no label, bytes still preserved (WIRE_FORMAT 15.3)"
366
+ },
367
+ {
368
+ "id": "envelope-unknown-required-profile",
369
+ "kind": "envelope-round-trip",
370
+ "decoder": "node",
371
+ "inputFile": "envelope/envelope-unknown-required-profile.json",
372
+ "expectedFile": "envelope/envelope-unknown-required-profile.json",
373
+ "description": "Behind unknown kind declaring requiredProfile core@1.4 — preserved + degrade label surfaced (WIRE_FORMAT 15.3)"
374
+ },
375
+ {
376
+ "id": "legacy-upgrade-card",
377
+ "kind": "lenient-accept",
378
+ "decoder": "node",
379
+ "inputFile": "lenient/legacy-upgrade-card.json",
380
+ "expectedFile": "lenient/legacy-upgrade-card.expected.json",
381
+ "description": "Legacy `Card` tag decode-upgrades to a Flex/Card Box preserving the heading (Phase 390)"
382
+ },
383
+ {
384
+ "id": "legacy-upgrade-dashboard",
385
+ "kind": "lenient-accept",
386
+ "decoder": "node",
387
+ "inputFile": "lenient/legacy-upgrade-dashboard.json",
388
+ "expectedFile": "lenient/legacy-upgrade-dashboard.expected.json",
389
+ "description": "Legacy `Dashboard` tag decode-upgrades to an Auto/Dashboard Box (Phase 390)"
390
+ },
391
+ {
392
+ "id": "legacy-upgrade-gridlayout",
393
+ "kind": "lenient-accept",
394
+ "decoder": "node",
395
+ "inputFile": "lenient/legacy-upgrade-gridlayout.json",
396
+ "expectedFile": "lenient/legacy-upgrade-gridlayout.expected.json",
397
+ "description": "Legacy `GridLayout` tag decode-upgrades to a Grid/Group Box (Phase 390)"
398
+ },
399
+ {
400
+ "id": "legacy-upgrade-stack",
401
+ "kind": "lenient-accept",
402
+ "decoder": "node",
403
+ "inputFile": "lenient/legacy-upgrade-stack.json",
404
+ "expectedFile": "lenient/legacy-upgrade-stack.expected.json",
405
+ "description": "Legacy `Stack` tag decode-upgrades to a Flex/Group Box (Phase 390)"
406
+ },
407
+ {
408
+ "id": "legacy-upgrade-table",
409
+ "kind": "lenient-accept",
410
+ "decoder": "node",
411
+ "inputFile": "lenient/legacy-upgrade-table.json",
412
+ "expectedFile": "lenient/legacy-upgrade-table.expected.json",
413
+ "description": "Legacy `Table` tag decode-upgrades to a static read-only DataGrid (Phase 393)"
414
+ },
415
+ {
416
+ "id": "lenient-022-lvr-emphasis-loud",
417
+ "kind": "lenient-accept",
418
+ "decoder": "node",
419
+ "inputFile": "lenient/lenient-022-lvr-emphasis-loud.json",
420
+ "expectedFile": "lenient/lenient-022-lvr-emphasis-loud.expected.json",
421
+ "description": "0.2.2 — the Emphasis style-enum string in LabelValueRow's bool slot coerces (Loud→true; Normal/Quiet→false)"
422
+ },
423
+ {
424
+ "id": "lenient-022-lvr-emphasis-normal",
425
+ "kind": "lenient-accept",
426
+ "decoder": "node",
427
+ "inputFile": "lenient/lenient-022-lvr-emphasis-normal.json",
428
+ "expectedFile": "lenient/lenient-022-lvr-emphasis-normal.expected.json",
429
+ "description": "0.2.2 — 'Normal' coerces to false, which is the omitted-when-false canonical form"
430
+ },
431
+ {
432
+ "id": "lenient-460-alias-emphasis-muted",
433
+ "kind": "lenient-accept",
434
+ "decoder": "node",
435
+ "inputFile": "lenient/lenient-460-alias-emphasis-muted.json",
436
+ "expectedFile": "lenient/lenient-460-alias-emphasis-muted.expected.json",
437
+ "description": "Phase 460 — lenient emphasis alias `Muted` canonicalises to `Quiet`"
438
+ },
439
+ {
440
+ "id": "lenient-460-alias-emphasis-strong",
441
+ "kind": "lenient-accept",
442
+ "decoder": "node",
443
+ "inputFile": "lenient/lenient-460-alias-emphasis-strong.json",
444
+ "expectedFile": "lenient/lenient-460-alias-emphasis-strong.expected.json",
445
+ "description": "Phase 460 — lenient emphasis alias `Strong` canonicalises to `Loud`"
446
+ },
447
+ {
448
+ "id": "lenient-460-alias-tone-danger",
449
+ "kind": "lenient-accept",
450
+ "decoder": "node",
451
+ "inputFile": "lenient/lenient-460-alias-tone-danger.json",
452
+ "expectedFile": "lenient/lenient-460-alias-tone-danger.expected.json",
453
+ "description": "Phase 460 — lenient tone alias `Danger` canonicalises to `Critical`"
454
+ },
455
+ {
456
+ "id": "lenient-460-alias-tone-positive",
457
+ "kind": "lenient-accept",
458
+ "decoder": "node",
459
+ "inputFile": "lenient/lenient-460-alias-tone-positive.json",
460
+ "expectedFile": "lenient/lenient-460-alias-tone-positive.expected.json",
461
+ "description": "Phase 460 — lenient tone alias `Positive` canonicalises to `Success`"
462
+ },
463
+ {
464
+ "id": "lenient-460-explicit-default-column",
465
+ "kind": "lenient-accept",
466
+ "decoder": "node",
467
+ "inputFile": "lenient/lenient-460-explicit-default-column.json",
468
+ "expectedFile": "lenient/lenient-460-explicit-default-column.expected.json",
469
+ "description": "Phase 460 — explicit-default column format/width decode and re-encode minimal (read-compat)"
470
+ },
471
+ {
472
+ "id": "lenient-460-explicit-default-metric",
473
+ "kind": "lenient-accept",
474
+ "decoder": "node",
475
+ "inputFile": "lenient/lenient-460-explicit-default-metric.json",
476
+ "expectedFile": "lenient/lenient-460-explicit-default-metric.expected.json",
477
+ "description": "Phase 460 — explicit-default Metric style fields decode and re-encode minimal (read-compat)"
478
+ },
479
+ {
480
+ "id": "lenient-460-explicit-default-style",
481
+ "kind": "lenient-accept",
482
+ "decoder": "node",
483
+ "inputFile": "lenient/lenient-460-explicit-default-style.json",
484
+ "expectedFile": "lenient/lenient-460-explicit-default-style.expected.json",
485
+ "description": "Phase 460 — explicit all-default SemanticStyle re-encodes as an omitted style (read-compat)"
486
+ },
487
+ {
488
+ "id": "lenient-596-form-explicit-auto-state",
489
+ "kind": "lenient-accept",
490
+ "decoder": "node",
491
+ "inputFile": "lenient/lenient-596-form-explicit-auto-state.json",
492
+ "expectedFile": "lenient/lenient-596-form-explicit-auto-state.expected.json",
493
+ "description": "Phase 596 — a form field's explicit auto-shape value (State(field id, placeholder)) normalises to the omitted-value canonical form"
494
+ },
495
+ {
496
+ "id": "lenient-alias-call-url",
497
+ "kind": "lenient-accept",
498
+ "decoder": "node",
499
+ "inputFile": "lenient/lenient-alias-call-url.json",
500
+ "expectedFile": "lenient/lenient-alias-call-url.expected.json",
501
+ "description": "Web-prior alias — Call `url`→`endpoint` (the fetch prior)"
502
+ },
503
+ {
504
+ "id": "lenient-alias-card-title-metric-value",
505
+ "kind": "lenient-accept",
506
+ "decoder": "node",
507
+ "inputFile": "lenient/lenient-alias-card-title-metric-value.json",
508
+ "expectedFile": "lenient/lenient-alias-card-title-metric-value.expected.json",
509
+ "description": "Web-prior aliases — Box `title`→`heading` (the universal card/modal prior), Metric scalar `value` (0.2.0 canonical; the KPI-card prior IS canon now), HeadingVariant/BadgeVariant `Default`→identity case"
510
+ },
511
+ {
512
+ "id": "lenient-alias-datagrid-data-column-type",
513
+ "kind": "lenient-accept",
514
+ "decoder": "node",
515
+ "inputFile": "lenient/lenient-alias-datagrid-data-column-type.json",
516
+ "expectedFile": "lenient/lenient-alias-datagrid-data-column-type.expected.json",
517
+ "description": "Web-prior aliases — DataGrid `data`→`source` (Chart.js/react-table prior), column `type`→`kind` + `header`→`label` (react-table prior)"
518
+ },
519
+ {
520
+ "id": "lenient-alias-form-field-name",
521
+ "kind": "lenient-accept",
522
+ "decoder": "node",
523
+ "inputFile": "lenient/lenient-alias-form-field-name.json",
524
+ "expectedFile": "lenient/lenient-alias-form-field-name.expected.json",
525
+ "description": "Web-prior alias — form field `name`→`id` (the HTML forms prior)"
526
+ },
527
+ {
528
+ "id": "lenient-alias-grid-columns-row",
529
+ "kind": "lenient-accept",
530
+ "decoder": "node",
531
+ "inputFile": "lenient/lenient-alias-grid-columns-row.json",
532
+ "expectedFile": "lenient/lenient-alias-grid-columns-row.expected.json",
533
+ "description": "Web-prior aliases — Grid `columns`→`cols` (CSS/Tailwind prior) + Flex direction `row`→`Horizontal` (CSS flex-direction prior)"
534
+ },
535
+ {
536
+ "id": "lenient-alias-navigate-href",
537
+ "kind": "lenient-accept",
538
+ "decoder": "node",
539
+ "inputFile": "lenient/lenient-alias-navigate-href.json",
540
+ "expectedFile": "lenient/lenient-alias-navigate-href.expected.json",
541
+ "description": "Web-prior aliases — Navigate `href`→`route` (the 2/2 observed Kimi guess) + ButtonVariant `Danger`→`Destructive`"
542
+ },
543
+ {
544
+ "id": "lenient-alias-select-options-query-deps",
545
+ "kind": "lenient-accept",
546
+ "decoder": "node",
547
+ "inputFile": "lenient/lenient-alias-select-options-query-deps.json",
548
+ "expectedFile": "lenient/lenient-alias-select-options-query-deps.expected.json",
549
+ "description": "Web-prior aliases — Select `options`→`source` (the HTML select prior), Query `deps`→`dependsOn` (React hooks prior), State `initialValue`→`defaultValue` (useState prior)"
550
+ },
551
+ {
552
+ "id": "lenient-bare-text-button-label",
553
+ "kind": "lenient-accept",
554
+ "decoder": "node",
555
+ "inputFile": "lenient/lenient-bare-text-button-label.json",
556
+ "expectedFile": "lenient/lenient-bare-text-button-label.expected.json",
557
+ "description": "Button.label as a bare JSON string (§16.1)"
558
+ },
559
+ {
560
+ "id": "lenient-bare-text-callout",
561
+ "kind": "lenient-accept",
562
+ "decoder": "node",
563
+ "inputFile": "lenient/lenient-bare-text-callout.json",
564
+ "expectedFile": "lenient/lenient-bare-text-callout.expected.json",
565
+ "description": "Callout.body (required) + Callout.heading (optional position) as bare strings (§16.1)"
566
+ },
567
+ {
568
+ "id": "lenient-bare-text-heading",
569
+ "kind": "lenient-accept",
570
+ "decoder": "node",
571
+ "inputFile": "lenient/lenient-bare-text-heading.json",
572
+ "expectedFile": "lenient/lenient-bare-text-heading.expected.json",
573
+ "description": "Heading.text as a bare JSON string (§16.1)"
574
+ },
575
+ {
576
+ "id": "lenient-bare-text-markdown",
577
+ "kind": "lenient-accept",
578
+ "decoder": "node",
579
+ "inputFile": "lenient/lenient-bare-text-markdown.json",
580
+ "expectedFile": "lenient/lenient-bare-text-markdown.expected.json",
581
+ "description": "Markdown.text as a bare JSON string (§16.1) — the highest-frequency saving"
582
+ },
583
+ {
584
+ "id": "lenient-binding-bound-wrapper",
585
+ "kind": "lenient-accept",
586
+ "decoder": "node",
587
+ "inputFile": "lenient/lenient-binding-bound-wrapper.json",
588
+ "expectedFile": "lenient/lenient-binding-bound-wrapper.expected.json",
589
+ "description": "pilot-5 n=3 gate — the Bound wrapper unwraps in bare-Binding slots (the TextSource.Bound convention transferred; one payload field, one-to-one); canonical stays the bare binding"
590
+ },
591
+ {
592
+ "id": "lenient-emphasis-cross-vocab",
593
+ "kind": "lenient-accept",
594
+ "decoder": "node",
595
+ "inputFile": "lenient/lenient-emphasis-cross-vocab.json",
596
+ "expectedFile": "lenient/lenient-emphasis-cross-vocab.expected.json",
597
+ "description": "2026-07-19 collision sweep — `emphasis` cross-vocabulary coercion, both directions: the style enum + Phase-460 aliases in the Fact/LabelValueRow BOOL slots (Loud/Strong/Bold ⇒ true, Normal/Quiet/Subtle/Muted ⇒ false) and a bool in the style-enum slot (true ⇒ Loud). One-to-one; the encoder still emits the canonical types."
598
+ },
599
+ {
600
+ "id": "lenient-fact-explicit-defaults",
601
+ "kind": "lenient-accept",
602
+ "decoder": "node",
603
+ "inputFile": "lenient/lenient-fact-explicit-defaults.json",
604
+ "expectedFile": "lenient/lenient-fact-explicit-defaults.expected.json",
605
+ "description": "Fact (the new labeled text-fact kind) — explicit-default `tone`/`emphasis` decode and canonicalise away (omitted-when-default on both boundaries from day one), and the bare-string TextSource shorthand applies to `label`/`value`. The canonical minimal Fact is exactly the two-field form models want to write."
606
+ },
607
+ {
608
+ "id": "lenient-null-static-options",
609
+ "kind": "lenient-accept",
610
+ "decoder": "node",
611
+ "inputFile": "lenient/lenient-null-static-options.json",
612
+ "expectedFile": "lenient/lenient-null-static-options.expected.json",
613
+ "description": "Pre-429 boxes-to-null empty options list decodes to the typed empty array (value None stays null)"
614
+ },
615
+ {
616
+ "id": "lenient-opaque-static-markers",
617
+ "kind": "lenient-accept",
618
+ "decoder": "node",
619
+ "inputFile": "lenient/lenient-opaque-static-markers.json",
620
+ "expectedFile": "lenient/lenient-opaque-static-markers.expected.json",
621
+ "description": "Pre-429 opaque Map markers decode to the typed empty array"
622
+ },
623
+ {
624
+ "id": "lenient-opaque-static-options",
625
+ "kind": "lenient-accept",
626
+ "decoder": "node",
627
+ "inputFile": "lenient/lenient-opaque-static-options.json",
628
+ "expectedFile": "lenient/lenient-opaque-static-options.expected.json",
629
+ "description": "Pre-429 opaque Static options + value decode to the tagged placeholder forms and re-encode typed"
630
+ },
631
+ {
632
+ "id": "lenient-opaque-static-series",
633
+ "kind": "lenient-accept",
634
+ "decoder": "node",
635
+ "inputFile": "lenient/lenient-opaque-static-series.json",
636
+ "expectedFile": "lenient/lenient-opaque-static-series.expected.json",
637
+ "description": "Pre-429 opaque Sparkline series decodes to the typed empty array"
638
+ },
639
+ {
640
+ "id": "lenient-opaque-static-values",
641
+ "kind": "lenient-accept",
642
+ "decoder": "node",
643
+ "inputFile": "lenient/lenient-opaque-static-values.json",
644
+ "expectedFile": "lenient/lenient-opaque-static-values.expected.json",
645
+ "description": "Pre-429 opaque multi-select values decode to the tagged placeholder list and re-encode typed"
646
+ },
647
+ {
648
+ "id": "lenient-shape-binding-scalar-fraction",
649
+ "kind": "lenient-accept",
650
+ "decoder": "node",
651
+ "inputFile": "lenient/lenient-shape-binding-scalar-fraction.json",
652
+ "expectedFile": "lenient/lenient-shape-binding-scalar-fraction.expected.json",
653
+ "description": "Envelope-confusion coercions, BOTH directions (2026-07-17 launch-eval evidence) — a bare scalar where a Binding is expected coerces to `Static` (`fraction: 0.65`), and a Static envelope where a PLAIN value is expected unwraps (`indeterminate: {\"$type\":\"Static\",\"value\":false}`). Unambiguous both ways; `null` and untyped objects stay strict."
654
+ },
655
+ {
656
+ "id": "lenient-shape-grid-no-cols",
657
+ "kind": "lenient-accept",
658
+ "decoder": "node",
659
+ "inputFile": "lenient/lenient-shape-grid-no-cols.json",
660
+ "expectedFile": "lenient/lenient-shape-grid-no-cols.expected.json",
661
+ "description": "Grid with NO column spec (no cols/columns/templateColumns) is the CSS auto-grid prior — accept-and-canonicalise to the language's existing `Auto` responsive auto-tile layout. 35 launch-eval cells across 8 tasks, every provider."
662
+ },
663
+ {
664
+ "id": "lenient-shape-grid-template-no-cols",
665
+ "kind": "lenient-accept",
666
+ "decoder": "node",
667
+ "inputFile": "lenient/lenient-shape-grid-template-no-cols.json",
668
+ "expectedFile": "lenient/lenient-shape-grid-template-no-cols.expected.json",
669
+ "description": "Grid with `templateColumns` but no `cols` — `Cols` is documented-ignored when `templateColumns` is present, so absence defaults to 1 instead of MISSING_FIELD (the 0.1.6 pilot residual). Distinct from the no-column-spec-at-all form, which canonicalises to `Auto`."
670
+ },
671
+ {
672
+ "id": "lenient-shape-options-bare-strings",
673
+ "kind": "lenient-accept",
674
+ "decoder": "node",
675
+ "inputFile": "lenient/lenient-shape-options-bare-strings.json",
676
+ "expectedFile": "lenient/lenient-shape-options-bare-strings.expected.json",
677
+ "description": "Web-prior SHAPE coercions — a bare array where a Binding is expected coerces to `Static` (the omitted-envelope prior, 2/2 observed eval failures), and a bare string option element coerces to `{value: s, label: Literal s}` (the HTML `<select>` prior). The value→label map form (`{\"A\":\"A\"}`) is deliberately NOT coerced: JSON key order is not contractual, so it could silently reorder visible options."
678
+ },
679
+ {
680
+ "id": "lenient-shape-params-map",
681
+ "kind": "lenient-accept",
682
+ "decoder": "node",
683
+ "inputFile": "lenient/lenient-shape-params-map.json",
684
+ "expectedFile": "lenient/lenient-shape-params-map.expected.json",
685
+ "description": "Query-params shape coercion — the name→binding MAP form coerces to the canonical `[{name, from}]` array (params are a name-keyed set, so key order carries no meaning — unlike the options map, which is refused), and `value` aliases `from` at the element. Every provider's first guess in the launch eval; 21/31 failures were repair-proof."
686
+ },
687
+ {
688
+ "id": "lenient-shape-segmented-orientation-omitted",
689
+ "kind": "lenient-accept",
690
+ "decoder": "node",
691
+ "inputFile": "lenient/lenient-shape-segmented-orientation-omitted.json",
692
+ "expectedFile": "lenient/lenient-shape-segmented-orientation-omitted.expected.json",
693
+ "description": "Omitted-when-default (the Phase 460 posture applied to `orientation`) — an absent segmented `orientation` restores the language default `Horizontal` (observed omitted in eval emission data); decode-only, the encoder still always emits it. Combined here with the bare-options shape coercion."
694
+ },
695
+ {
696
+ "id": "lenient-shape-static-envelope-plain-scalars",
697
+ "kind": "lenient-accept",
698
+ "decoder": "node",
699
+ "inputFile": "lenient/lenient-shape-static-envelope-plain-scalars.json",
700
+ "expectedFile": "lenient/lenient-shape-static-envelope-plain-scalars.expected.json",
701
+ "description": "Static-envelope unwrap GENERALISED to every plain-scalar position (2026-07-18 — the 0.1.6 pilot found `emphasis` wrapped after `indeterminate` was fixed site-locally; the confusion is generic). A well-formed envelope at a plain-scalar position has exactly one reading; the encoder still emits bare scalars."
702
+ },
703
+ {
704
+ "id": "lenient-transform-bare-columns",
705
+ "kind": "lenient-accept",
706
+ "decoder": "node",
707
+ "inputFile": "lenient/lenient-transform-bare-columns.json",
708
+ "expectedFile": "lenient/lenient-transform-bare-columns.expected.json",
709
+ "description": "fuaran-core#88 — bare-array columns are the just-the-data shorthand (all-present validity); the wrapped form stays canonical"
710
+ },
711
+ {
712
+ "id": "lenient-transform-epoch-timestamps",
713
+ "kind": "lenient-accept",
714
+ "decoder": "node",
715
+ "inputFile": "lenient/lenient-transform-epoch-timestamps.json",
716
+ "expectedFile": "lenient/lenient-transform-epoch-timestamps.expected.json",
717
+ "description": "fuaran-core#94 — epoch numbers in a declared-timestamp column decode to the canonical ISO instant (seconds, and milliseconds via the whole-float path; unit by magnitude)"
718
+ },
719
+ {
720
+ "id": "lenient-transform-expr-spellings",
721
+ "kind": "lenient-accept",
722
+ "decoder": "node",
723
+ "inputFile": "lenient/lenient-transform-expr-spellings.json",
724
+ "expectedFile": "lenient/lenient-transform-expr-spellings.expected.json",
725
+ "description": "fuaran-core#93 — predicate/contains-as-$type/call spellings (the tier-a-055 shape) coerce to the canonical nested binary"
726
+ },
727
+ {
728
+ "id": "lenient-transform-flat-contains",
729
+ "kind": "lenient-accept",
730
+ "decoder": "node",
731
+ "inputFile": "lenient/lenient-transform-flat-contains.json",
732
+ "expectedFile": "lenient/lenient-transform-flat-contains.expected.json",
733
+ "description": "fuaran-core#90 — the text-search prior: a flat contains step coerces to the canonical nested predicate"
734
+ },
735
+ {
736
+ "id": "lenient-transform-flat-filter",
737
+ "kind": "lenient-accept",
738
+ "decoder": "node",
739
+ "inputFile": "lenient/lenient-transform-flat-filter.json",
740
+ "expectedFile": "lenient/lenient-transform-flat-filter.expected.json",
741
+ "description": "fuaran-core#89 — the flat filter step {column, op, param} coerces to the canonical nested predicate"
742
+ },
743
+ {
744
+ "id": "lenient-transform-flat-or",
745
+ "kind": "lenient-accept",
746
+ "decoder": "node",
747
+ "inputFile": "lenient/lenient-transform-flat-or.json",
748
+ "expectedFile": "lenient/lenient-transform-flat-or.expected.json",
749
+ "description": "fuaran-core#94 — flat variadic `or` (exprs array) + flat `eq` (left/right) left-fold into the canonical nested `binary` tree"
750
+ },
751
+ {
752
+ "id": "lenient-transform-flat-scalar-fn",
753
+ "kind": "lenient-accept",
754
+ "decoder": "node",
755
+ "inputFile": "lenient/lenient-transform-flat-scalar-fn.json",
756
+ "expectedFile": "lenient/lenient-transform-flat-scalar-fn.expected.json",
757
+ "description": "fuaran-core#94 — flat scalar-fn spellings: `fn` aliases `apply` (same fn/args), and a bare fn-name node ({\"$type\":\"lower\",\"expr\":…}) denotes ApplyFn directly; canonical stays `apply`"
758
+ },
759
+ {
760
+ "id": "lenient-transform-schemaless",
761
+ "kind": "lenient-accept",
762
+ "decoder": "node",
763
+ "inputFile": "lenient/lenient-transform-schemaless.json",
764
+ "expectedFile": "lenient/lenient-transform-schemaless.expected.json",
765
+ "description": "fuaran-core#88 — an embedded Transform source may omit schema; column types infer from the cells (int/float/bool/string only)"
766
+ },
767
+ {
768
+ "id": "lenient-transform-step-aliases",
769
+ "kind": "lenient-accept",
770
+ "decoder": "node",
771
+ "inputFile": "lenient/lenient-transform-step-aliases.json",
772
+ "expectedFile": "lenient/lenient-transform-step-aliases.expected.json",
773
+ "description": "fuaran-core#92 — the SQL/pandas step-field spellings (by/aggregations/op/as/avg, keys/column/descending, count) coerce to the canonical fields"
774
+ },
775
+ {
776
+ "id": "lenient-transform-values-only-columns",
777
+ "kind": "lenient-accept",
778
+ "decoder": "node",
779
+ "inputFile": "lenient/lenient-transform-values-only-columns.json",
780
+ "expectedFile": "lenient/lenient-transform-values-only-columns.expected.json",
781
+ "description": "fuaran-core#94 — a values-only column object is the all-present shorthand (the canonical wrapped shape minus the mask); the masked form stays canonical"
782
+ },
783
+ {
784
+ "id": "lenient-window-cumsum-legacy",
785
+ "kind": "lenient-accept",
786
+ "decoder": "node",
787
+ "inputFile": "lenient/lenient-window-cumsum-legacy.json",
788
+ "expectedFile": "lenient/lenient-window-cumsum-legacy.expected.json",
789
+ "description": "2026-07-19 rename — the legacy cumSum window-fn tag coerces to the canonical cumulSum"
790
+ },
791
+ {
792
+ "id": "badge-1",
793
+ "kind": "node-round-trip",
794
+ "decoder": "node",
795
+ "inputFile": "nodes/badge-1.json",
796
+ "expectedFile": "nodes/badge-1.json",
797
+ "description": "Display/Badge"
798
+ },
799
+ {
800
+ "id": "boundary-1",
801
+ "kind": "node-round-trip",
802
+ "decoder": "node",
803
+ "inputFile": "nodes/boundary-1.json",
804
+ "expectedFile": "nodes/boundary-1.json",
805
+ "description": "ErrorBoundary (Markdown child + Callout fallback)"
806
+ },
807
+ {
808
+ "id": "btn-1",
809
+ "kind": "node-round-trip",
810
+ "decoder": "node",
811
+ "inputFile": "nodes/btn-1.json",
812
+ "expectedFile": "nodes/btn-1.json",
813
+ "description": "Input/Button"
814
+ },
815
+ {
816
+ "id": "btn-copy-link",
817
+ "kind": "node-round-trip",
818
+ "decoder": "node",
819
+ "inputFile": "nodes/btn-copy-link.json",
820
+ "expectedFile": "nodes/btn-copy-link.json",
821
+ "description": "Input/Button (Action.WriteToClipboard chained with Dispatch)"
822
+ },
823
+ {
824
+ "id": "btn-invoke",
825
+ "kind": "node-round-trip",
826
+ "decoder": "node",
827
+ "inputFile": "nodes/btn-invoke.json",
828
+ "expectedFile": "nodes/btn-invoke.json",
829
+ "description": "Input/Button (Phase 283 — Action.Invoke capability effect)"
830
+ },
831
+ {
832
+ "id": "btn-read-workbook",
833
+ "kind": "node-round-trip",
834
+ "decoder": "node",
835
+ "inputFile": "nodes/btn-read-workbook.json",
836
+ "expectedFile": "nodes/btn-read-workbook.json",
837
+ "description": "Input/Button (Action.ReadFileBody base64)"
838
+ },
839
+ {
840
+ "id": "call-into",
841
+ "kind": "node-round-trip",
842
+ "decoder": "node",
843
+ "inputFile": "nodes/call-into.json",
844
+ "expectedFile": "nodes/call-into.json",
845
+ "description": "Layout/Stack (Phase 428 — Action.Call result targets: closure / into State / into Query)"
846
+ },
847
+ {
848
+ "id": "callout-1",
849
+ "kind": "node-round-trip",
850
+ "decoder": "node",
851
+ "inputFile": "nodes/callout-1.json",
852
+ "expectedFile": "nodes/callout-1.json",
853
+ "description": "Display/Callout"
854
+ },
855
+ {
856
+ "id": "card-1",
857
+ "kind": "node-round-trip",
858
+ "decoder": "node",
859
+ "inputFile": "nodes/card-1.json",
860
+ "expectedFile": "nodes/card-1.json",
861
+ "description": "Layout/Card"
862
+ },
863
+ {
864
+ "id": "chart-1",
865
+ "kind": "node-round-trip",
866
+ "decoder": "node",
867
+ "inputFile": "nodes/chart-1.json",
868
+ "expectedFile": "nodes/chart-1.json",
869
+ "description": "Visualisation/Chart"
870
+ },
871
+ {
872
+ "id": "code-1",
873
+ "kind": "node-round-trip",
874
+ "decoder": "node",
875
+ "inputFile": "nodes/code-1.json",
876
+ "expectedFile": "nodes/code-1.json",
877
+ "description": "Display/CodeBlock (fsharp, line numbers + highlights)"
878
+ },
879
+ {
880
+ "id": "composite-root",
881
+ "kind": "node-round-trip",
882
+ "decoder": "node",
883
+ "inputFile": "nodes/composite-root.json",
884
+ "expectedFile": "nodes/composite-root.json",
885
+ "description": "Composite (Dashboard ⊃ Card ⊃ Metric + Stack)"
886
+ },
887
+ {
888
+ "id": "controls-closure",
889
+ "kind": "node-round-trip",
890
+ "decoder": "node",
891
+ "inputFile": "nodes/controls-closure.json",
892
+ "expectedFile": "nodes/controls-closure.json",
893
+ "description": "Layout/Stack (Phase 426 — closure-authored onSelectTag / onToggle / onChangeMulti sentinels)"
894
+ },
895
+ {
896
+ "id": "controls-declarative",
897
+ "kind": "node-round-trip",
898
+ "decoder": "node",
899
+ "inputFile": "nodes/controls-declarative.json",
900
+ "expectedFile": "nodes/controls-declarative.json",
901
+ "description": "Layout/Stack (Phase 426 — declarative tabs + modal + disclosure + select, handlers omitted)"
902
+ },
903
+ {
904
+ "id": "custom-1",
905
+ "kind": "node-round-trip",
906
+ "decoder": "node",
907
+ "inputFile": "nodes/custom-1.json",
908
+ "expectedFile": "nodes/custom-1.json",
909
+ "description": "Custom"
910
+ },
911
+ {
912
+ "id": "custom-bounded-1",
913
+ "kind": "node-round-trip",
914
+ "decoder": "node",
915
+ "inputFile": "nodes/custom-bounded-1.json",
916
+ "expectedFile": "nodes/custom-bounded-1.json",
917
+ "description": "Custom (bounded escape, StrictReplay hash + exposed-ids)"
918
+ },
919
+ {
920
+ "id": "custom-bounded-advisory",
921
+ "kind": "node-round-trip",
922
+ "decoder": "node",
923
+ "inputFile": "nodes/custom-bounded-advisory.json",
924
+ "expectedFile": "nodes/custom-bounded-advisory.json",
925
+ "description": "Custom (bounded escape, AdvisoryWarning hash + no exposed-ids)"
926
+ },
927
+ {
928
+ "id": "dash-empty",
929
+ "kind": "node-round-trip",
930
+ "decoder": "node",
931
+ "inputFile": "nodes/dash-empty.json",
932
+ "expectedFile": "nodes/dash-empty.json",
933
+ "description": "Layout/Dashboard (empty)"
934
+ },
935
+ {
936
+ "id": "discl-1",
937
+ "kind": "node-round-trip",
938
+ "decoder": "node",
939
+ "inputFile": "nodes/discl-1.json",
940
+ "expectedFile": "nodes/discl-1.json",
941
+ "description": "Layout/Disclosure"
942
+ },
943
+ {
944
+ "id": "drawing-1",
945
+ "kind": "node-round-trip",
946
+ "decoder": "node",
947
+ "inputFile": "nodes/drawing-1.json",
948
+ "expectedFile": "nodes/drawing-1.json",
949
+ "description": "Display/Drawing (all shapes + curve commands + styled bindings)"
950
+ },
951
+ {
952
+ "id": "drawing-empty",
953
+ "kind": "node-round-trip",
954
+ "decoder": "node",
955
+ "inputFile": "nodes/drawing-empty.json",
956
+ "expectedFile": "nodes/drawing-empty.json",
957
+ "description": "Display/Drawing (degenerate — empty)"
958
+ },
959
+ {
960
+ "id": "fact-1",
961
+ "kind": "node-round-trip",
962
+ "decoder": "node",
963
+ "inputFile": "nodes/fact-1.json",
964
+ "expectedFile": "nodes/fact-1.json",
965
+ "description": "Display/Fact"
966
+ },
967
+ {
968
+ "id": "filterable-static-dashboard",
969
+ "kind": "node-round-trip",
970
+ "decoder": "node",
971
+ "inputFile": "nodes/filterable-static-dashboard.json",
972
+ "expectedFile": "nodes/filterable-static-dashboard.json",
973
+ "description": "Layout/Box (filterable-static dashboard — Filters params wired through Transform to chart + grid)"
974
+ },
975
+ {
976
+ "id": "filters-1",
977
+ "kind": "node-round-trip",
978
+ "decoder": "node",
979
+ "inputFile": "nodes/filters-1.json",
980
+ "expectedFile": "nodes/filters-1.json",
981
+ "description": "Input/Filters (text + choice)"
982
+ },
983
+ {
984
+ "id": "filters-declarative",
985
+ "kind": "node-round-trip",
986
+ "decoder": "node",
987
+ "inputFile": "nodes/filters-declarative.json",
988
+ "expectedFile": "nodes/filters-declarative.json",
989
+ "description": "Input/Filters (declarative — omitted onChange + typed range bounds)"
990
+ },
991
+ {
992
+ "id": "filters-segmented",
993
+ "kind": "node-round-trip",
994
+ "decoder": "node",
995
+ "inputFile": "nodes/filters-segmented.json",
996
+ "expectedFile": "nodes/filters-segmented.json",
997
+ "description": "Input/Filters (SegmentedFilter horizontal)"
998
+ },
999
+ {
1000
+ "id": "form-1",
1001
+ "kind": "node-round-trip",
1002
+ "decoder": "node",
1003
+ "inputFile": "nodes/form-1.json",
1004
+ "expectedFile": "nodes/form-1.json",
1005
+ "description": "Input/Form (all fields)"
1006
+ },
1007
+ {
1008
+ "id": "form-date",
1009
+ "kind": "node-round-trip",
1010
+ "decoder": "node",
1011
+ "inputFile": "nodes/form-date.json",
1012
+ "expectedFile": "nodes/form-date.json",
1013
+ "description": "Input/Form (Date — date/time/datetime variants + bounds)"
1014
+ },
1015
+ {
1016
+ "id": "form-declarative",
1017
+ "kind": "node-round-trip",
1018
+ "decoder": "node",
1019
+ "inputFile": "nodes/form-declarative.json",
1020
+ "expectedFile": "nodes/form-declarative.json",
1021
+ "description": "Input/Form (Phase 426 — handler-free write-back fields, State-bound)"
1022
+ },
1023
+ {
1024
+ "id": "form-declarative-minimal",
1025
+ "kind": "node-round-trip",
1026
+ "decoder": "node",
1027
+ "inputFile": "nodes/form-declarative-minimal.json",
1028
+ "expectedFile": "nodes/form-declarative-minimal.json",
1029
+ "description": "Input/Form (Phase 596 — symmetric auto-bind, omitted-value fields)"
1030
+ },
1031
+ {
1032
+ "id": "form-local-1",
1033
+ "kind": "node-round-trip",
1034
+ "decoder": "node",
1035
+ "inputFile": "nodes/form-local-1.json",
1036
+ "expectedFile": "nodes/form-local-1.json",
1037
+ "description": "Input/Form (Local-bound text, OnBlur)"
1038
+ },
1039
+ {
1040
+ "id": "form-local-debounce",
1041
+ "kind": "node-round-trip",
1042
+ "decoder": "node",
1043
+ "inputFile": "nodes/form-local-debounce.json",
1044
+ "expectedFile": "nodes/form-local-debounce.json",
1045
+ "description": "Input/Form (Local-bound text, OnDebounce 250)"
1046
+ },
1047
+ {
1048
+ "id": "form-ranged",
1049
+ "kind": "node-round-trip",
1050
+ "decoder": "node",
1051
+ "inputFile": "nodes/form-ranged.json",
1052
+ "expectedFile": "nodes/form-ranged.json",
1053
+ "description": "Input/Form (RangedNumber — all/min-only/no bounds)"
1054
+ },
1055
+ {
1056
+ "id": "form-segmented",
1057
+ "kind": "node-round-trip",
1058
+ "decoder": "node",
1059
+ "inputFile": "nodes/form-segmented.json",
1060
+ "expectedFile": "nodes/form-segmented.json",
1061
+ "description": "Input/Form (SegmentedChoice horizontal + vertical)"
1062
+ },
1063
+ {
1064
+ "id": "format-bindings",
1065
+ "kind": "node-round-trip",
1066
+ "decoder": "node",
1067
+ "inputFile": "nodes/format-bindings.json",
1068
+ "expectedFile": "nodes/format-bindings.json",
1069
+ "description": "Binding.Format (number/currency/percent/date/relativeTime across locales)"
1070
+ },
1071
+ {
1072
+ "id": "frag-decl-1",
1073
+ "kind": "node-round-trip",
1074
+ "decoder": "node",
1075
+ "inputFile": "nodes/frag-decl-1.json",
1076
+ "expectedFile": "nodes/frag-decl-1.json",
1077
+ "description": "FragmentDecl (named template with Markdown body)"
1078
+ },
1079
+ {
1080
+ "id": "frag-decl-param",
1081
+ "kind": "node-round-trip",
1082
+ "decoder": "node",
1083
+ "inputFile": "nodes/frag-decl-param.json",
1084
+ "expectedFile": "nodes/frag-decl-param.json",
1085
+ "description": "FragmentDecl (parameterised — value/slot/repeat holes + effect class)"
1086
+ },
1087
+ {
1088
+ "id": "frag-ref-1",
1089
+ "kind": "node-round-trip",
1090
+ "decoder": "node",
1091
+ "inputFile": "nodes/frag-ref-1.json",
1092
+ "expectedFile": "nodes/frag-ref-1.json",
1093
+ "description": "FragmentRef (name-only wire shape)"
1094
+ },
1095
+ {
1096
+ "id": "frag-ref-args",
1097
+ "kind": "node-round-trip",
1098
+ "decoder": "node",
1099
+ "inputFile": "nodes/frag-ref-args.json",
1100
+ "expectedFile": "nodes/frag-ref-args.json",
1101
+ "description": "FragmentRef (parameterised — value + slot args)"
1102
+ },
1103
+ {
1104
+ "id": "glayout-1",
1105
+ "kind": "node-round-trip",
1106
+ "decoder": "node",
1107
+ "inputFile": "nodes/glayout-1.json",
1108
+ "expectedFile": "nodes/glayout-1.json",
1109
+ "description": "Layout/Grid"
1110
+ },
1111
+ {
1112
+ "id": "glayout-tpl-autofit",
1113
+ "kind": "node-round-trip",
1114
+ "decoder": "node",
1115
+ "inputFile": "nodes/glayout-tpl-autofit.json",
1116
+ "expectedFile": "nodes/glayout-tpl-autofit.json",
1117
+ "description": "Layout/Grid (TemplateColumns auto-fit minmax)"
1118
+ },
1119
+ {
1120
+ "id": "glayout-tpl-fixed",
1121
+ "kind": "node-round-trip",
1122
+ "decoder": "node",
1123
+ "inputFile": "nodes/glayout-tpl-fixed.json",
1124
+ "expectedFile": "nodes/glayout-tpl-fixed.json",
1125
+ "description": "Layout/Grid (TemplateColumns 100px + repeat fixed-plus-flex)"
1126
+ },
1127
+ {
1128
+ "id": "glayout-tpl-ratio",
1129
+ "kind": "node-round-trip",
1130
+ "decoder": "node",
1131
+ "inputFile": "nodes/glayout-tpl-ratio.json",
1132
+ "expectedFile": "nodes/glayout-tpl-ratio.json",
1133
+ "description": "Layout/Grid (TemplateColumns 1fr 2fr ratio)"
1134
+ },
1135
+ {
1136
+ "id": "grid-1",
1137
+ "kind": "node-round-trip",
1138
+ "decoder": "node",
1139
+ "inputFile": "nodes/grid-1.json",
1140
+ "expectedFile": "nodes/grid-1.json",
1141
+ "description": "Visualisation/Grid"
1142
+ },
1143
+ {
1144
+ "id": "grid-field-named",
1145
+ "kind": "node-round-trip",
1146
+ "decoder": "node",
1147
+ "inputFile": "nodes/grid-field-named.json",
1148
+ "expectedFile": "nodes/grid-field-named.json",
1149
+ "description": "Visualisation/Grid (Phase 425 — field-named columns + RowKeyField, closure-free)"
1150
+ },
1151
+ {
1152
+ "id": "grid-transform",
1153
+ "kind": "node-round-trip",
1154
+ "decoder": "node",
1155
+ "inputFile": "nodes/grid-transform.json",
1156
+ "expectedFile": "nodes/grid-transform.json",
1157
+ "description": "Visualisation/Grid (Phase 282 — Binding.Transform compute source)"
1158
+ },
1159
+ {
1160
+ "id": "grid-transform-param",
1161
+ "kind": "node-round-trip",
1162
+ "decoder": "node",
1163
+ "inputFile": "nodes/grid-transform-param.json",
1164
+ "expectedFile": "nodes/grid-transform-param.json",
1165
+ "description": "Visualisation/Grid (Phase 424 — parameterised Binding.Transform, filter param from a chip)"
1166
+ },
1167
+ {
1168
+ "id": "heading-1",
1169
+ "kind": "node-round-trip",
1170
+ "decoder": "node",
1171
+ "inputFile": "nodes/heading-1.json",
1172
+ "expectedFile": "nodes/heading-1.json",
1173
+ "description": "Display/Heading"
1174
+ },
1175
+ {
1176
+ "id": "image-1",
1177
+ "kind": "node-round-trip",
1178
+ "decoder": "node",
1179
+ "inputFile": "nodes/image-1.json",
1180
+ "expectedFile": "nodes/image-1.json",
1181
+ "description": "Display/Image (Avatar variant)"
1182
+ },
1183
+ {
1184
+ "id": "link-1",
1185
+ "kind": "node-round-trip",
1186
+ "decoder": "node",
1187
+ "inputFile": "nodes/link-1.json",
1188
+ "expectedFile": "nodes/link-1.json",
1189
+ "description": "Display/Link"
1190
+ },
1191
+ {
1192
+ "id": "list-1",
1193
+ "kind": "node-round-trip",
1194
+ "decoder": "node",
1195
+ "inputFile": "nodes/list-1.json",
1196
+ "expectedFile": "nodes/list-1.json",
1197
+ "description": "Display/List (ordered)"
1198
+ },
1199
+ {
1200
+ "id": "lvr-1",
1201
+ "kind": "node-round-trip",
1202
+ "decoder": "node",
1203
+ "inputFile": "nodes/lvr-1.json",
1204
+ "expectedFile": "nodes/lvr-1.json",
1205
+ "description": "Display/LabelValueRow"
1206
+ },
1207
+ {
1208
+ "id": "map-1",
1209
+ "kind": "node-round-trip",
1210
+ "decoder": "node",
1211
+ "inputFile": "nodes/map-1.json",
1212
+ "expectedFile": "nodes/map-1.json",
1213
+ "description": "Visualisation/Map"
1214
+ },
1215
+ {
1216
+ "id": "markdown-1",
1217
+ "kind": "node-round-trip",
1218
+ "decoder": "node",
1219
+ "inputFile": "nodes/markdown-1.json",
1220
+ "expectedFile": "nodes/markdown-1.json",
1221
+ "description": "Display/Markdown"
1222
+ },
1223
+ {
1224
+ "id": "master-detail-preselected",
1225
+ "kind": "node-round-trip",
1226
+ "decoder": "node",
1227
+ "inputFile": "nodes/master-detail-preselected.json",
1228
+ "expectedFile": "nodes/master-detail-preselected.json",
1229
+ "description": "Layout/Box (master-detail — grid + detail card State-bound with a pre-selected defaultValue)"
1230
+ },
1231
+ {
1232
+ "id": "math-1",
1233
+ "kind": "node-round-trip",
1234
+ "decoder": "node",
1235
+ "inputFile": "nodes/math-1.json",
1236
+ "expectedFile": "nodes/math-1.json",
1237
+ "description": "Display/Math (block LaTeX)"
1238
+ },
1239
+ {
1240
+ "id": "metric-1",
1241
+ "kind": "node-round-trip",
1242
+ "decoder": "node",
1243
+ "inputFile": "nodes/metric-1.json",
1244
+ "expectedFile": "nodes/metric-1.json",
1245
+ "description": "Display/Metric"
1246
+ },
1247
+ {
1248
+ "id": "metric-float-17sig",
1249
+ "kind": "node-round-trip",
1250
+ "decoder": "node",
1251
+ "inputFile": "nodes/metric-float-17sig.json",
1252
+ "expectedFile": "nodes/metric-float-17sig.json",
1253
+ "description": "Display/Metric (float divergence-zone — 17 significant digits)"
1254
+ },
1255
+ {
1256
+ "id": "metric-float-bigint",
1257
+ "kind": "node-round-trip",
1258
+ "decoder": "node",
1259
+ "inputFile": "nodes/metric-float-bigint.json",
1260
+ "expectedFile": "nodes/metric-float-bigint.json",
1261
+ "description": "Display/Metric (float divergence-zone — integer > 2^53)"
1262
+ },
1263
+ {
1264
+ "id": "metric-float-exp-neg",
1265
+ "kind": "node-round-trip",
1266
+ "decoder": "node",
1267
+ "inputFile": "nodes/metric-float-exp-neg.json",
1268
+ "expectedFile": "nodes/metric-float-exp-neg.json",
1269
+ "description": "Display/Metric (float divergence-zone — 1e-7 scientific)"
1270
+ },
1271
+ {
1272
+ "id": "metric-float-exp-pos",
1273
+ "kind": "node-round-trip",
1274
+ "decoder": "node",
1275
+ "inputFile": "nodes/metric-float-exp-pos.json",
1276
+ "expectedFile": "nodes/metric-float-exp-pos.json",
1277
+ "description": "Display/Metric (float divergence-zone — 1e21 scientific)"
1278
+ },
1279
+ {
1280
+ "id": "metric-invoke",
1281
+ "kind": "node-round-trip",
1282
+ "decoder": "node",
1283
+ "inputFile": "nodes/metric-invoke.json",
1284
+ "expectedFile": "nodes/metric-invoke.json",
1285
+ "description": "Display/Metric (Phase 283 — Binding.Invoke capability source)"
1286
+ },
1287
+ {
1288
+ "id": "modal-1",
1289
+ "kind": "node-round-trip",
1290
+ "decoder": "node",
1291
+ "inputFile": "nodes/modal-1.json",
1292
+ "expectedFile": "nodes/modal-1.json",
1293
+ "description": "Layout/Modal (heading + child + onDismiss)"
1294
+ },
1295
+ {
1296
+ "id": "mount-1",
1297
+ "kind": "node-round-trip",
1298
+ "decoder": "node",
1299
+ "inputFile": "nodes/mount-1.json",
1300
+ "expectedFile": "nodes/mount-1.json",
1301
+ "description": "Mount (§4o — out-only, default-deny, zero-input degenerate)"
1302
+ },
1303
+ {
1304
+ "id": "mount-2",
1305
+ "kind": "node-round-trip",
1306
+ "decoder": "node",
1307
+ "inputFile": "nodes/mount-2.json",
1308
+ "expectedFile": "nodes/mount-2.json",
1309
+ "description": "Mount (§4o — capabilities + TwoWay message shape + value/slot inputs)"
1310
+ },
1311
+ {
1312
+ "id": "multiselect-1",
1313
+ "kind": "node-round-trip",
1314
+ "decoder": "node",
1315
+ "inputFile": "nodes/multiselect-1.json",
1316
+ "expectedFile": "nodes/multiselect-1.json",
1317
+ "description": "Input/Select (multi-select — list value)"
1318
+ },
1319
+ {
1320
+ "id": "progress-1",
1321
+ "kind": "node-round-trip",
1322
+ "decoder": "node",
1323
+ "inputFile": "nodes/progress-1.json",
1324
+ "expectedFile": "nodes/progress-1.json",
1325
+ "description": "Display/Progress"
1326
+ },
1327
+ {
1328
+ "id": "query-dependson",
1329
+ "kind": "node-round-trip",
1330
+ "decoder": "node",
1331
+ "inputFile": "nodes/query-dependson.json",
1332
+ "expectedFile": "nodes/query-dependson.json",
1333
+ "description": "Display/Metric (Phase 421 — Binding.Query with a declared dependsOn filter edge)"
1334
+ },
1335
+ {
1336
+ "id": "scalar-transform-composition",
1337
+ "kind": "node-round-trip",
1338
+ "decoder": "node",
1339
+ "inputFile": "nodes/scalar-transform-composition.json",
1340
+ "expectedFile": "nodes/scalar-transform-composition.json",
1341
+ "description": "Layout/Box (Phase 632 — Transform in scalar slots: selected-row Callout body + Badge count)"
1342
+ },
1343
+ {
1344
+ "id": "scroll-1",
1345
+ "kind": "node-round-trip",
1346
+ "decoder": "node",
1347
+ "inputFile": "nodes/scroll-1.json",
1348
+ "expectedFile": "nodes/scroll-1.json",
1349
+ "description": "Layout/ScrollArea (vertical, maxHeight)"
1350
+ },
1351
+ {
1352
+ "id": "select-1",
1353
+ "kind": "node-round-trip",
1354
+ "decoder": "node",
1355
+ "inputFile": "nodes/select-1.json",
1356
+ "expectedFile": "nodes/select-1.json",
1357
+ "description": "Input/Select"
1358
+ },
1359
+ {
1360
+ "id": "skel-1",
1361
+ "kind": "node-round-trip",
1362
+ "decoder": "node",
1363
+ "inputFile": "nodes/skel-1.json",
1364
+ "expectedFile": "nodes/skel-1.json",
1365
+ "description": "Display/Skeleton"
1366
+ },
1367
+ {
1368
+ "id": "spark-1",
1369
+ "kind": "node-round-trip",
1370
+ "decoder": "node",
1371
+ "inputFile": "nodes/spark-1.json",
1372
+ "expectedFile": "nodes/spark-1.json",
1373
+ "description": "Display/Sparkline"
1374
+ },
1375
+ {
1376
+ "id": "split-1",
1377
+ "kind": "node-round-trip",
1378
+ "decoder": "node",
1379
+ "inputFile": "nodes/split-1.json",
1380
+ "expectedFile": "nodes/split-1.json",
1381
+ "description": "Layout/SplitPanel"
1382
+ },
1383
+ {
1384
+ "id": "stack-1",
1385
+ "kind": "node-round-trip",
1386
+ "decoder": "node",
1387
+ "inputFile": "nodes/stack-1.json",
1388
+ "expectedFile": "nodes/stack-1.json",
1389
+ "description": "Layout/Stack"
1390
+ },
1391
+ {
1392
+ "id": "step-1",
1393
+ "kind": "node-round-trip",
1394
+ "decoder": "node",
1395
+ "inputFile": "nodes/step-1.json",
1396
+ "expectedFile": "nodes/step-1.json",
1397
+ "description": "Layout/Stepper"
1398
+ },
1399
+ {
1400
+ "id": "style-role-voice-1",
1401
+ "kind": "node-round-trip",
1402
+ "decoder": "node",
1403
+ "inputFile": "nodes/style-role-voice-1.json",
1404
+ "expectedFile": "nodes/style-role-voice-1.json",
1405
+ "description": "Display/Markdown (Phase 147 Role=Data + Voice=Display)"
1406
+ },
1407
+ {
1408
+ "id": "summary-1",
1409
+ "kind": "node-round-trip",
1410
+ "decoder": "node",
1411
+ "inputFile": "nodes/summary-1.json",
1412
+ "expectedFile": "nodes/summary-1.json",
1413
+ "description": "Layout/SummaryList"
1414
+ },
1415
+ {
1416
+ "id": "switch-1",
1417
+ "kind": "node-round-trip",
1418
+ "decoder": "node",
1419
+ "inputFile": "nodes/switch-1.json",
1420
+ "expectedFile": "nodes/switch-1.json",
1421
+ "description": "Switch (view state → details/summary cases + info default)"
1422
+ },
1423
+ {
1424
+ "id": "table-1",
1425
+ "kind": "node-round-trip",
1426
+ "decoder": "node",
1427
+ "inputFile": "nodes/table-1.json",
1428
+ "expectedFile": "nodes/table-1.json",
1429
+ "description": "Visualisation/Table"
1430
+ },
1431
+ {
1432
+ "id": "tabs-1",
1433
+ "kind": "node-round-trip",
1434
+ "decoder": "node",
1435
+ "inputFile": "nodes/tabs-1.json",
1436
+ "expectedFile": "nodes/tabs-1.json",
1437
+ "description": "Layout/Tabs"
1438
+ },
1439
+ {
1440
+ "id": "tabs-explicit-1",
1441
+ "kind": "node-round-trip",
1442
+ "decoder": "node",
1443
+ "inputFile": "nodes/tabs-explicit-1.json",
1444
+ "expectedFile": "nodes/tabs-explicit-1.json",
1445
+ "description": "Layout/Tabs (explicit headers + tags + activeTag)"
1446
+ },
1447
+ {
1448
+ "id": "toast-1",
1449
+ "kind": "node-round-trip",
1450
+ "decoder": "node",
1451
+ "inputFile": "nodes/toast-1.json",
1452
+ "expectedFile": "nodes/toast-1.json",
1453
+ "description": "Display/Toast (Success tone, open)"
1454
+ },
1455
+ {
1456
+ "id": "upload-1",
1457
+ "kind": "node-round-trip",
1458
+ "decoder": "node",
1459
+ "inputFile": "nodes/upload-1.json",
1460
+ "expectedFile": "nodes/upload-1.json",
1461
+ "description": "Input/FileUpload"
1462
+ },
1463
+ {
1464
+ "id": "op-batch",
1465
+ "kind": "op-round-trip",
1466
+ "decoder": "op",
1467
+ "inputFile": "ops/op-batch.json",
1468
+ "expectedFile": "ops/op-batch.json",
1469
+ "description": "Batch"
1470
+ },
1471
+ {
1472
+ "id": "op-editnode",
1473
+ "kind": "op-round-trip",
1474
+ "decoder": "op",
1475
+ "inputFile": "ops/op-editnode.json",
1476
+ "expectedFile": "ops/op-editnode.json",
1477
+ "description": "EditNode"
1478
+ },
1479
+ {
1480
+ "id": "op-insertchild",
1481
+ "kind": "op-round-trip",
1482
+ "decoder": "op",
1483
+ "inputFile": "ops/op-insertchild.json",
1484
+ "expectedFile": "ops/op-insertchild.json",
1485
+ "description": "InsertChild"
1486
+ },
1487
+ {
1488
+ "id": "op-movenode",
1489
+ "kind": "op-round-trip",
1490
+ "decoder": "op",
1491
+ "inputFile": "ops/op-movenode.json",
1492
+ "expectedFile": "ops/op-movenode.json",
1493
+ "description": "MoveNode"
1494
+ },
1495
+ {
1496
+ "id": "op-removenode",
1497
+ "kind": "op-round-trip",
1498
+ "decoder": "op",
1499
+ "inputFile": "ops/op-removenode.json",
1500
+ "expectedFile": "ops/op-removenode.json",
1501
+ "description": "RemoveNode"
1502
+ },
1503
+ {
1504
+ "id": "op-reorderchildren",
1505
+ "kind": "op-round-trip",
1506
+ "decoder": "op",
1507
+ "inputFile": "ops/op-reorderchildren.json",
1508
+ "expectedFile": "ops/op-reorderchildren.json",
1509
+ "description": "ReorderChildren"
1510
+ },
1511
+ {
1512
+ "id": "op-replacebinding",
1513
+ "kind": "op-round-trip",
1514
+ "decoder": "op",
1515
+ "inputFile": "ops/op-replacebinding.json",
1516
+ "expectedFile": "ops/op-replacebinding.json",
1517
+ "description": "ReplaceBinding"
1518
+ },
1519
+ {
1520
+ "id": "op-replaceroot",
1521
+ "kind": "op-round-trip",
1522
+ "decoder": "op",
1523
+ "inputFile": "ops/op-replaceroot.json",
1524
+ "expectedFile": "ops/op-replaceroot.json",
1525
+ "description": "ReplaceRoot"
1526
+ },
1527
+ {
1528
+ "id": "op-updateprop",
1529
+ "kind": "op-round-trip",
1530
+ "decoder": "op",
1531
+ "inputFile": "ops/op-updateprop.json",
1532
+ "expectedFile": "ops/op-updateprop.json",
1533
+ "description": "UpdateProp"
1534
+ },
1535
+ {
1536
+ "id": "op-updateprop-nested-badfield",
1537
+ "kind": "op-round-trip",
1538
+ "decoder": "op",
1539
+ "inputFile": "ops/op-updateprop-nested-badfield.json",
1540
+ "expectedFile": "ops/op-updateprop-nested-badfield.json",
1541
+ "description": "UpdateProp-nested-badfield"
1542
+ },
1543
+ {
1544
+ "id": "op-updateprop-nested-badindex",
1545
+ "kind": "op-round-trip",
1546
+ "decoder": "op",
1547
+ "inputFile": "ops/op-updateprop-nested-badindex.json",
1548
+ "expectedFile": "ops/op-updateprop-nested-badindex.json",
1549
+ "description": "UpdateProp-nested-badindex"
1550
+ },
1551
+ {
1552
+ "id": "op-updateprop-nested-column0-label",
1553
+ "kind": "op-round-trip",
1554
+ "decoder": "op",
1555
+ "inputFile": "ops/op-updateprop-nested-column0-label.json",
1556
+ "expectedFile": "ops/op-updateprop-nested-column0-label.json",
1557
+ "description": "UpdateProp-nested-column0-label"
1558
+ },
1559
+ {
1560
+ "id": "op-updateprop-nested-column1-label",
1561
+ "kind": "op-round-trip",
1562
+ "decoder": "op",
1563
+ "inputFile": "ops/op-updateprop-nested-column1-label.json",
1564
+ "expectedFile": "ops/op-updateprop-nested-column1-label.json",
1565
+ "description": "UpdateProp-nested-column1-label"
1566
+ },
1567
+ {
1568
+ "id": "op-updateprop-nested-field0-required",
1569
+ "kind": "op-round-trip",
1570
+ "decoder": "op",
1571
+ "inputFile": "ops/op-updateprop-nested-field0-required.json",
1572
+ "expectedFile": "ops/op-updateprop-nested-field0-required.json",
1573
+ "description": "UpdateProp-nested-field0-required"
1574
+ },
1575
+ {
1576
+ "id": "op-updateprop-nested-field1-required",
1577
+ "kind": "op-round-trip",
1578
+ "decoder": "op",
1579
+ "inputFile": "ops/op-updateprop-nested-field1-required.json",
1580
+ "expectedFile": "ops/op-updateprop-nested-field1-required.json",
1581
+ "description": "UpdateProp-nested-field1-required"
1582
+ },
1583
+ {
1584
+ "id": "op-updateprop-nested-malformed",
1585
+ "kind": "op-round-trip",
1586
+ "decoder": "op",
1587
+ "inputFile": "ops/op-updateprop-nested-malformed.json",
1588
+ "expectedFile": "ops/op-updateprop-nested-malformed.json",
1589
+ "description": "UpdateProp-nested-malformed"
1590
+ },
1591
+ {
1592
+ "id": "op-updateprop-nested-object-value",
1593
+ "kind": "op-round-trip",
1594
+ "decoder": "op",
1595
+ "inputFile": "ops/op-updateprop-nested-object-value.json",
1596
+ "expectedFile": "ops/op-updateprop-nested-object-value.json",
1597
+ "description": "UpdateProp-nested-object-value"
1598
+ },
1599
+ {
1600
+ "id": "op-updateprop-nested-yfield0",
1601
+ "kind": "op-round-trip",
1602
+ "decoder": "op",
1603
+ "inputFile": "ops/op-updateprop-nested-yfield0.json",
1604
+ "expectedFile": "ops/op-updateprop-nested-yfield0.json",
1605
+ "description": "UpdateProp-nested-yfield0"
1606
+ },
1607
+ {
1608
+ "id": "op-updateprop-nested-yfield1",
1609
+ "kind": "op-round-trip",
1610
+ "decoder": "op",
1611
+ "inputFile": "ops/op-updateprop-nested-yfield1.json",
1612
+ "expectedFile": "ops/op-updateprop-nested-yfield1.json",
1613
+ "description": "UpdateProp-nested-yfield1"
1614
+ },
1615
+ {
1616
+ "id": "op-updatestate",
1617
+ "kind": "op-round-trip",
1618
+ "decoder": "op",
1619
+ "inputFile": "ops/op-updatestate.json",
1620
+ "expectedFile": "ops/op-updatestate.json",
1621
+ "description": "UpdateState"
1622
+ },
1623
+ {
1624
+ "id": "op-updatestyle",
1625
+ "kind": "op-round-trip",
1626
+ "decoder": "op",
1627
+ "inputFile": "ops/op-updatestyle.json",
1628
+ "expectedFile": "ops/op-updatestyle.json",
1629
+ "description": "UpdateStyle"
1630
+ },
1631
+ {
1632
+ "id": "op-updatestyle (phase 147 role=eyebrow + voice=structural)",
1633
+ "kind": "op-round-trip",
1634
+ "decoder": "op",
1635
+ "inputFile": "ops/op-updatestyle (phase 147 role=eyebrow + voice=structural).json",
1636
+ "expectedFile": "ops/op-updatestyle (phase 147 role=eyebrow + voice=structural).json",
1637
+ "description": "UpdateStyle (Phase 147 Role=Eyebrow + Voice=Structural)"
1638
+ },
1639
+ {
1640
+ "id": "reject-emptynodeid",
1641
+ "kind": "reject",
1642
+ "decoder": "node",
1643
+ "inputFile": "reject/reject-emptynodeid.json",
1644
+ "expectedErrorCode": "EMPTY_NODE_ID",
1645
+ "expectedPath": "$.id",
1646
+ "description": "Empty top-level id"
1647
+ },
1648
+ {
1649
+ "id": "reject-invalid-empty",
1650
+ "kind": "reject",
1651
+ "decoder": "node",
1652
+ "inputFile": "reject/reject-invalid-empty.json",
1653
+ "expectedErrorCode": "INVALID_JSON",
1654
+ "expectedPath": "$",
1655
+ "description": "empty string"
1656
+ },
1657
+ {
1658
+ "id": "reject-invalid-garbage",
1659
+ "kind": "reject",
1660
+ "decoder": "node",
1661
+ "inputFile": "reject/reject-invalid-garbage.json",
1662
+ "expectedErrorCode": "INVALID_JSON",
1663
+ "expectedPath": "$",
1664
+ "description": "garbage input"
1665
+ },
1666
+ {
1667
+ "id": "reject-invalid-truncated",
1668
+ "kind": "reject",
1669
+ "decoder": "node",
1670
+ "inputFile": "reject/reject-invalid-truncated.json",
1671
+ "expectedErrorCode": "INVALID_JSON",
1672
+ "expectedPath": "$",
1673
+ "description": "truncated object"
1674
+ },
1675
+ {
1676
+ "id": "reject-missing-binding-type",
1677
+ "kind": "reject",
1678
+ "decoder": "node",
1679
+ "inputFile": "reject/reject-missing-binding-type.json",
1680
+ "expectedErrorCode": "MISSING_FIELD",
1681
+ "expectedPath": "$.kind.value.$type",
1682
+ "description": "Binding missing $type"
1683
+ },
1684
+ {
1685
+ "id": "reject-missing-custom-moduleid",
1686
+ "kind": "reject",
1687
+ "decoder": "node",
1688
+ "inputFile": "reject/reject-missing-custom-moduleid.json",
1689
+ "expectedErrorCode": "MISSING_FIELD",
1690
+ "expectedPath": "$.kind.moduleId",
1691
+ "description": "Custom missing moduleId"
1692
+ },
1693
+ {
1694
+ "id": "reject-missing-markdown-text",
1695
+ "kind": "reject",
1696
+ "decoder": "node",
1697
+ "inputFile": "reject/reject-missing-markdown-text.json",
1698
+ "expectedErrorCode": "MISSING_FIELD",
1699
+ "expectedPath": "$.kind.text",
1700
+ "description": "Markdown spec missing text"
1701
+ },
1702
+ {
1703
+ "id": "reject-missing-metric-value",
1704
+ "kind": "reject",
1705
+ "decoder": "node",
1706
+ "inputFile": "reject/reject-missing-metric-value.json",
1707
+ "expectedErrorCode": "MISSING_FIELD",
1708
+ "expectedPath": "$.kind.value",
1709
+ "description": "Metric spec missing value"
1710
+ },
1711
+ {
1712
+ "id": "reject-missing-mount-scopeid",
1713
+ "kind": "reject",
1714
+ "decoder": "node",
1715
+ "inputFile": "reject/reject-missing-mount-scopeid.json",
1716
+ "expectedErrorCode": "MISSING_FIELD",
1717
+ "expectedPath": "$.kind.scopeId",
1718
+ "description": "Mount missing scopeId (§4o)"
1719
+ },
1720
+ {
1721
+ "id": "reject-missing-node-id",
1722
+ "kind": "reject",
1723
+ "decoder": "node",
1724
+ "inputFile": "reject/reject-missing-node-id.json",
1725
+ "expectedErrorCode": "MISSING_FIELD",
1726
+ "expectedPath": "$.id",
1727
+ "description": "Node missing id"
1728
+ },
1729
+ {
1730
+ "id": "reject-missing-node-kind",
1731
+ "kind": "reject",
1732
+ "decoder": "node",
1733
+ "inputFile": "reject/reject-missing-node-kind.json",
1734
+ "expectedErrorCode": "MISSING_FIELD",
1735
+ "expectedPath": "$.kind",
1736
+ "description": "Node missing kind"
1737
+ },
1738
+ {
1739
+ "id": "reject-missing-switch-cases",
1740
+ "kind": "reject",
1741
+ "decoder": "node",
1742
+ "inputFile": "reject/reject-missing-switch-cases.json",
1743
+ "expectedErrorCode": "MISSING_FIELD",
1744
+ "expectedPath": "$.kind.cases",
1745
+ "description": "Switch missing cases"
1746
+ },
1747
+ {
1748
+ "id": "reject-missing-switch-default",
1749
+ "kind": "reject",
1750
+ "decoder": "node",
1751
+ "inputFile": "reject/reject-missing-switch-default.json",
1752
+ "expectedErrorCode": "MISSING_FIELD",
1753
+ "expectedPath": "$.kind.default",
1754
+ "description": "Switch missing default Node"
1755
+ },
1756
+ {
1757
+ "id": "reject-missing-switch-statekey",
1758
+ "kind": "reject",
1759
+ "decoder": "node",
1760
+ "inputFile": "reject/reject-missing-switch-statekey.json",
1761
+ "expectedErrorCode": "MISSING_FIELD",
1762
+ "expectedPath": "$.kind.stateKey",
1763
+ "description": "Switch missing stateKey"
1764
+ },
1765
+ {
1766
+ "id": "reject-null-action-aitool-args",
1767
+ "kind": "reject",
1768
+ "decoder": "node",
1769
+ "inputFile": "reject/reject-null-action-aitool-args.json",
1770
+ "expectedErrorCode": "WRONG_TYPE",
1771
+ "expectedPath": "$.kind.onClick.args",
1772
+ "description": "null Action.AiTool args (structured JVal position)"
1773
+ },
1774
+ {
1775
+ "id": "reject-null-action-notify-payload",
1776
+ "kind": "reject",
1777
+ "decoder": "node",
1778
+ "inputFile": "reject/reject-null-action-notify-payload.json",
1779
+ "expectedErrorCode": "WRONG_TYPE",
1780
+ "expectedPath": "$.kind.onClick.payload",
1781
+ "description": "null Action.Notify payload (structured JVal position)"
1782
+ },
1783
+ {
1784
+ "id": "reject-null-action-setstate-value",
1785
+ "kind": "reject",
1786
+ "decoder": "node",
1787
+ "inputFile": "reject/reject-null-action-setstate-value.json",
1788
+ "expectedErrorCode": "WRONG_TYPE",
1789
+ "expectedPath": "$.kind.onClick.value",
1790
+ "description": "null Action.SetState value (structured JVal position)"
1791
+ },
1792
+ {
1793
+ "id": "reject-null-custom-prop",
1794
+ "kind": "reject",
1795
+ "decoder": "node",
1796
+ "inputFile": "reject/reject-null-custom-prop.json",
1797
+ "expectedErrorCode": "WRONG_TYPE",
1798
+ "expectedPath": "$.kind.props.k",
1799
+ "description": "null Custom prop value (structured JVal position)"
1800
+ },
1801
+ {
1802
+ "id": "reject-null-i18n-arg",
1803
+ "kind": "reject",
1804
+ "decoder": "node",
1805
+ "inputFile": "reject/reject-null-i18n-arg.json",
1806
+ "expectedErrorCode": "WRONG_TYPE",
1807
+ "expectedPath": "$.kind.text.args.name",
1808
+ "description": "null I18n arg value (structured JVal position)"
1809
+ },
1810
+ {
1811
+ "id": "reject-null-updateprop-value",
1812
+ "kind": "reject",
1813
+ "decoder": "op",
1814
+ "inputFile": "reject/reject-null-updateprop-value.json",
1815
+ "expectedErrorCode": "WRONG_TYPE",
1816
+ "expectedPath": "$.value",
1817
+ "description": "null UpdateProp value (structured JVal position)"
1818
+ },
1819
+ {
1820
+ "id": "reject-op-insertchild-empty-childid",
1821
+ "kind": "reject",
1822
+ "decoder": "op",
1823
+ "inputFile": "reject/reject-op-insertchild-empty-childid.json",
1824
+ "expectedErrorCode": "EMPTY_NODE_ID",
1825
+ "expectedPath": "$.child.id",
1826
+ "description": "InsertChild child carries empty id"
1827
+ },
1828
+ {
1829
+ "id": "reject-op-insertchild-missing-parentid",
1830
+ "kind": "reject",
1831
+ "decoder": "op",
1832
+ "inputFile": "reject/reject-op-insertchild-missing-parentid.json",
1833
+ "expectedErrorCode": "MISSING_FIELD",
1834
+ "expectedPath": "$.parentId",
1835
+ "description": "InsertChild missing parentId"
1836
+ },
1837
+ {
1838
+ "id": "reject-op-missing-type",
1839
+ "kind": "reject",
1840
+ "decoder": "op",
1841
+ "inputFile": "reject/reject-op-missing-type.json",
1842
+ "expectedErrorCode": "MISSING_FIELD",
1843
+ "expectedPath": "$.$type",
1844
+ "description": "Op missing $type entirely"
1845
+ },
1846
+ {
1847
+ "id": "reject-op-reorderchildren-wrongtype",
1848
+ "kind": "reject",
1849
+ "decoder": "op",
1850
+ "inputFile": "reject/reject-op-reorderchildren-wrongtype.json",
1851
+ "expectedErrorCode": "WRONG_TYPE",
1852
+ "expectedPath": "$.newOrder",
1853
+ "description": "ReorderChildren newOrder is string not array"
1854
+ },
1855
+ {
1856
+ "id": "reject-op-unknown-yeet",
1857
+ "kind": "reject",
1858
+ "decoder": "op",
1859
+ "inputFile": "reject/reject-op-unknown-yeet.json",
1860
+ "expectedErrorCode": "UNKNOWN_DU_CASE",
1861
+ "expectedPath": "$.$type",
1862
+ "description": "Unknown op discriminator 'Yeet'"
1863
+ },
1864
+ {
1865
+ "id": "reject-op-updateprop-missing-path",
1866
+ "kind": "reject",
1867
+ "decoder": "op",
1868
+ "inputFile": "reject/reject-op-updateprop-missing-path.json",
1869
+ "expectedErrorCode": "MISSING_FIELD",
1870
+ "expectedPath": "$.path",
1871
+ "description": "UpdateProp missing path"
1872
+ },
1873
+ {
1874
+ "id": "reject-unknown-binding",
1875
+ "kind": "reject",
1876
+ "decoder": "node",
1877
+ "inputFile": "reject/reject-unknown-binding.json",
1878
+ "expectedErrorCode": "UNKNOWN_DU_CASE",
1879
+ "expectedPath": "$.kind.value.$type",
1880
+ "description": "Binding $type 'Bogus'"
1881
+ },
1882
+ {
1883
+ "id": "reject-unknown-drawing-curve-command",
1884
+ "kind": "reject",
1885
+ "decoder": "node",
1886
+ "inputFile": "reject/reject-unknown-drawing-curve-command.json",
1887
+ "expectedErrorCode": "UNKNOWN_DU_CASE",
1888
+ "expectedPath": "$.kind.shapes[0].commands[0].$type",
1889
+ "description": "Drawing CurveCommand $type 'ArcTo' — typed command list default-deny (Phase 524)"
1890
+ },
1891
+ {
1892
+ "id": "reject-unknown-drawing-shape",
1893
+ "kind": "reject",
1894
+ "decoder": "node",
1895
+ "inputFile": "reject/reject-unknown-drawing-shape.json",
1896
+ "expectedErrorCode": "UNKNOWN_DU_CASE",
1897
+ "expectedPath": "$.kind.shapes[0].$type",
1898
+ "description": "Drawing Shape $type 'Blob' — the closed-shape default-deny (Phase 524)"
1899
+ },
1900
+ {
1901
+ "id": "reject-unknown-mount-direction",
1902
+ "kind": "reject",
1903
+ "decoder": "node",
1904
+ "inputFile": "reject/reject-unknown-mount-direction.json",
1905
+ "expectedErrorCode": "UNKNOWN_DU_CASE",
1906
+ "expectedPath": "$.kind.channel.direction",
1907
+ "description": "Mount ChannelDirection value 'Sideways' (§4o)"
1908
+ },
1909
+ {
1910
+ "id": "reject-unknown-textsource",
1911
+ "kind": "reject",
1912
+ "decoder": "node",
1913
+ "inputFile": "reject/reject-unknown-textsource.json",
1914
+ "expectedErrorCode": "UNKNOWN_DU_CASE",
1915
+ "expectedPath": "$.kind.text.$type",
1916
+ "description": "TextSource $type 'TemplateString'"
1917
+ },
1918
+ {
1919
+ "id": "reject-unknown-tone",
1920
+ "kind": "reject",
1921
+ "decoder": "node",
1922
+ "inputFile": "reject/reject-unknown-tone.json",
1923
+ "expectedErrorCode": "UNKNOWN_DU_CASE",
1924
+ "expectedPath": "$.style.tone",
1925
+ "description": "ToneVariant value 'Magenta'"
1926
+ },
1927
+ {
1928
+ "id": "reject-wrongnodekind-sparkler",
1929
+ "kind": "reject",
1930
+ "decoder": "node",
1931
+ "inputFile": "reject/reject-wrongnodekind-sparkler.json",
1932
+ "expectedErrorCode": "WRONG_NODE_KIND",
1933
+ "expectedPath": "$.kind.$type",
1934
+ "description": "Plausible-but-invalid kind 'Sparkler' — on the flat wire an unknown primitive is WRONG_NODE_KIND, not a nested DisplayKind miss"
1935
+ },
1936
+ {
1937
+ "id": "reject-wrongnodekind-widget",
1938
+ "kind": "reject",
1939
+ "decoder": "node",
1940
+ "inputFile": "reject/reject-wrongnodekind-widget.json",
1941
+ "expectedErrorCode": "WRONG_NODE_KIND",
1942
+ "expectedPath": "$.kind.$type",
1943
+ "description": "Top-level kind 'Widget' is not a recognised node kind"
1944
+ },
1945
+ {
1946
+ "id": "reject-wrongtype-dashboard-children",
1947
+ "kind": "reject",
1948
+ "decoder": "node",
1949
+ "inputFile": "reject/reject-wrongtype-dashboard-children.json",
1950
+ "expectedErrorCode": "WRONG_TYPE",
1951
+ "expectedPath": "$.kind.children",
1952
+ "description": "Dashboard children is object not array"
1953
+ },
1954
+ {
1955
+ "id": "reject-wrongtype-discriminator",
1956
+ "kind": "reject",
1957
+ "decoder": "node",
1958
+ "inputFile": "reject/reject-wrongtype-discriminator.json",
1959
+ "expectedErrorCode": "WRONG_TYPE",
1960
+ "expectedPath": "$.kind.text.$type",
1961
+ "description": "Discriminator under Style is number"
1962
+ },
1963
+ {
1964
+ "id": "reject-wrongtype-heading-level",
1965
+ "kind": "reject",
1966
+ "decoder": "node",
1967
+ "inputFile": "reject/reject-wrongtype-heading-level.json",
1968
+ "expectedErrorCode": "WRONG_TYPE",
1969
+ "expectedPath": "$.kind.level",
1970
+ "description": "Heading level is string not number"
1971
+ },
1972
+ {
1973
+ "id": "reject-wrongtype-id",
1974
+ "kind": "reject",
1975
+ "decoder": "node",
1976
+ "inputFile": "reject/reject-wrongtype-id.json",
1977
+ "expectedErrorCode": "WRONG_TYPE",
1978
+ "expectedPath": "$.id",
1979
+ "description": "Node id is integer not string"
1980
+ },
1981
+ {
1982
+ "id": "reject-wrongtype-kind",
1983
+ "kind": "reject",
1984
+ "decoder": "node",
1985
+ "inputFile": "reject/reject-wrongtype-kind.json",
1986
+ "expectedErrorCode": "WRONG_TYPE",
1987
+ "expectedPath": "$.kind",
1988
+ "description": "Node kind is a bare string not an object"
1989
+ },
1990
+ {
1991
+ "id": "reject-wrongtype-style-tone",
1992
+ "kind": "reject",
1993
+ "decoder": "node",
1994
+ "inputFile": "reject/reject-wrongtype-style-tone.json",
1995
+ "expectedErrorCode": "WRONG_TYPE",
1996
+ "expectedPath": "$.style.tone",
1997
+ "description": "Style.tone is integer not string"
1998
+ }
1999
+ ]
2000
+ }