fuaran-py 0.0.1__tar.gz

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 (602) hide show
  1. fuaran_py-0.0.1/.gitattributes +31 -0
  2. fuaran_py-0.0.1/.github/workflows/ci.yml +150 -0
  3. fuaran_py-0.0.1/.github/workflows/publish-pypi.yml +64 -0
  4. fuaran_py-0.0.1/.gitignore +32 -0
  5. fuaran_py-0.0.1/CLAUDE.md +307 -0
  6. fuaran_py-0.0.1/CODE_OF_CONDUCT.md +77 -0
  7. fuaran_py-0.0.1/CONTRIBUTING.md +32 -0
  8. fuaran_py-0.0.1/LICENSE +215 -0
  9. fuaran_py-0.0.1/NOTICE +16 -0
  10. fuaran_py-0.0.1/PKG-INFO +508 -0
  11. fuaran_py-0.0.1/README.md +483 -0
  12. fuaran_py-0.0.1/SECURITY.md +29 -0
  13. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-ans-accept-full.json +1 -0
  14. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-ans-accept-int-for-float.json +1 -0
  15. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-ans-accept-minimal.json +1 -0
  16. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-ans-reject-enum.json +1 -0
  17. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-ans-reject-float-range.json +1 -0
  18. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-ans-reject-int-range.json +1 -0
  19. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-ans-reject-missing-required.json +1 -0
  20. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-ans-reject-string-len.json +1 -0
  21. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-ans-reject-type-mismatch.json +1 -0
  22. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-ans-reject-undeclared.json +1 -0
  23. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-full.json +1 -0
  24. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-minimal.json +1 -0
  25. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-out-answered.json +1 -0
  26. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-out-declined.json +1 -0
  27. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-out-reject-empty-id.json +1 -0
  28. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-out-reject-missing-answer.json +1 -0
  29. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-out-reject-stray-key.json +1 -0
  30. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-out-reject-unknown-type.json +1 -0
  31. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-out-superseded-anon.json +1 -0
  32. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-out-superseded-by.json +1 -0
  33. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-out-timedout.json +1 -0
  34. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-reject-bad-space.json +1 -0
  35. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-reject-bad-timeout.json +1 -0
  36. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-reject-bad-version.json +1 -0
  37. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-reject-default-nonconformant.json +1 -0
  38. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-reject-duplicate-field.json +1 -0
  39. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-reject-empty-contract.json +1 -0
  40. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-reject-empty-id.json +1 -0
  41. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-reject-missing-version.json +1 -0
  42. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-reject-stray-key.json +1 -0
  43. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-reject-tree-decode.json +1 -0
  44. fuaran_py-0.0.1/conformance/corpus/elicitation/elc-reject-unknown-node.json +1 -0
  45. fuaran_py-0.0.1/conformance/corpus/envelope/envelope-foreign-major.json +1 -0
  46. fuaran_py-0.0.1/conformance/corpus/envelope/envelope-foreign-namespace.json +1 -0
  47. fuaran_py-0.0.1/conformance/corpus/envelope/envelope-known-current.json +1 -0
  48. fuaran_py-0.0.1/conformance/corpus/envelope/envelope-unknown-behind.json +1 -0
  49. fuaran_py-0.0.1/conformance/corpus/envelope/envelope-unknown-malformed-required-profile.json +1 -0
  50. fuaran_py-0.0.1/conformance/corpus/envelope/envelope-unknown-required-profile.json +1 -0
  51. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-022-lvr-emphasis-loud.expected.json +1 -0
  52. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-022-lvr-emphasis-loud.json +1 -0
  53. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-022-lvr-emphasis-normal.expected.json +1 -0
  54. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-022-lvr-emphasis-normal.json +1 -0
  55. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-alias-emphasis-muted.expected.json +1 -0
  56. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-alias-emphasis-muted.json +1 -0
  57. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-alias-emphasis-strong.expected.json +1 -0
  58. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-alias-emphasis-strong.json +1 -0
  59. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-alias-tone-danger.expected.json +1 -0
  60. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-alias-tone-danger.json +1 -0
  61. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-alias-tone-positive.expected.json +1 -0
  62. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-alias-tone-positive.json +1 -0
  63. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-explicit-default-column.expected.json +1 -0
  64. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-explicit-default-column.json +1 -0
  65. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-explicit-default-metric.expected.json +1 -0
  66. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-explicit-default-metric.json +1 -0
  67. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-explicit-default-style.expected.json +1 -0
  68. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-460-explicit-default-style.json +1 -0
  69. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-596-form-explicit-auto-state.expected.json +1 -0
  70. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-596-form-explicit-auto-state.json +1 -0
  71. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-665-rows-opaque-sentinel.expected.json +1 -0
  72. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-665-rows-opaque-sentinel.json +1 -0
  73. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-call-url.expected.json +1 -0
  74. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-call-url.json +1 -0
  75. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-card-title-metric-value.expected.json +1 -0
  76. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-card-title-metric-value.json +1 -0
  77. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-datagrid-data-column-type.expected.json +1 -0
  78. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-datagrid-data-column-type.json +1 -0
  79. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-form-field-name.expected.json +1 -0
  80. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-form-field-name.json +1 -0
  81. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-grid-columns-row.expected.json +1 -0
  82. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-grid-columns-row.json +1 -0
  83. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-navigate-href.expected.json +1 -0
  84. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-navigate-href.json +1 -0
  85. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-select-options-query-deps.expected.json +1 -0
  86. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-alias-select-options-query-deps.json +1 -0
  87. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-bare-text-button-label.expected.json +1 -0
  88. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-bare-text-button-label.json +1 -0
  89. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-bare-text-callout.expected.json +1 -0
  90. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-bare-text-callout.json +1 -0
  91. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-bare-text-heading.expected.json +1 -0
  92. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-bare-text-heading.json +1 -0
  93. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-bare-text-markdown.expected.json +1 -0
  94. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-bare-text-markdown.json +1 -0
  95. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-binding-bound-wrapper.expected.json +1 -0
  96. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-binding-bound-wrapper.json +1 -0
  97. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-daterange-bare-array.expected.json +1 -0
  98. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-daterange-bare-array.json +1 -0
  99. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-daterange-static-envelope.expected.json +1 -0
  100. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-daterange-static-envelope.json +1 -0
  101. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-emphasis-cross-vocab.expected.json +1 -0
  102. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-emphasis-cross-vocab.json +1 -0
  103. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-fact-explicit-defaults.expected.json +1 -0
  104. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-fact-explicit-defaults.json +1 -0
  105. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-filterable-static-dashboard-compact.expected.json +1 -0
  106. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-filterable-static-dashboard-compact.json +1 -0
  107. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-grid-field-named-compact.expected.json +1 -0
  108. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-grid-field-named-compact.json +1 -0
  109. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-grid-transform-param-compact.expected.json +1 -0
  110. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-grid-transform-param-compact.json +1 -0
  111. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-image-caption-envelope.expected.json +1 -0
  112. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-image-caption-envelope.json +1 -0
  113. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-image-empty-srcset.expected.json +1 -0
  114. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-image-empty-srcset.json +1 -0
  115. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-image-explicit-defaults.expected.json +1 -0
  116. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-image-explicit-defaults.json +1 -0
  117. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-image-explicit-expandable-false.expected.json +1 -0
  118. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-image-explicit-expandable-false.json +1 -0
  119. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-master-detail-preselected-compact.expected.json +1 -0
  120. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-master-detail-preselected-compact.json +1 -0
  121. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-null-static-options.expected.json +1 -0
  122. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-null-static-options.json +1 -0
  123. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-opaque-static-markers.expected.json +1 -0
  124. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-opaque-static-markers.json +1 -0
  125. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-opaque-static-options.expected.json +1 -0
  126. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-opaque-static-options.json +1 -0
  127. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-opaque-static-series.expected.json +1 -0
  128. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-opaque-static-series.json +1 -0
  129. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-opaque-static-values.expected.json +1 -0
  130. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-opaque-static-values.json +1 -0
  131. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-scalar-transform-composition-compact.expected.json +1 -0
  132. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-scalar-transform-composition-compact.json +1 -0
  133. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-a11y-label-bare-scalar.expected.json +1 -0
  134. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-a11y-label-bare-scalar.json +1 -0
  135. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-binding-scalar-fraction.expected.json +1 -0
  136. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-binding-scalar-fraction.json +1 -0
  137. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-grid-no-cols.expected.json +1 -0
  138. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-grid-no-cols.json +1 -0
  139. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-grid-template-no-cols.expected.json +1 -0
  140. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-grid-template-no-cols.json +1 -0
  141. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-options-bare-strings.expected.json +1 -0
  142. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-options-bare-strings.json +1 -0
  143. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-params-map.expected.json +1 -0
  144. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-params-map.json +1 -0
  145. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-segmented-orientation-omitted.expected.json +1 -0
  146. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-segmented-orientation-omitted.json +1 -0
  147. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-static-envelope-plain-scalars.expected.json +1 -0
  148. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-shape-static-envelope-plain-scalars.json +1 -0
  149. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-tonedpill-pill-tag.expected.json +1 -0
  150. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-tonedpill-pill-tag.json +1 -0
  151. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-tonedpill-tone-aliases.expected.json +1 -0
  152. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-tonedpill-tone-aliases.json +1 -0
  153. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-tonedpill-tonemap-alias.expected.json +1 -0
  154. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-tonedpill-tonemap-alias.json +1 -0
  155. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-bare-columns.expected.json +1 -0
  156. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-bare-columns.json +1 -0
  157. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-epoch-timestamps.expected.json +1 -0
  158. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-epoch-timestamps.json +1 -0
  159. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-expr-spellings.expected.json +1 -0
  160. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-expr-spellings.json +1 -0
  161. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-flat-contains.expected.json +1 -0
  162. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-flat-contains.json +1 -0
  163. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-flat-filter.expected.json +1 -0
  164. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-flat-filter.json +1 -0
  165. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-flat-or.expected.json +1 -0
  166. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-flat-or.json +1 -0
  167. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-flat-scalar-fn.expected.json +1 -0
  168. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-flat-scalar-fn.json +1 -0
  169. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-schemaless.expected.json +1 -0
  170. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-schemaless.json +1 -0
  171. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-source-rowmajor.expected.json +1 -0
  172. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-source-rowmajor.json +1 -0
  173. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-source-state-rows.expected.json +1 -0
  174. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-source-state-rows.json +1 -0
  175. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-step-aliases.expected.json +1 -0
  176. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-step-aliases.json +1 -0
  177. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-values-only-columns.expected.json +1 -0
  178. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-transform-values-only-columns.json +1 -0
  179. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-window-cumsum-legacy.expected.json +1 -0
  180. fuaran_py-0.0.1/conformance/corpus/lenient/lenient-window-cumsum-legacy.json +1 -0
  181. fuaran_py-0.0.1/conformance/corpus/manifest.json +3253 -0
  182. fuaran_py-0.0.1/conformance/corpus/nodes/a11y-alert-assertive.json +1 -0
  183. fuaran_py-0.0.1/conformance/corpus/nodes/a11y-button-named.json +1 -0
  184. fuaran_py-0.0.1/conformance/corpus/nodes/a11y-image-decorative.json +1 -0
  185. fuaran_py-0.0.1/conformance/corpus/nodes/a11y-link-labelled.json +1 -0
  186. fuaran_py-0.0.1/conformance/corpus/nodes/a11y-wrapper-all-slots.json +1 -0
  187. fuaran_py-0.0.1/conformance/corpus/nodes/a11y-wrapper-state-bound.json +1 -0
  188. fuaran_py-0.0.1/conformance/corpus/nodes/badge-1.json +1 -0
  189. fuaran_py-0.0.1/conformance/corpus/nodes/badge-transform-live.json +1 -0
  190. fuaran_py-0.0.1/conformance/corpus/nodes/boundary-1.json +1 -0
  191. fuaran_py-0.0.1/conformance/corpus/nodes/btn-1.json +1 -0
  192. fuaran_py-0.0.1/conformance/corpus/nodes/btn-copy-link.json +1 -0
  193. fuaran_py-0.0.1/conformance/corpus/nodes/btn-invoke.json +1 -0
  194. fuaran_py-0.0.1/conformance/corpus/nodes/btn-json-payloads.json +1 -0
  195. fuaran_py-0.0.1/conformance/corpus/nodes/btn-read-workbook.json +1 -0
  196. fuaran_py-0.0.1/conformance/corpus/nodes/button-setstate-valuefrom.json +1 -0
  197. fuaran_py-0.0.1/conformance/corpus/nodes/call-into.json +1 -0
  198. fuaran_py-0.0.1/conformance/corpus/nodes/callout-1.json +1 -0
  199. fuaran_py-0.0.1/conformance/corpus/nodes/card-1.json +1 -0
  200. fuaran_py-0.0.1/conformance/corpus/nodes/chart-1.json +1 -0
  201. fuaran_py-0.0.1/conformance/corpus/nodes/chart-axis-titles.json +1 -0
  202. fuaran_py-0.0.1/conformance/corpus/nodes/chart-data-labels.json +1 -0
  203. fuaran_py-0.0.1/conformance/corpus/nodes/chart-legend-position.json +1 -0
  204. fuaran_py-0.0.1/conformance/corpus/nodes/chart-state-rows.json +1 -0
  205. fuaran_py-0.0.1/conformance/corpus/nodes/chart-temporal-x.json +1 -0
  206. fuaran_py-0.0.1/conformance/corpus/nodes/chart-value-format.json +1 -0
  207. fuaran_py-0.0.1/conformance/corpus/nodes/code-1.json +1 -0
  208. fuaran_py-0.0.1/conformance/corpus/nodes/composite-root.json +1 -0
  209. fuaran_py-0.0.1/conformance/corpus/nodes/composite-tabs-panels.json +1 -0
  210. fuaran_py-0.0.1/conformance/corpus/nodes/controls-closure.json +1 -0
  211. fuaran_py-0.0.1/conformance/corpus/nodes/controls-declarative.json +1 -0
  212. fuaran_py-0.0.1/conformance/corpus/nodes/custom-1.json +1 -0
  213. fuaran_py-0.0.1/conformance/corpus/nodes/custom-bounded-1.json +1 -0
  214. fuaran_py-0.0.1/conformance/corpus/nodes/custom-bounded-advisory.json +1 -0
  215. fuaran_py-0.0.1/conformance/corpus/nodes/dash-empty.json +1 -0
  216. fuaran_py-0.0.1/conformance/corpus/nodes/discl-1.json +1 -0
  217. fuaran_py-0.0.1/conformance/corpus/nodes/drawing-1.json +1 -0
  218. fuaran_py-0.0.1/conformance/corpus/nodes/drawing-empty.json +1 -0
  219. fuaran_py-0.0.1/conformance/corpus/nodes/drawing-nonfinite-sentinels.json +1 -0
  220. fuaran_py-0.0.1/conformance/corpus/nodes/drawing-rotated-labels.json +1 -0
  221. fuaran_py-0.0.1/conformance/corpus/nodes/drawing-tipped-shapes.json +1 -0
  222. fuaran_py-0.0.1/conformance/corpus/nodes/empty-state-card.json +1 -0
  223. fuaran_py-0.0.1/conformance/corpus/nodes/fact-1.json +1 -0
  224. fuaran_py-0.0.1/conformance/corpus/nodes/filterable-static-dashboard.json +1 -0
  225. fuaran_py-0.0.1/conformance/corpus/nodes/filters-1.json +1 -0
  226. fuaran_py-0.0.1/conformance/corpus/nodes/filters-date-range.json +1 -0
  227. fuaran_py-0.0.1/conformance/corpus/nodes/filters-declarative.json +1 -0
  228. fuaran_py-0.0.1/conformance/corpus/nodes/filters-segmented.json +1 -0
  229. fuaran_py-0.0.1/conformance/corpus/nodes/form-1.json +1 -0
  230. fuaran_py-0.0.1/conformance/corpus/nodes/form-date-range.json +1 -0
  231. fuaran_py-0.0.1/conformance/corpus/nodes/form-date.json +1 -0
  232. fuaran_py-0.0.1/conformance/corpus/nodes/form-declarative-minimal.json +1 -0
  233. fuaran_py-0.0.1/conformance/corpus/nodes/form-declarative.json +1 -0
  234. fuaran_py-0.0.1/conformance/corpus/nodes/form-field-rules.json +1 -0
  235. fuaran_py-0.0.1/conformance/corpus/nodes/form-local-1.json +1 -0
  236. fuaran_py-0.0.1/conformance/corpus/nodes/form-local-debounce.json +1 -0
  237. fuaran_py-0.0.1/conformance/corpus/nodes/form-ranged.json +1 -0
  238. fuaran_py-0.0.1/conformance/corpus/nodes/form-segmented.json +1 -0
  239. fuaran_py-0.0.1/conformance/corpus/nodes/form-toggle.json +1 -0
  240. fuaran_py-0.0.1/conformance/corpus/nodes/format-bindings.json +1 -0
  241. fuaran_py-0.0.1/conformance/corpus/nodes/frag-decl-1.json +1 -0
  242. fuaran_py-0.0.1/conformance/corpus/nodes/frag-decl-param.json +1 -0
  243. fuaran_py-0.0.1/conformance/corpus/nodes/frag-ref-1.json +1 -0
  244. fuaran_py-0.0.1/conformance/corpus/nodes/frag-ref-args.json +1 -0
  245. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-confirm-action-pair-ref.json +1 -0
  246. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-confirm-action-pair.json +1 -0
  247. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-empty-state-panel-ref.json +1 -0
  248. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-empty-state-panel.json +1 -0
  249. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-filter-bar-ref.json +1 -0
  250. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-filter-bar.json +1 -0
  251. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-kpi-strip-ref.json +1 -0
  252. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-kpi-strip.json +1 -0
  253. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-labelled-metric-row-ref.json +1 -0
  254. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-labelled-metric-row.json +1 -0
  255. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-loading-placeholder-ref.json +1 -0
  256. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-loading-placeholder.json +1 -0
  257. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-metric-card-ref.json +1 -0
  258. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-metric-card.json +1 -0
  259. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-section-header-ref.json +1 -0
  260. fuaran_py-0.0.1/conformance/corpus/nodes/frag-stdlib-section-header.json +1 -0
  261. fuaran_py-0.0.1/conformance/corpus/nodes/glayout-1.json +1 -0
  262. fuaran_py-0.0.1/conformance/corpus/nodes/glayout-tpl-autofit.json +1 -0
  263. fuaran_py-0.0.1/conformance/corpus/nodes/glayout-tpl-fixed.json +1 -0
  264. fuaran_py-0.0.1/conformance/corpus/nodes/glayout-tpl-ratio.json +1 -0
  265. fuaran_py-0.0.1/conformance/corpus/nodes/grid-1.json +1 -0
  266. fuaran_py-0.0.1/conformance/corpus/nodes/grid-bound-sort.json +1 -0
  267. fuaran_py-0.0.1/conformance/corpus/nodes/grid-declared-edit.json +1 -0
  268. fuaran_py-0.0.1/conformance/corpus/nodes/grid-editable-state.json +1 -0
  269. fuaran_py-0.0.1/conformance/corpus/nodes/grid-field-named.json +1 -0
  270. fuaran_py-0.0.1/conformance/corpus/nodes/grid-paged-sorted.json +1 -0
  271. fuaran_py-0.0.1/conformance/corpus/nodes/grid-paged.json +1 -0
  272. fuaran_py-0.0.1/conformance/corpus/nodes/grid-reorderable.json +1 -0
  273. fuaran_py-0.0.1/conformance/corpus/nodes/grid-sort-state-key.json +1 -0
  274. fuaran_py-0.0.1/conformance/corpus/nodes/grid-toned-pill.json +1 -0
  275. fuaran_py-0.0.1/conformance/corpus/nodes/grid-transform-param.json +1 -0
  276. fuaran_py-0.0.1/conformance/corpus/nodes/grid-transform.json +1 -0
  277. fuaran_py-0.0.1/conformance/corpus/nodes/heading-1.json +1 -0
  278. fuaran_py-0.0.1/conformance/corpus/nodes/icon-1.json +1 -0
  279. fuaran_py-0.0.1/conformance/corpus/nodes/image-1.json +1 -0
  280. fuaran_py-0.0.1/conformance/corpus/nodes/image-caption-1.json +1 -0
  281. fuaran_py-0.0.1/conformance/corpus/nodes/image-caption-i18n-1.json +1 -0
  282. fuaran_py-0.0.1/conformance/corpus/nodes/image-expandable-1.json +1 -0
  283. fuaran_py-0.0.1/conformance/corpus/nodes/image-expandable-figure-1.json +1 -0
  284. fuaran_py-0.0.1/conformance/corpus/nodes/image-presentation-1.json +1 -0
  285. fuaran_py-0.0.1/conformance/corpus/nodes/image-srcset-1.json +1 -0
  286. fuaran_py-0.0.1/conformance/corpus/nodes/limit-node-depth-at-max.json +1 -0
  287. fuaran_py-0.0.1/conformance/corpus/nodes/link-1.json +1 -0
  288. fuaran_py-0.0.1/conformance/corpus/nodes/link-protected-1.json +1 -0
  289. fuaran_py-0.0.1/conformance/corpus/nodes/list-1.json +1 -0
  290. fuaran_py-0.0.1/conformance/corpus/nodes/lvr-1.json +1 -0
  291. fuaran_py-0.0.1/conformance/corpus/nodes/map-1.json +1 -0
  292. fuaran_py-0.0.1/conformance/corpus/nodes/markdown-1.json +1 -0
  293. fuaran_py-0.0.1/conformance/corpus/nodes/masonry-1.json +1 -0
  294. fuaran_py-0.0.1/conformance/corpus/nodes/masonry-gap.json +1 -0
  295. fuaran_py-0.0.1/conformance/corpus/nodes/master-detail-multi-field.json +1 -0
  296. fuaran_py-0.0.1/conformance/corpus/nodes/master-detail-preselected-second-row.json +1 -0
  297. fuaran_py-0.0.1/conformance/corpus/nodes/master-detail-preselected.json +1 -0
  298. fuaran_py-0.0.1/conformance/corpus/nodes/math-1.json +1 -0
  299. fuaran_py-0.0.1/conformance/corpus/nodes/media-audio-1.json +1 -0
  300. fuaran_py-0.0.1/conformance/corpus/nodes/media-video-1.json +1 -0
  301. fuaran_py-0.0.1/conformance/corpus/nodes/media-video-autoplay-1.json +1 -0
  302. fuaran_py-0.0.1/conformance/corpus/nodes/media-video-poster-1.json +1 -0
  303. fuaran_py-0.0.1/conformance/corpus/nodes/metric-1.json +1 -0
  304. fuaran_py-0.0.1/conformance/corpus/nodes/metric-duration-1.json +1 -0
  305. fuaran_py-0.0.1/conformance/corpus/nodes/metric-float-17sig.json +1 -0
  306. fuaran_py-0.0.1/conformance/corpus/nodes/metric-float-bigint.json +1 -0
  307. fuaran_py-0.0.1/conformance/corpus/nodes/metric-float-exp-neg.json +1 -0
  308. fuaran_py-0.0.1/conformance/corpus/nodes/metric-float-exp-pos.json +1 -0
  309. fuaran_py-0.0.1/conformance/corpus/nodes/metric-inverted-polarity.json +1 -0
  310. fuaran_py-0.0.1/conformance/corpus/nodes/metric-invoke.json +1 -0
  311. fuaran_py-0.0.1/conformance/corpus/nodes/metric-nonfinite-sentinel.json +1 -0
  312. fuaran_py-0.0.1/conformance/corpus/nodes/modal-1.json +1 -0
  313. fuaran_py-0.0.1/conformance/corpus/nodes/mount-1.json +1 -0
  314. fuaran_py-0.0.1/conformance/corpus/nodes/mount-2.json +1 -0
  315. fuaran_py-0.0.1/conformance/corpus/nodes/multiselect-1.json +1 -0
  316. fuaran_py-0.0.1/conformance/corpus/nodes/multiselect-chip-list-param.json +1 -0
  317. fuaran_py-0.0.1/conformance/corpus/nodes/now-environment-binding.json +1 -0
  318. fuaran_py-0.0.1/conformance/corpus/nodes/progress-1.json +1 -0
  319. fuaran_py-0.0.1/conformance/corpus/nodes/query-dependson.json +1 -0
  320. fuaran_py-0.0.1/conformance/corpus/nodes/scalar-transform-composition.json +1 -0
  321. fuaran_py-0.0.1/conformance/corpus/nodes/scroll-1.json +1 -0
  322. fuaran_py-0.0.1/conformance/corpus/nodes/select-1.json +1 -0
  323. fuaran_py-0.0.1/conformance/corpus/nodes/shared-source-seeded-pair.json +1 -0
  324. fuaran_py-0.0.1/conformance/corpus/nodes/skel-1.json +1 -0
  325. fuaran_py-0.0.1/conformance/corpus/nodes/spark-1.json +1 -0
  326. fuaran_py-0.0.1/conformance/corpus/nodes/spark-nonfinite-sentinel.json +1 -0
  327. fuaran_py-0.0.1/conformance/corpus/nodes/split-1.json +1 -0
  328. fuaran_py-0.0.1/conformance/corpus/nodes/stack-1.json +1 -0
  329. fuaran_py-0.0.1/conformance/corpus/nodes/step-1.json +1 -0
  330. fuaran_py-0.0.1/conformance/corpus/nodes/style-role-voice-1.json +1 -0
  331. fuaran_py-0.0.1/conformance/corpus/nodes/summary-1.json +1 -0
  332. fuaran_py-0.0.1/conformance/corpus/nodes/switch-1.json +1 -0
  333. fuaran_py-0.0.1/conformance/corpus/nodes/switch-on-selection.json +1 -0
  334. fuaran_py-0.0.1/conformance/corpus/nodes/table-1.json +1 -0
  335. fuaran_py-0.0.1/conformance/corpus/nodes/table-sortable-1.json +1 -0
  336. fuaran_py-0.0.1/conformance/corpus/nodes/tabs-1.json +1 -0
  337. fuaran_py-0.0.1/conformance/corpus/nodes/tabs-explicit-1.json +1 -0
  338. fuaran_py-0.0.1/conformance/corpus/nodes/toast-1.json +1 -0
  339. fuaran_py-0.0.1/conformance/corpus/nodes/upload-1.json +1 -0
  340. fuaran_py-0.0.1/conformance/corpus/ops/op-batch.json +1 -0
  341. fuaran_py-0.0.1/conformance/corpus/ops/op-editnode.json +1 -0
  342. fuaran_py-0.0.1/conformance/corpus/ops/op-insertchild.json +1 -0
  343. fuaran_py-0.0.1/conformance/corpus/ops/op-movenode.json +1 -0
  344. fuaran_py-0.0.1/conformance/corpus/ops/op-removenode.json +1 -0
  345. fuaran_py-0.0.1/conformance/corpus/ops/op-reorderchildren.json +1 -0
  346. fuaran_py-0.0.1/conformance/corpus/ops/op-replacebinding.json +1 -0
  347. fuaran_py-0.0.1/conformance/corpus/ops/op-replaceroot.json +1 -0
  348. fuaran_py-0.0.1/conformance/corpus/ops/op-updateprop-nested-badfield.json +1 -0
  349. fuaran_py-0.0.1/conformance/corpus/ops/op-updateprop-nested-badindex.json +1 -0
  350. fuaran_py-0.0.1/conformance/corpus/ops/op-updateprop-nested-column0-label.json +1 -0
  351. fuaran_py-0.0.1/conformance/corpus/ops/op-updateprop-nested-column1-label.json +1 -0
  352. fuaran_py-0.0.1/conformance/corpus/ops/op-updateprop-nested-field0-required.json +1 -0
  353. fuaran_py-0.0.1/conformance/corpus/ops/op-updateprop-nested-field1-required.json +1 -0
  354. fuaran_py-0.0.1/conformance/corpus/ops/op-updateprop-nested-malformed.json +1 -0
  355. fuaran_py-0.0.1/conformance/corpus/ops/op-updateprop-nested-object-value.json +1 -0
  356. fuaran_py-0.0.1/conformance/corpus/ops/op-updateprop-nested-yfield0.json +1 -0
  357. fuaran_py-0.0.1/conformance/corpus/ops/op-updateprop-nested-yfield1.json +1 -0
  358. fuaran_py-0.0.1/conformance/corpus/ops/op-updateprop.json +1 -0
  359. fuaran_py-0.0.1/conformance/corpus/ops/op-updatestate.json +1 -0
  360. fuaran_py-0.0.1/conformance/corpus/ops/op-updatestyle (phase 147 role=eyebrow + voice=structural).json +1 -0
  361. fuaran_py-0.0.1/conformance/corpus/ops/op-updatestyle.json +1 -0
  362. fuaran_py-0.0.1/conformance/corpus/reject/reject-a11y-hidden-nonbool.json +1 -0
  363. fuaran_py-0.0.1/conformance/corpus/reject/reject-a11y-labelledby-nonstring.json +1 -0
  364. fuaran_py-0.0.1/conformance/corpus/reject/reject-a11y-liveregion-nonstring.json +1 -0
  365. fuaran_py-0.0.1/conformance/corpus/reject/reject-a11y-liveregion-unknown.json +1 -0
  366. fuaran_py-0.0.1/conformance/corpus/reject/reject-a11y-not-object.json +1 -0
  367. fuaran_py-0.0.1/conformance/corpus/reject/reject-a11y-role-nonstring.json +1 -0
  368. fuaran_py-0.0.1/conformance/corpus/reject/reject-binding-float-bool.json +1 -0
  369. fuaran_py-0.0.1/conformance/corpus/reject/reject-binding-float-sentinel-case.json +1 -0
  370. fuaran_py-0.0.1/conformance/corpus/reject/reject-binding-float-string.json +1 -0
  371. fuaran_py-0.0.1/conformance/corpus/reject/reject-binding-int-bool.json +1 -0
  372. fuaran_py-0.0.1/conformance/corpus/reject/reject-binding-int-sentinel-string.json +1 -0
  373. fuaran_py-0.0.1/conformance/corpus/reject/reject-box-masonry-nonpositive-cols.json +1 -0
  374. fuaran_py-0.0.1/conformance/corpus/reject/reject-daterange-unordered.json +1 -0
  375. fuaran_py-0.0.1/conformance/corpus/reject/reject-emptynodeid.json +1 -0
  376. fuaran_py-0.0.1/conformance/corpus/reject/reject-fieldrule-empty.json +1 -0
  377. fuaran_py-0.0.1/conformance/corpus/reject/reject-fieldrule-length-unordered.json +1 -0
  378. fuaran_py-0.0.1/conformance/corpus/reject/reject-formfield-near-miss-validation.json +1 -0
  379. fuaran_py-0.0.1/conformance/corpus/reject/reject-image-expandable-nonbool.json +1 -0
  380. fuaran_py-0.0.1/conformance/corpus/reject/reject-image-srcset-nonpositive-width.json +1 -0
  381. fuaran_py-0.0.1/conformance/corpus/reject/reject-image-srcset-null.json +1 -0
  382. fuaran_py-0.0.1/conformance/corpus/reject/reject-invalid-empty.json +0 -0
  383. fuaran_py-0.0.1/conformance/corpus/reject/reject-invalid-garbage.json +1 -0
  384. fuaran_py-0.0.1/conformance/corpus/reject/reject-invalid-truncated.json +1 -0
  385. fuaran_py-0.0.1/conformance/corpus/reject/reject-limit-json-depth-at-max.json +1 -0
  386. fuaran_py-0.0.1/conformance/corpus/reject/reject-limit-json-depth.json +1 -0
  387. fuaran_py-0.0.1/conformance/corpus/reject/reject-limit-node-depth.json +1 -0
  388. fuaran_py-0.0.1/conformance/corpus/reject/reject-limit-op-depth.json +1 -0
  389. fuaran_py-0.0.1/conformance/corpus/reject/reject-media-autoplay-nonbool.json +1 -0
  390. fuaran_py-0.0.1/conformance/corpus/reject/reject-media-missing-label.json +1 -0
  391. fuaran_py-0.0.1/conformance/corpus/reject/reject-missing-binding-type.json +1 -0
  392. fuaran_py-0.0.1/conformance/corpus/reject/reject-missing-custom-moduleid.json +1 -0
  393. fuaran_py-0.0.1/conformance/corpus/reject/reject-missing-markdown-text.json +1 -0
  394. fuaran_py-0.0.1/conformance/corpus/reject/reject-missing-metric-value.json +1 -0
  395. fuaran_py-0.0.1/conformance/corpus/reject/reject-missing-mount-scopeid.json +1 -0
  396. fuaran_py-0.0.1/conformance/corpus/reject/reject-missing-node-id.json +1 -0
  397. fuaran_py-0.0.1/conformance/corpus/reject/reject-missing-node-kind.json +1 -0
  398. fuaran_py-0.0.1/conformance/corpus/reject/reject-missing-switch-cases.json +1 -0
  399. fuaran_py-0.0.1/conformance/corpus/reject/reject-missing-switch-default.json +1 -0
  400. fuaran_py-0.0.1/conformance/corpus/reject/reject-missing-switch-statekey.json +1 -0
  401. fuaran_py-0.0.1/conformance/corpus/reject/reject-nearmiss-a11y-aria-hidden.json +1 -0
  402. fuaran_py-0.0.1/conformance/corpus/reject/reject-nearmiss-a11y-arialabel.json +1 -0
  403. fuaran_py-0.0.1/conformance/corpus/reject/reject-nearmiss-a11y-live.json +1 -0
  404. fuaran_py-0.0.1/conformance/corpus/reject/reject-nearmiss-a11y-liveregion-case.json +1 -0
  405. fuaran_py-0.0.1/conformance/corpus/reject/reject-nearmiss-column-readonly.json +1 -0
  406. fuaran_py-0.0.1/conformance/corpus/reject/reject-nearmiss-grid-behaviour-record.json +1 -0
  407. fuaran_py-0.0.1/conformance/corpus/reject/reject-nearmiss-grid-current-page.json +1 -0
  408. fuaran_py-0.0.1/conformance/corpus/reject/reject-nearmiss-grid-sortable.json +1 -0
  409. fuaran_py-0.0.1/conformance/corpus/reject/reject-null-action-aitool-args.json +1 -0
  410. fuaran_py-0.0.1/conformance/corpus/reject/reject-null-action-notify-payload.json +1 -0
  411. fuaran_py-0.0.1/conformance/corpus/reject/reject-null-action-setstate-value.json +1 -0
  412. fuaran_py-0.0.1/conformance/corpus/reject/reject-null-custom-prop.json +1 -0
  413. fuaran_py-0.0.1/conformance/corpus/reject/reject-null-i18n-arg.json +1 -0
  414. fuaran_py-0.0.1/conformance/corpus/reject/reject-null-updateprop-value.json +1 -0
  415. fuaran_py-0.0.1/conformance/corpus/reject/reject-op-insertchild-empty-childid.json +1 -0
  416. fuaran_py-0.0.1/conformance/corpus/reject/reject-op-insertchild-missing-parentid.json +1 -0
  417. fuaran_py-0.0.1/conformance/corpus/reject/reject-op-insertchild-retired-position.json +1 -0
  418. fuaran_py-0.0.1/conformance/corpus/reject/reject-op-missing-type.json +1 -0
  419. fuaran_py-0.0.1/conformance/corpus/reject/reject-op-movenode-retired-newposition.json +1 -0
  420. fuaran_py-0.0.1/conformance/corpus/reject/reject-op-reorderchildren-wrongtype.json +1 -0
  421. fuaran_py-0.0.1/conformance/corpus/reject/reject-op-unknown-yeet.json +1 -0
  422. fuaran_py-0.0.1/conformance/corpus/reject/reject-op-updateprop-missing-path.json +1 -0
  423. fuaran_py-0.0.1/conformance/corpus/reject/reject-setstate-value-and-valuefrom.json +1 -0
  424. fuaran_py-0.0.1/conformance/corpus/reject/reject-tonedpill-unknown-tone.json +1 -0
  425. fuaran_py-0.0.1/conformance/corpus/reject/reject-unknown-binding.json +1 -0
  426. fuaran_py-0.0.1/conformance/corpus/reject/reject-unknown-drawing-curve-command.json +1 -0
  427. fuaran_py-0.0.1/conformance/corpus/reject/reject-unknown-drawing-shape.json +1 -0
  428. fuaran_py-0.0.1/conformance/corpus/reject/reject-unknown-image-aspect.json +1 -0
  429. fuaran_py-0.0.1/conformance/corpus/reject/reject-unknown-link-protection.json +1 -0
  430. fuaran_py-0.0.1/conformance/corpus/reject/reject-unknown-media-kind.json +1 -0
  431. fuaran_py-0.0.1/conformance/corpus/reject/reject-unknown-mount-direction.json +1 -0
  432. fuaran_py-0.0.1/conformance/corpus/reject/reject-unknown-static-sort-direction.json +1 -0
  433. fuaran_py-0.0.1/conformance/corpus/reject/reject-unknown-textsource.json +1 -0
  434. fuaran_py-0.0.1/conformance/corpus/reject/reject-unknown-tone.json +1 -0
  435. fuaran_py-0.0.1/conformance/corpus/reject/reject-unknown-trend-polarity.json +1 -0
  436. fuaran_py-0.0.1/conformance/corpus/reject/reject-wrongnodekind-sparkler.json +1 -0
  437. fuaran_py-0.0.1/conformance/corpus/reject/reject-wrongnodekind-widget.json +1 -0
  438. fuaran_py-0.0.1/conformance/corpus/reject/reject-wrongtype-box-children.json +1 -0
  439. fuaran_py-0.0.1/conformance/corpus/reject/reject-wrongtype-discriminator.json +1 -0
  440. fuaran_py-0.0.1/conformance/corpus/reject/reject-wrongtype-grid-default-sort-column.json +1 -0
  441. fuaran_py-0.0.1/conformance/corpus/reject/reject-wrongtype-grid-page-size-zero.json +1 -0
  442. fuaran_py-0.0.1/conformance/corpus/reject/reject-wrongtype-heading-level.json +1 -0
  443. fuaran_py-0.0.1/conformance/corpus/reject/reject-wrongtype-id.json +1 -0
  444. fuaran_py-0.0.1/conformance/corpus/reject/reject-wrongtype-kind.json +1 -0
  445. fuaran_py-0.0.1/conformance/corpus/reject/reject-wrongtype-static-sort-column.json +1 -0
  446. fuaran_py-0.0.1/conformance/corpus/reject/reject-wrongtype-style-tone.json +1 -0
  447. fuaran_py-0.0.1/conformance/corpus/schema.json +8164 -0
  448. fuaran_py-0.0.1/conformance/sync_corpus.py +65 -0
  449. fuaran_py-0.0.1/docs/AUTHORING.md +104 -0
  450. fuaran_py-0.0.1/docs/fable-python-decision.md +127 -0
  451. fuaran_py-0.0.1/examples/quickstart_client.py +36 -0
  452. fuaran_py-0.0.1/examples/quickstart_reactive_data_app.py +119 -0
  453. fuaran_py-0.0.1/pyproject.toml +63 -0
  454. fuaran_py-0.0.1/run.ps1 +106 -0
  455. fuaran_py-0.0.1/samples/fastapi-host/README.md +116 -0
  456. fuaran_py-0.0.1/samples/fastapi-host/app.py +186 -0
  457. fuaran_py-0.0.1/samples/fastapi-host/requirements.txt +6 -0
  458. fuaran_py-0.0.1/src/fuaran_py/__init__.py +107 -0
  459. fuaran_py-0.0.1/src/fuaran_py/ai_tools/__init__.py +86 -0
  460. fuaran_py-0.0.1/src/fuaran_py/ai_tools/dispatch.py +91 -0
  461. fuaran_py-0.0.1/src/fuaran_py/ai_tools/introspect.py +190 -0
  462. fuaran_py-0.0.1/src/fuaran_py/ai_tools/surface.py +194 -0
  463. fuaran_py-0.0.1/src/fuaran_py/canonical.py +165 -0
  464. fuaran_py-0.0.1/src/fuaran_py/charts/__init__.py +2693 -0
  465. fuaran_py-0.0.1/src/fuaran_py/client/__init__.py +68 -0
  466. fuaran_py-0.0.1/src/fuaran_py/client/client.py +147 -0
  467. fuaran_py-0.0.1/src/fuaran_py/client/contract.py +136 -0
  468. fuaran_py-0.0.1/src/fuaran_py/client/session.py +64 -0
  469. fuaran_py-0.0.1/src/fuaran_py/client/wire.py +141 -0
  470. fuaran_py-0.0.1/src/fuaran_py/compute/__init__.py +38 -0
  471. fuaran_py-0.0.1/src/fuaran_py/compute/evaluate.py +437 -0
  472. fuaran_py-0.0.1/src/fuaran_py/conformance/__init__.py +7 -0
  473. fuaran_py-0.0.1/src/fuaran_py/conformance/bridge.py +84 -0
  474. fuaran_py-0.0.1/src/fuaran_py/conformance/decoder_fuzz.py +1036 -0
  475. fuaran_py-0.0.1/src/fuaran_py/conformance/fuzz_exchange.py +209 -0
  476. fuaran_py-0.0.1/src/fuaran_py/conformance/harness.py +111 -0
  477. fuaran_py-0.0.1/src/fuaran_py/conformance/refusal_report.py +123 -0
  478. fuaran_py-0.0.1/src/fuaran_py/dag.py +172 -0
  479. fuaran_py-0.0.1/src/fuaran_py/dataframe/__init__.py +143 -0
  480. fuaran_py-0.0.1/src/fuaran_py/dataframe/codec.py +1078 -0
  481. fuaran_py-0.0.1/src/fuaran_py/dataframe/evaluate.py +899 -0
  482. fuaran_py-0.0.1/src/fuaran_py/dataframe/model.py +424 -0
  483. fuaran_py-0.0.1/src/fuaran_py/elicitation.py +549 -0
  484. fuaran_py-0.0.1/src/fuaran_py/envelope.py +161 -0
  485. fuaran_py-0.0.1/src/fuaran_py/function.py +294 -0
  486. fuaran_py-0.0.1/src/fuaran_py/layout_observer/__init__.py +70 -0
  487. fuaran_py-0.0.1/src/fuaran_py/layout_observer/flags.py +260 -0
  488. fuaran_py-0.0.1/src/fuaran_py/layout_observer/observer.py +230 -0
  489. fuaran_py-0.0.1/src/fuaran_py/limits.py +62 -0
  490. fuaran_py-0.0.1/src/fuaran_py/merge.py +539 -0
  491. fuaran_py-0.0.1/src/fuaran_py/model.py +70 -0
  492. fuaran_py-0.0.1/src/fuaran_py/op_stream/__init__.py +114 -0
  493. fuaran_py-0.0.1/src/fuaran_py/op_stream/hash_chain.py +230 -0
  494. fuaran_py-0.0.1/src/fuaran_py/op_stream/in_memory_sink.py +76 -0
  495. fuaran_py-0.0.1/src/fuaran_py/op_stream/replay.py +180 -0
  496. fuaran_py-0.0.1/src/fuaran_py/op_stream/types.py +205 -0
  497. fuaran_py-0.0.1/src/fuaran_py/ops/__init__.py +26 -0
  498. fuaran_py-0.0.1/src/fuaran_py/ops/apply.py +1053 -0
  499. fuaran_py-0.0.1/src/fuaran_py/ops/decode.py +233 -0
  500. fuaran_py-0.0.1/src/fuaran_py/ops/diff.py +305 -0
  501. fuaran_py-0.0.1/src/fuaran_py/ops/encode.py +11 -0
  502. fuaran_py-0.0.1/src/fuaran_py/render_fidelity.py +439 -0
  503. fuaran_py-0.0.1/src/fuaran_py/renderer/__init__.py +84 -0
  504. fuaran_py-0.0.1/src/fuaran_py/renderer/bindings.py +348 -0
  505. fuaran_py-0.0.1/src/fuaran_py/renderer/content/fuaran-reference.css +2723 -0
  506. fuaran_py-0.0.1/src/fuaran_py/renderer/egress.py +562 -0
  507. fuaran_py-0.0.1/src/fuaran_py/renderer/html.py +67 -0
  508. fuaran_py-0.0.1/src/fuaran_py/renderer/markdown.py +1211 -0
  509. fuaran_py-0.0.1/src/fuaran_py/renderer/render.py +1945 -0
  510. fuaran_py-0.0.1/src/fuaran_py/renderer/sanitize.py +287 -0
  511. fuaran_py-0.0.1/src/fuaran_py/renderer/seeds.py +149 -0
  512. fuaran_py-0.0.1/src/fuaran_py/renderer/theme.py +208 -0
  513. fuaran_py-0.0.1/src/fuaran_py/result.py +71 -0
  514. fuaran_py-0.0.1/src/fuaran_py/runtime/__init__.py +22 -0
  515. fuaran_py-0.0.1/src/fuaran_py/runtime/runtime.py +256 -0
  516. fuaran_py-0.0.1/src/fuaran_py/runtime/sample.py +57 -0
  517. fuaran_py-0.0.1/src/fuaran_py/schema/__init__.py +15 -0
  518. fuaran_py-0.0.1/src/fuaran_py/schema/decode.py +2888 -0
  519. fuaran_py-0.0.1/src/fuaran_py/schema/encode.py +11 -0
  520. fuaran_py-0.0.1/src/fuaran_py/schema/types.py +2169 -0
  521. fuaran_py-0.0.1/src/fuaran_py/shapeguard.py +129 -0
  522. fuaran_py-0.0.1/src/fuaran_py/style_observer/__init__.py +129 -0
  523. fuaran_py-0.0.1/src/fuaran_py/style_observer/color.py +91 -0
  524. fuaran_py-0.0.1/src/fuaran_py/style_observer/flags.py +326 -0
  525. fuaran_py-0.0.1/src/fuaran_py/style_observer/manifest_flags.py +108 -0
  526. fuaran_py-0.0.1/src/fuaran_py/style_observer/observer.py +320 -0
  527. fuaran_py-0.0.1/src/fuaran_py/teleport.py +240 -0
  528. fuaran_py-0.0.1/src/fuaran_py/theme_manifest/__init__.py +91 -0
  529. fuaran_py-0.0.1/src/fuaran_py/theme_manifest/decode.py +162 -0
  530. fuaran_py-0.0.1/src/fuaran_py/theme_manifest/manifest.py +184 -0
  531. fuaran_py-0.0.1/src/fuaran_py/theme_manifest/project.py +173 -0
  532. fuaran_py-0.0.1/src/fuaran_py/ui/__init__.py +1025 -0
  533. fuaran_py-0.0.1/src/fuaran_py/ui/capability.py +238 -0
  534. fuaran_py-0.0.1/src/fuaran_py/ui/compute.py +546 -0
  535. fuaran_py-0.0.1/src/fuaran_py/validator/__init__.py +7 -0
  536. fuaran_py-0.0.1/src/fuaran_py/validator/validate.py +455 -0
  537. fuaran_py-0.0.1/tests/_corpus.py +105 -0
  538. fuaran_py-0.0.1/tests/_reference_host.py +95 -0
  539. fuaran_py-0.0.1/tests/fixtures/dataframe_parity.json +1 -0
  540. fuaran_py-0.0.1/tests/test_action_cases.py +62 -0
  541. fuaran_py-0.0.1/tests/test_ai_tools.py +179 -0
  542. fuaran_py-0.0.1/tests/test_authoring_toggle_now_selection.py +158 -0
  543. fuaran_py-0.0.1/tests/test_bare_state_source.py +75 -0
  544. fuaran_py-0.0.1/tests/test_bridge.py +91 -0
  545. fuaran_py-0.0.1/tests/test_browser_style_observer.py +80 -0
  546. fuaran_py-0.0.1/tests/test_canonical_numbers.py +48 -0
  547. fuaran_py-0.0.1/tests/test_capability_seam.py +118 -0
  548. fuaran_py-0.0.1/tests/test_chart_lowering.py +831 -0
  549. fuaran_py-0.0.1/tests/test_client.py +339 -0
  550. fuaran_py-0.0.1/tests/test_client_mock_endpoint.py +109 -0
  551. fuaran_py-0.0.1/tests/test_compute.py +361 -0
  552. fuaran_py-0.0.1/tests/test_compute_authoring.py +123 -0
  553. fuaran_py-0.0.1/tests/test_corpus_sync.py +75 -0
  554. fuaran_py-0.0.1/tests/test_dag_roundtrip.py +70 -0
  555. fuaran_py-0.0.1/tests/test_dataframe_parity.py +72 -0
  556. fuaran_py-0.0.1/tests/test_decoder_fuzz.py +202 -0
  557. fuaran_py-0.0.1/tests/test_diff.py +365 -0
  558. fuaran_py-0.0.1/tests/test_diff_golden.py +116 -0
  559. fuaran_py-0.0.1/tests/test_egress_policy.py +485 -0
  560. fuaran_py-0.0.1/tests/test_elicitation.py +115 -0
  561. fuaran_py-0.0.1/tests/test_envelope.py +93 -0
  562. fuaran_py-0.0.1/tests/test_fastapi_host.py +140 -0
  563. fuaran_py-0.0.1/tests/test_field_rule.py +316 -0
  564. fuaran_py-0.0.1/tests/test_function.py +159 -0
  565. fuaran_py-0.0.1/tests/test_fuzz_exchange.py +168 -0
  566. fuaran_py-0.0.1/tests/test_generative_parity.py +104 -0
  567. fuaran_py-0.0.1/tests/test_kind_set.py +125 -0
  568. fuaran_py-0.0.1/tests/test_layout_observer.py +162 -0
  569. fuaran_py-0.0.1/tests/test_lenient.py +32 -0
  570. fuaran_py-0.0.1/tests/test_limits.py +176 -0
  571. fuaran_py-0.0.1/tests/test_manifest_flags.py +135 -0
  572. fuaran_py-0.0.1/tests/test_markdown_corpus.py +176 -0
  573. fuaran_py-0.0.1/tests/test_masonry_layout.py +119 -0
  574. fuaran_py-0.0.1/tests/test_merge_conformance.py +149 -0
  575. fuaran_py-0.0.1/tests/test_merge_primacy.py +207 -0
  576. fuaran_py-0.0.1/tests/test_op_stream.py +268 -0
  577. fuaran_py-0.0.1/tests/test_ops_apply.py +451 -0
  578. fuaran_py-0.0.1/tests/test_reject.py +20 -0
  579. fuaran_py-0.0.1/tests/test_render_a11y_corpus.py +136 -0
  580. fuaran_py-0.0.1/tests/test_render_a11y_placement.py +88 -0
  581. fuaran_py-0.0.1/tests/test_render_a11y_projection.py +125 -0
  582. fuaran_py-0.0.1/tests/test_render_fidelity.py +143 -0
  583. fuaran_py-0.0.1/tests/test_render_obligations.py +479 -0
  584. fuaran_py-0.0.1/tests/test_render_parity.py +188 -0
  585. fuaran_py-0.0.1/tests/test_render_sanitize.py +228 -0
  586. fuaran_py-0.0.1/tests/test_renderer.py +395 -0
  587. fuaran_py-0.0.1/tests/test_retired_position.py +68 -0
  588. fuaran_py-0.0.1/tests/test_roundtrip.py +24 -0
  589. fuaran_py-0.0.1/tests/test_runtime.py +146 -0
  590. fuaran_py-0.0.1/tests/test_sanitization_corpus.py +137 -0
  591. fuaran_py-0.0.1/tests/test_scalar_compute_parity.py +174 -0
  592. fuaran_py-0.0.1/tests/test_schema_conformance.py +75 -0
  593. fuaran_py-0.0.1/tests/test_state_seeding.py +211 -0
  594. fuaran_py-0.0.1/tests/test_style_observer.py +205 -0
  595. fuaran_py-0.0.1/tests/test_teleport.py +131 -0
  596. fuaran_py-0.0.1/tests/test_theme_manifest.py +118 -0
  597. fuaran_py-0.0.1/tests/test_toned_pill.py +160 -0
  598. fuaran_py-0.0.1/tests/test_trend_polarity.py +248 -0
  599. fuaran_py-0.0.1/tests/test_ui_authoring.py +441 -0
  600. fuaran_py-0.0.1/tests/test_validator.py +252 -0
  601. fuaran_py-0.0.1/tests/test_validator_coverage.py +83 -0
  602. fuaran_py-0.0.1/validator-coverage.json +34 -0
@@ -0,0 +1,31 @@
1
+ # Pin canonical text-file line endings to LF.
2
+ #
3
+ # `text=auto` lets git detect text vs. binary; `eol=lf` pins the
4
+ # canonical in-repo line ending. On a Windows checkout, files stay LF
5
+ # on disk (no autocrlf round-trip churn), eliminating the recurring
6
+ # "LF will be replaced by CRLF the next time Git touches it" warnings
7
+ # and phantom "modified" churn on tool-regenerated files.
8
+
9
+ * text=auto eol=lf
10
+
11
+ # Explicit binary types — git's auto-detection is usually correct
12
+ # but spell out the common ones to be safe.
13
+ *.png binary
14
+ *.jpg binary
15
+ *.jpeg binary
16
+ *.gif binary
17
+ *.ico binary
18
+ *.svg binary
19
+ *.dll binary
20
+ *.exe binary
21
+ *.pdb binary
22
+ *.nupkg binary
23
+ *.snupkg binary
24
+ *.zip binary
25
+ *.tar binary
26
+ *.gz binary
27
+ *.pdf binary
28
+ *.woff binary
29
+ *.woff2 binary
30
+ *.ttf binary
31
+ *.eot binary
@@ -0,0 +1,150 @@
1
+ # Build, test and wire-format conformance gate for the Python host.
2
+ #
3
+ # ── Layout ───────────────────────────────────────────────────────────────────
4
+ # The conformance corpus is its own public repository. The test suite resolves
5
+ # it as a SIBLING of this repo root (tests/_corpus.py walks to
6
+ # `<container>/wire-format-fixtures`), so this repo is checked out into a
7
+ # subdirectory and the corpus beside it:
8
+ #
9
+ # $GITHUB_WORKSPACE/
10
+ # ├── fuaran-py/ ← this repo
11
+ # └── wire-format-fixtures/ ← the corpus (fuaran-ui/fuaran-ui-specification)
12
+ #
13
+ # The corpus repository is PUBLIC, so the checkout is anonymous — no token.
14
+ #
15
+ # ── Why the corpus assertion below is not optional ───────────────────────────
16
+ # When the corpus is absent, tests/_corpus.py does NOT fail — it silently falls
17
+ # back to the committed offline snapshot under conformance/corpus/. A layout
18
+ # drift would therefore leave the suite certifying against a stale local copy of
19
+ # the spec while the job stayed green, which is the one failure mode a
20
+ # conformance gate must never have. The assertion turns that into a hard stop.
21
+
22
+ name: CI
23
+
24
+ on:
25
+ push:
26
+ branches: [main]
27
+ pull_request:
28
+ branches: [main]
29
+
30
+ permissions:
31
+ contents: read
32
+
33
+ env:
34
+ # ── QUARANTINE ──────────────────────────────────────────────────────────────────────────
35
+ # Cases that fail on a clean tree are excluded from the blocking gate here, so
36
+ # that a NEW regression is caught while known drift stays visible. An entry is
37
+ # not a judgement that a case is wrong — it is a record of known, understood,
38
+ # outstanding work, and the list SHRINKS TO EMPTY as the decoder catches up.
39
+ # Delete entries as they start passing; do not add to it to make a red build
40
+ # green without a root-cause note — a new failure here is the regression this
41
+ # gate exists to catch.
42
+ #
43
+ # EMPTY as of 2026-08-13: the Toggle/Now/Switch vocabulary landed
44
+ # (3ac3c87/8e9fac3), the offline corpus snapshot was re-synced (392abd6), and
45
+ # every formerly quarantined case passes against the current corpus —
46
+ # verified by the full suite at 1627 passed with zero deselections AND each
47
+ # former entry re-run by node ID (24 passed). The machinery stays armed; a
48
+ # future corpus advance repopulates the list the same way.
49
+ QUARANTINE: ""
50
+
51
+ jobs:
52
+ build:
53
+ runs-on: ubuntu-latest
54
+ defaults:
55
+ run:
56
+ working-directory: fuaran-py
57
+ steps:
58
+ - uses: actions/checkout@v4
59
+ with:
60
+ path: fuaran-py
61
+
62
+ # Deliberately UNPINNED: the corpus is the shared conformance authority
63
+ # every host certifies against, and one current spec for all hosts is the
64
+ # point of giving it a single home. Pinning here would let this host drift
65
+ # from the spec without anything going red.
66
+ - name: Check out the wire-format conformance corpus
67
+ uses: actions/checkout@v4
68
+ with:
69
+ repository: fuaran-ui/fuaran-ui-specification
70
+ path: wire-format-fixtures
71
+
72
+ - name: Assert the corpus is where the tests resolve it
73
+ run: test -f ../wire-format-fixtures/manifest.json
74
+
75
+ - uses: actions/setup-python@v5
76
+ with:
77
+ python-version: '3.13'
78
+
79
+ - name: Install
80
+ run: |
81
+ python -m pip install --upgrade pip
82
+ python -m pip install ".[dev]"
83
+
84
+ - name: Lint (ruff check)
85
+ run: python -m ruff check .
86
+
87
+ - name: Format check (ruff format)
88
+ run: python -m ruff format --check .
89
+
90
+ - name: Type check (mypy)
91
+ run: python -m mypy
92
+
93
+ # Print what this gate does NOT cover, on every run. A cap nobody can see
94
+ # reads as "covered everything".
95
+ - name: Report the conformance quarantine
96
+ run: |
97
+ if [ -n "$QUARANTINE" ]; then
98
+ echo "The blocking gate below EXCLUDES these known-failing cases:"
99
+ echo "$QUARANTINE" | tr ' ' '\n' | grep -v '^--deselect$' | sed 's/^/ - /'
100
+ else
101
+ echo "Quarantine EMPTY — the blocking gate covers the full conformance suite."
102
+ fi
103
+ echo
104
+ echo "ALSO NOT GATED HERE — inert rather than quarantined (see the skip"
105
+ echo "summary that -rs prints under each test run below):"
106
+ echo " - the reference-renderer parity tests read the reference host's source"
107
+ echo " from a sibling checkout this workflow does not make, so they skip."
108
+ echo " A skip here does NOT mean the path they look in is right: it was"
109
+ echo " wrong for months (the host was renamed) and this note read as the"
110
+ echo " explanation. What proves the path now is"
111
+ echo " test_reference_host_resolves_in_a_cross_host_checkout, which never"
112
+ echo " skips and fails in any checkout that HAS sibling hosts but no"
113
+ echo " reference host. It passes here because this job is genuinely a"
114
+ echo " single-host checkout — the one shape in which skipping is honest."
115
+ echo " - the FastAPI sample-host tests skip because fastapi is a sample-only"
116
+ echo " dependency and is not in the [dev] extra this job installs."
117
+ {
118
+ echo "### Conformance quarantine (excluded from the blocking gate)"
119
+ echo
120
+ if [ -n "$QUARANTINE" ]; then
121
+ echo '```'
122
+ echo "$QUARANTINE" | tr ' ' '\n' | grep -v '^--deselect$'
123
+ echo '```'
124
+ else
125
+ echo "Empty — the blocking gate covers the full conformance suite."
126
+ fi
127
+ } >> "$GITHUB_STEP_SUMMARY"
128
+
129
+ # Non-blocking: runs the FULL suite so the size of the existing drift is
130
+ # measured on every run rather than inferred from the quarantine list.
131
+ - name: Conformance drift (reported, non-blocking)
132
+ continue-on-error: true
133
+ run: |
134
+ set +e
135
+ python -m pytest -q -rs > drift.log 2>&1
136
+ status=$?
137
+ tail -40 drift.log
138
+ {
139
+ echo "### Full suite, including quarantined cases (non-blocking)"
140
+ echo
141
+ echo '```'
142
+ grep -E '^[0-9]+ (failed|passed)|failed,|passed,' drift.log | tail -3
143
+ echo '```'
144
+ } >> "$GITHUB_STEP_SUMMARY"
145
+ exit 0
146
+
147
+ # THE GATE. Everything the suite currently passes, including every
148
+ # conformance case outside the quarantine above.
149
+ - name: Test (gated)
150
+ run: python -m pytest -q -rs $QUARANTINE
@@ -0,0 +1,64 @@
1
+ # Publish fuaran-py to PyPI on a version tag, via PyPI Trusted Publishing (OIDC — no stored token).
2
+ #
3
+ # Trigger: a `v*` tag push only. A branch push reaches no publish job.
4
+ # Prerequisites (one-time, on pypi.org): register this repository as the project's trusted
5
+ # publisher — owner `fuaran-ui`, repository `fuaran-py`, workflow `publish-pypi.yml`,
6
+ # environment `pypi` — then create the `pypi` environment on this repository.
7
+ # The tag must equal the version in pyproject.toml; the gate below refuses otherwise, so a
8
+ # mistyped tag never publishes a mismatched release.
9
+ name: publish-pypi
10
+
11
+ on:
12
+ push:
13
+ tags: ["v*"]
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ build:
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+ - uses: actions/setup-python@v5
24
+ with:
25
+ python-version: "3.13"
26
+ - name: Version gate — tag must equal pyproject version
27
+ run: |
28
+ set -euo pipefail
29
+ tag="${GITHUB_REF_NAME#v}"
30
+ ver="$(python - <<'PY'
31
+ import tomllib
32
+ print(tomllib.load(open("pyproject.toml","rb"))["project"]["version"])
33
+ PY
34
+ )"
35
+ if [ "$tag" != "$ver" ]; then
36
+ echo "tag v$tag does not match pyproject version $ver" >&2
37
+ exit 1
38
+ fi
39
+ - name: Build sdist + wheel
40
+ run: |
41
+ python -m pip install --upgrade pip build
42
+ python -m build
43
+ - uses: actions/upload-artifact@v4
44
+ with:
45
+ name: dist
46
+ path: dist/
47
+ if-no-files-found: error
48
+
49
+ publish:
50
+ needs: build
51
+ runs-on: ubuntu-latest
52
+ environment: pypi
53
+ permissions:
54
+ id-token: write
55
+ contents: read
56
+ steps:
57
+ - uses: actions/download-artifact@v4
58
+ with:
59
+ name: dist
60
+ path: dist/
61
+ - name: Publish to PyPI (Trusted Publishing)
62
+ uses: pypa/gh-action-pypi-publish@release/v1
63
+ with:
64
+ skip-existing: true
@@ -0,0 +1,32 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+
9
+ # Virtual environments
10
+ .venv/
11
+ venv/
12
+ env/
13
+
14
+ # Tooling caches
15
+ .pytest_cache/
16
+ .mypy_cache/
17
+ .ruff_cache/
18
+ .coverage
19
+ htmlcov/
20
+ coverage.xml
21
+
22
+ # Editors / OS
23
+ .vscode/
24
+ .idea/
25
+ .DS_Store
26
+ Thumbs.db
27
+
28
+ # The synced corpus snapshot (conformance/corpus/) IS committed — it makes
29
+ # fuaran-py standalone-testable offline and gives the drift guard
30
+ # (tests/test_corpus_sync.py) a committed baseline to pin against the authority.
31
+ # Re-sync + re-commit it whenever the authoritative corpus regenerates
32
+ # (python conformance/sync_corpus.py), per the §11 forward-coupling rule.
@@ -0,0 +1,307 @@
1
+ # CLAUDE.md — fuaran-py (Python reference implementation)
2
+
3
+ This repo is the **Python host of the Fuaran UI language** — a **co-equal sibling
4
+ to the F# (`Fuaran.UI`) and TypeScript (`@fuaran-ui/*`) tiers**, not merely a
5
+ codec. The target identity is a full authoring + rendering host: an ergonomic
6
+ `fuaran_py.ui` smart-constructor authoring surface (roadmap Phase 278), a tree-op
7
+ apply engine (279), a server-HTML renderer (`fuaran_py.renderer`, Phase 239 —
8
+ shipped) plus an interactive Pyodide client runtime (280), all conformant to the
9
+ shared wire format. What ships **today** is the floor: the canonical-JSON codec
10
+ (`decode_node` / `encode_node` / `decode_op` / `encode_op`), a pre-emit validator,
11
+ the corpus conformance harness, and the headless renderer; the authoring +
12
+ interactive surfaces are the Wave 35 co-equality expansion (Phases 278–281).
13
+
14
+ **Framing — load-bearing, do not regress.** The LLM's emission surface is the
15
+ **canonical JSON wire format, for every host**. The three language tiers (F#, TS,
16
+ Python) are **human-developer authoring surfaces** that produce that JSON; the AI
17
+ never authors host-language code — a structure-free baseline exists only as the
18
+ *thing to beat*, not a direction. Python being
19
+ the language AI orchestrators are written in is a reason it is *valuable*, not a
20
+ reason to make it a lesser, codec-only kind of artefact than F#/TS.
21
+
22
+ This repo sits alongside the `fuaran` (F#) and `fuaran-ts` (TypeScript) tiers as a co-equal
23
+ conformant host. Cross-repo development conventions (port allocation, formatting, language-baseline pinning) live at the maintainers' workspace level and are not shipped here.
24
+
25
+ ## Posture
26
+
27
+ - **Apache 2.0 from day one** — same posture as `fuaran-ts`, to make the
28
+ reference-implementation claim unambiguous.
29
+ - **Sibling reference implementation, not a transpile.** `fuaran-py` is built to
30
+ the language-neutral wire-format spec (`../fuaran-dotnet/docs/WIRE_FORMAT.md`) +
31
+ conformance corpus (`../wire-format-fixtures/`), not generated from the F# tier.
32
+ The Fable-Python build-vs-port evaluation that settled this is recorded in
33
+ [`docs/fable-python-decision.md`](docs/fable-python-decision.md).
34
+ - **Wire-format conformance is the stability contract.** The codec encodes /
35
+ decodes byte-identically against the shared corpus; it is certified the same
36
+ way the F# and TypeScript hosts are.
37
+ - **Dependency-light.** The runtime codec uses only the Python standard library.
38
+ Third-party packages appear only as dev tooling (`pytest` / `mypy` / `ruff`).
39
+
40
+ ## Language baseline
41
+
42
+ CPython **3.13+** (the workspace-chosen floor for this sibling; uses PEP 695
43
+ type parameters / `type` aliases). The Python analogue of the workspace's
44
+ F#-10/.NET-10 pinning.
45
+
46
+ ## Layout
47
+
48
+ ```
49
+ fuaran-py/
50
+ ├── src/fuaran_py/
51
+ │ ├── canonical.py # the canonical-JSON encoder (number form, key sort, escaping)
52
+ │ ├── model.py # the structural typed tree (Node / Obj / Arr)
53
+ │ ├── result.py # Ok / Err + the six DecodeError codes
54
+ │ ├── schema/ # decode_node / encode_node + the per-kind field schemas
55
+ │ ├── ops/ # decode_op / encode_op over the 11-op TreeOp algebra
56
+ │ ├── op_stream/ # hash-chained provenance log: StreamEntry envelope + SHA-256 chain + in-memory sink + replay
57
+ │ ├── validator/ # pre-emit, default-deny-by-shape structural validator
58
+ │ ├── ai_tools/ # AI-tools introspection: emittable-surface catalog + value-space + tool schemas + tree introspection + default-deny dispatch gate (Phase 237)
59
+ │ ├── conformance/ # corpus round-trip smoke harness + certification bridge + the cross-host fuzz-sample exchange (Phase 236)
60
+ │ ├── renderer/ # optional server-HTML renderer + sanitiser + reference CSS (Phase 239)
61
+ │ ├── style_observer/ # computed-style observer: pure flag tier + InMemory + Pyodide live read-back
62
+ │ └── theme_manifest/ # DTCG-compatible theme contract (tokens + role bindings + invariants)
63
+ ├── tests/ # pytest: number form, full-corpus round-trip + reject, validator
64
+ ├── docs/ # fable-python-decision.md (the build-vs-port decision record)
65
+ ├── pyproject.toml # dependency-light; dev extras = pytest / mypy / ruff
66
+ ├── LICENSE # Apache 2.0 + Diametrical Ltd copyright
67
+ └── run.ps1 # Stage-0 entry point — lint + format-check + type-check + test
68
+ ```
69
+
70
+ ## Build / verify pipeline
71
+
72
+ ```powershell
73
+ .\run.ps1 # provision .venv (first run) + ruff + mypy + pytest
74
+ .\run.ps1 -SkipInstall # run the gate against an already-provisioned .venv
75
+ ```
76
+
77
+ Or drive the tools directly inside the venv: `ruff check .`, `ruff format .`,
78
+ `mypy`, `pytest`.
79
+
80
+ ## Formatting mandate
81
+
82
+ The workspace formatting mandate (Fantomas for F#, Prettier for TS) maps here to
83
+ **ruff** — every commit is preceded by `ruff format` + `ruff check` over the
84
+ changed files. The CI gate is `ruff format --check` + `ruff check`.
85
+
86
+ ## Wire format
87
+
88
+ The canonical wire format is owned by the F# `fuaran` tier
89
+ (`../fuaran-dotnet/docs/WIRE_FORMAT.md`) with the workspace-level
90
+ `../wire-format-fixtures/` corpus as the executable conformance suite. `fuaran-py`
91
+ is one conformant host: it round-trips the corpus byte-for-byte and surfaces the
92
+ canonical reject code + path for every malformed fixture. The **forward-coupling
93
+ rule** (`WIRE_FORMAT.md` §11) means a new `NodeKind` / `Spec` / `TreeOp` /
94
+ `Binding` / `Action` case must move every host in one change — `fuaran-py` is now
95
+ one of those hosts.
96
+
97
+ ### Conformance coverage (v0 bootstrap)
98
+
99
+ The codec **runs the full four-family corpus green** — node round-trips, op
100
+ round-trips, rejects, and `lenient-accept` per WIRE_FORMAT §16's normative
101
+ block (fixture counts drift as the corpus grows —
102
+ `../wire-format-fixtures/manifest.json` is the authoritative enumeration).
103
+ The 2026-07-05 parity pass closed the measured divergences: the `Mount`
104
+ NodeKind decodes (typed scopeId/channel, structural inputs); the §16
105
+ bare-string TextSource shorthand is accepted and normalises to canonical
106
+ bytes; JSON null rejects in structured JVal positions at the null's exact
107
+ path (`_from_json_strict` — the §5 `Binding.Static` opaque seam deliberately
108
+ stays null-lenient); the op decoder gates the reserved `"<opaque>"` /
109
+ `"<closure>"` sentinels in `UpdateProp` values like the F# reference. Typed
110
+ field-level validation is implemented for the common kinds;
111
+ recognised-but-not-yet-typed kinds are accepted structurally (still
112
+ byte-exact on round-trip). The formal certification harness (offline corpus
113
+ snapshot + drift guard, schema validation, a language-agnostic certification
114
+ bridge, a CI leg, and generative parity) has since landed.
115
+
116
+ ### Within-host parity vs the cross-host exchange (do not conflate these)
117
+
118
+ Two generative floors sit above the curated corpus, and each proves something the
119
+ other cannot:
120
+
121
+ - **Within-host** — `tests/test_generative_parity.py`, ≥1000 `hypothesis` trees,
122
+ `encode(decode(encode x)) == encode x`. This host's canonical form is a fixed
123
+ point. Self-consistency only: a misreading of the spec that this host applies
124
+ *consistently* passes it every time.
125
+ - **Cross-host** — `fuaran_py.conformance.fuzz_exchange`, the fuzz-sample
126
+ exchange. Another host emits its canonical bytes for generated trees into
127
+ `<dir>/fsharp/`; this module decodes + re-encodes each through the Python codec,
128
+ asserts byte-identity, and writes **this** host's canonical output to
129
+ `<dir>/python/` so the sibling's `--check-fuzz-samples <dir> python` can check
130
+ the converse direction. One host's output, a different host's codec — the only
131
+ arrangement in which a shared misreading is visible.
132
+
133
+ The exchange needs a sibling host's emitter and so is hand-driven (the module
134
+ docstring carries the full command sequence); the within-host floor runs under a
135
+ plain `pytest`. `tests/test_fuzz_exchange.py` pins the *runner* — that it detects
136
+ a divergence, emits this host's set, and refuses a missing input set — using real
137
+ corpus payloads, so it needs no other toolchain.
138
+
139
+ The exchange's directory names (`fsharp` / `python`) are a cross-repo contract
140
+ with the sibling's `--check-fuzz-samples <dir> <host>` argument; renaming either
141
+ side silently un-wires it.
142
+
143
+ ### Decoder robustness fuzz (`fuaran_py.conformance.decoder_fuzz` + `tests/test_decoder_fuzz.py`)
144
+
145
+ A third generative floor, and the only one aimed at inputs a conformant emitter would never produce.
146
+ The refusal contract — decoding is TOTAL, so a malformed or hostile input yields a structured typed
147
+ error, never an exception and never a hang — is asserted against **generated** hostile input rather
148
+ than against the curated reject corpus alone. A curated corpus is evidence about the author's
149
+ imagination.
150
+
151
+ - **The bounded run IS the PR gate.** It landed in the suite `pytest` already runs, so no workflow
152
+ change was needed and none can silently switch it off.
153
+ - **The long run is a CLI**, and it writes its own machine-readable record:
154
+ `python -m fuaran_py.conformance.decoder_fuzz --long --iterations 250000 --evidence <file>`.
155
+ - **The go-red self-test is permanent, and so is its inverse.** Five mutants, one per invariant, plus
156
+ a pin that each is PARTIAL — a mutant that broke every input would make the harness look sensitive
157
+ while testing nothing.
158
+ - **The allocation invariant is split in two, deliberately.** The main stream carries a cheap
159
+ canonical-output amplification proxy; `test_pathological_inputs_stay_inside_an_allocation_budget`
160
+ spends `tracemalloc` on the pathological family, where an adversarial shape would actually
161
+ amplify. Neither half is the whole invariant, and the docstrings say which is which.
162
+ - **`RecursionError` is the escape this host most needs to see.** A recursive-descent decoder that
163
+ lets the interpreter's stack limit answer for it has no depth guard, whatever its §21 constant
164
+ says. `check` catches it and reports it as a counterexample rather than letting it propagate.
165
+ - **The generator is a SIBLING of the reference one, not a transpile.** Same five input families; a
166
+ different byte stream, necessarily — the reference alphabet carries lone surrogates a `str` cannot
167
+ encode to UTF-8 at all, and the module names that gap rather than closing it silently.
168
+ - **The `duplicate-key` mutator and the `NaN` / `Infinity` / `1e999` / `+1` tokens are generated
169
+ deliberately, and nothing here asserts which answer is right.** Those are §20 "Decode
170
+ determinism", landed PROPOSED and not yet ratified; crash-freedom on them is in scope, agreement
171
+ is not.
172
+
173
+ `fuaran_py.conformance.refusal_report` is the companion emitter: this host's refusal class for every
174
+ reject fixture, as JSON, for a cross-host runner that compares the hosts to each other rather than
175
+ each to the corpus in isolation.
176
+
177
+ ## Renderer (Phase 239)
178
+
179
+ `fuaran_py.renderer.render_html` walks a decoded `Node` tree and emits a
180
+ **body-fragment HTML string** carrying the reference `fuaran-*` class vocabulary,
181
+ so the byte-copied stylesheet styles it exactly as the F#/TS hosts style their
182
+ output. Server semantics mirror the F# SSR precedent: no runtime, no dispatch
183
+ (`Button` inert, `Link` a real `<a href>`), `Static` bindings resolve and the
184
+ rest placeholder to an em-dash, and a visualisation this host cannot paint
185
+ renders a deterministic placeholder. A **data-bound `DataGrid` renders its
186
+ rows** — the completeness posture; the declared boundary (a closure-projected
187
+ column, which cannot survive the wire) is written up in the README's
188
+ "Bound-grid rendering" section.
189
+
190
+ Two disciplines keep it honest:
191
+
192
+ - **Reference-CSS byte-copy.** `src/fuaran_py/renderer/content/fuaran-reference.css`
193
+ is a byte-for-byte copy of the F# canonical
194
+ (`../fuaran-dotnet/src/Fuaran.UI.Renderer/content/fuaran-reference.css`). A test
195
+ (`test_render_parity` / the byte-identical check) fails if the copy drifts when
196
+ the F# sibling is checked out alongside. Re-copy it in the same change-set as
197
+ any F#-side CSS change (the §11 forward-coupling rule now spans this host too).
198
+ - **Class-name vocabulary parity.** `tests/test_render_parity.py` extracts the
199
+ class vocabulary straight from the F# reference renderer source (`Render.fs` +
200
+ `Theme.fs`, literals + `sprintf "...-%s"` prefixes) and asserts every class the
201
+ Python renderer emits over the node corpus is in it — a cross-host parity lock,
202
+ the rendering analogue of the wire corpus. It skips when the F# sibling is
203
+ absent. **A new `NodeKind` / variant that changes the emitted class vocabulary
204
+ updates the renderer here in the same move that updates the codec.**
205
+
206
+ Sanitisation matches the F#/TS posture (`fuaran_py.renderer.sanitize` ports
207
+ `Sanitize.fs`): URL-scheme default-deny, `data-*`/`aria-*` attribute allowlist,
208
+ markdown escaped-first then swept. The `Custom` host-renderer registry is a host
209
+ trust boundary — the baseline ships no registry seam, so `Custom` renders an
210
+ inert labelled placeholder.
211
+
212
+ **Destination policy is AMBIENT on the render context, and defaults to deny.**
213
+ `Renderer.egress_policy` (`fuaran_py.renderer.egress`, the port of the reference
214
+ host's destination-policy section) is consulted by every `href` / `src` the
215
+ renderer emits — the `Link` node's `href` under the `HYPERLINK` class, the
216
+ `Image` node's `src` under `MEDIA`, and the whole markdown body through
217
+ `markdown.to_html_with_egress`. `render_html(..., egress_policy=…)` and
218
+ `FuaranRuntime(..., egress_policy=…)` are the declaration points; both default to
219
+ `DENY_NON_LOCAL_EGRESS`, so a host that declares nothing gets deny, and
220
+ `PERMISSIVE_EGRESS` is reachable only by that name.
221
+
222
+ Three disciplines follow, and the third is the one that decays quietly:
223
+
224
+ - **A new emission that carries a URL owes a policy consultation in the same
225
+ change.** `sanitize_url_or_blank` is the *floor*, not the seam — reaching for
226
+ it directly at a render call site re-opens the hole the ambient default closed.
227
+ Use `egress.sanitize_url_for_egress(self.egress_policy, <class>, url)` and
228
+ splice the returned attribute pairs onto the emitted element, last.
229
+ - **Never widen the default to make a test pass.** The corpus fixtures and the
230
+ ambient tests in `tests/test_egress_policy.py` are the falsifiers in both
231
+ directions; a fixture that needs an off-origin host names a policy.
232
+ - **`tests/test_markdown_corpus.py` runs TWO legs.** The seam leg calls
233
+ `to_html_with_egress` directly; the ambient leg renders a `Markdown` node
234
+ through `render_html` with **no policy named** for the `denyNonLocal` fixtures.
235
+ Keep both — the seam leg cannot detect a renderer that stopped reaching the
236
+ seam, which is precisely the state this host was in while the policy was merely
237
+ available.
238
+
239
+ The README's "Destination policy" section carries the host-facing contract and
240
+ the four declared shape differences from the reference host.
241
+
242
+ ## Op-stream (hash chain)
243
+
244
+ `fuaran_py.op_stream` is the Python host of the op-stream **hash-chained provenance
245
+ log** — the twin of the F# and TypeScript op-stream tiers. A stream's applied
246
+ `TreeOp` edits are an append-only sequence of `OpRecord` envelopes; a host-side
247
+ SHA-256 chain (`sha256(previousHash | payload)`) links them so the stream is
248
+ tamper-evident. The pre-image is byte-identical across hosts: the versioned
249
+ `StreamEntry` envelope leads with `{"v":2,…}` (the chain format version folded in
250
+ first), wrapped in the canonical delimited `{"seq":…,"actor":…,"op":…}` payload,
251
+ with the op encoded by the shared `fuaran_py.ops.encode_op` + `fuaran_py.canonical`
252
+ (never a re-implemented encoder). The module is **stdlib-only** — unlike the
253
+ Fable-constrained hosts it uses `hashlib.sha256` directly.
254
+
255
+ - **Conformance is the contract.** `tests/test_op_stream.py` loads the shared
256
+ `chain/chain-corpus.json` golden and asserts every computed chain hash equals the
257
+ committed value byte-for-byte — the same corpus the F# and TypeScript hosts
258
+ certify against. A mismatch is a bug in this host's encoder/chain, **never** the
259
+ corpus; do not regenerate the golden to make a test pass.
260
+ - **Version lock-step.** `CHAIN_FORMAT_VERSION` is pinned to the corpus `version`;
261
+ bump it in lock-step with the other hosts + the golden whenever the pre-image
262
+ formula, envelope shape, or hash function changes (the wire-format forward-coupling
263
+ rule now spans the chain envelope too).
264
+
265
+ ## Computed-style observer + theme manifest
266
+
267
+ `fuaran_py.style_observer` is the Python twin of `Fuaran.UI.StyleObserver`: it
268
+ reads back a rendered tree's resolved computed styles and derives a fixed
269
+ vocabulary of resolved-style flags (contrast-below-AA, invisible-text,
270
+ accent-indistinct, plus the four manifest-aware checks) the semantic-state channel
271
+ is blind to — as small typed facts, deterministically. The flag + observation
272
+ JSON encode is **byte-identical** to the F# and TypeScript hosts.
273
+
274
+ - `InMemoryStyleObserver` — fixture-driven, substrate-free (tests / headless).
275
+ - `BrowserStyleObserver` — reads **live** `getComputedStyle` under **Pyodide**
276
+ (CPython compiled to WASM running client-side in the browser — the Python
277
+ analogue of the F# Fable / TS browser observers). Browser-API access is behind
278
+ an injectable `BrowserDeps` (default: the `js` interop module, imported lazily so
279
+ the package stays stdlib-only at install time and importable under plain CPython;
280
+ tests inject a fake DOM). `connect()` wires a live `MutationObserver`
281
+ (Pyodide-only) so a theme toggle re-derives automatically.
282
+
283
+ `fuaran_py.theme_manifest` is the Python twin of `Fuaran.UI.ThemeManifest`: a
284
+ DTCG-compatible token model + semantic role bindings + quantified invariants
285
+ (per-role contrast floors, 60-30-10 usage budgets, motion voice). It is the
286
+ contract the observer's manifest-aware tier (`per_node_flags` /
287
+ `verify_usage_budgets`) verifies resolved style against. Both modules are
288
+ stdlib-only; the Pyodide-only `js` / `pyodide.ffi` imports are lazy and
289
+ import-guarded (the `#if FABLE_COMPILER` analogue). Manifest JSON encode + the F#
290
+ `ThemeBridge` (typed-`Theme` projector) are not yet ported (follow-up).
291
+
292
+ ## Cross-repo dependencies
293
+
294
+ No upstream dependency on any other sibling. At test time it reads the
295
+ workspace-relative corpus at `../wire-format-fixtures/` (skipped when absent, so
296
+ the repo is standalone-testable). It produces a Python package, not a NuGet pack
297
+ — the workspace `pack-all.ps1` treats it as a no-op.
298
+
299
+ ## Public vocabulary discipline
300
+
301
+ `fuaran-py` is OSS-public (Apache 2.0). Per the workspace OSS publication
302
+ boundary, **shipped artefacts** (source, README, package metadata) reference only
303
+ "the Fuaran UI wire format" generically — never a private sibling/package name,
304
+ commercial product names, or the strategic-command names. The specific banned
305
+ list lives in the workspace OSS publication boundary doc, not here. This
306
+ `CLAUDE.md` lives in the public repo, so it observes the same boundary — it names
307
+ no private sibling, package, product, or command.
@@ -0,0 +1,77 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ - Demonstrating empathy and kindness toward other people
21
+ - Being respectful of differing opinions, viewpoints, and experiences
22
+ - Giving and gracefully accepting constructive feedback
23
+ - Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ - Focusing on what is best not just for us as individuals, but for the overall
26
+ community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ - The use of sexualized language or imagery, and sexual attention or advances
31
+ of any kind
32
+ - Trolling, insulting or derogatory comments, and personal or political attacks
33
+ - Public or private harassment
34
+ - Publishing others' private information, such as a physical or email address,
35
+ without their explicit permission
36
+ - Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for
49
+ moderation decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+
56
+ ## Enforcement
57
+
58
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
59
+ reported to the community leaders responsible for enforcement at
60
+ andrew@fuaran.com. All complaints will be reviewed and investigated
61
+ promptly and fairly.
62
+
63
+ All community leaders are obligated to respect the privacy and security of the
64
+ reporter of any incident.
65
+
66
+ ## Attribution
67
+
68
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
69
+ version 2.1, available at
70
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
71
+
72
+ For answers to common questions about this code of conduct, see the FAQ at
73
+ [https://www.contributor-covenant.org/faq][FAQ].
74
+
75
+ [homepage]: https://www.contributor-covenant.org
76
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
77
+ [FAQ]: https://www.contributor-covenant.org/faq