mythik 0.0.1 → 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 (1111) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +4 -0
  3. package/README.md +97 -2
  4. package/dist/actions/dispatcher.d.ts +46 -0
  5. package/dist/actions/dispatcher.d.ts.map +1 -0
  6. package/dist/actions/dispatcher.js +366 -0
  7. package/dist/actions/dispatcher.js.map +1 -0
  8. package/dist/actions/middleware.d.ts +27 -0
  9. package/dist/actions/middleware.d.ts.map +1 -0
  10. package/dist/actions/middleware.js +37 -0
  11. package/dist/actions/middleware.js.map +1 -0
  12. package/dist/actions/transaction-engine.d.ts +13 -0
  13. package/dist/actions/transaction-engine.d.ts.map +1 -0
  14. package/dist/actions/transaction-engine.js +96 -0
  15. package/dist/actions/transaction-engine.js.map +1 -0
  16. package/dist/app/app-engine.d.ts +106 -0
  17. package/dist/app/app-engine.d.ts.map +1 -0
  18. package/dist/app/app-engine.js +413 -0
  19. package/dist/app/app-engine.js.map +1 -0
  20. package/dist/auth/cross-tab.d.ts +24 -0
  21. package/dist/auth/cross-tab.d.ts.map +1 -0
  22. package/dist/auth/cross-tab.js +117 -0
  23. package/dist/auth/cross-tab.js.map +1 -0
  24. package/dist/auth/engine.d.ts +16 -0
  25. package/dist/auth/engine.d.ts.map +1 -0
  26. package/dist/auth/engine.js +225 -0
  27. package/dist/auth/engine.js.map +1 -0
  28. package/dist/auth/persistence.d.ts +21 -0
  29. package/dist/auth/persistence.d.ts.map +1 -0
  30. package/dist/auth/persistence.js +97 -0
  31. package/dist/auth/persistence.js.map +1 -0
  32. package/dist/auth/providers/custom-jwt.d.ts +41 -0
  33. package/dist/auth/providers/custom-jwt.d.ts.map +1 -0
  34. package/dist/auth/providers/custom-jwt.js +165 -0
  35. package/dist/auth/providers/custom-jwt.js.map +1 -0
  36. package/dist/auth/providers/mock.d.ts +7 -0
  37. package/dist/auth/providers/mock.d.ts.map +1 -0
  38. package/dist/auth/providers/mock.js +52 -0
  39. package/dist/auth/providers/mock.js.map +1 -0
  40. package/dist/auth/providers/supabase.d.ts +90 -0
  41. package/dist/auth/providers/supabase.d.ts.map +1 -0
  42. package/dist/auth/providers/supabase.js +102 -0
  43. package/dist/auth/providers/supabase.js.map +1 -0
  44. package/dist/auth/rate-limiter.d.ts +29 -0
  45. package/dist/auth/rate-limiter.d.ts.map +1 -0
  46. package/dist/auth/rate-limiter.js +67 -0
  47. package/dist/auth/rate-limiter.js.map +1 -0
  48. package/dist/auth/refresh-engine.d.ts +25 -0
  49. package/dist/auth/refresh-engine.d.ts.map +1 -0
  50. package/dist/auth/refresh-engine.js +59 -0
  51. package/dist/auth/refresh-engine.js.map +1 -0
  52. package/dist/auth/types.d.ts +89 -0
  53. package/dist/auth/types.d.ts.map +1 -0
  54. package/dist/auth/types.js +2 -0
  55. package/dist/auth/types.js.map +1 -0
  56. package/dist/contract/endpoint-map.d.ts +20 -0
  57. package/dist/contract/endpoint-map.d.ts.map +1 -0
  58. package/dist/contract/endpoint-map.js +57 -0
  59. package/dist/contract/endpoint-map.js.map +1 -0
  60. package/dist/contract/engine.d.ts +12 -0
  61. package/dist/contract/engine.d.ts.map +1 -0
  62. package/dist/contract/engine.js +80 -0
  63. package/dist/contract/engine.js.map +1 -0
  64. package/dist/contract/extractor.d.ts +7 -0
  65. package/dist/contract/extractor.d.ts.map +1 -0
  66. package/dist/contract/extractor.js +133 -0
  67. package/dist/contract/extractor.js.map +1 -0
  68. package/dist/contract/index.d.ts +4 -0
  69. package/dist/contract/index.d.ts.map +1 -0
  70. package/dist/contract/index.js +2 -0
  71. package/dist/contract/index.js.map +1 -0
  72. package/dist/contract/matcher.d.ts +13 -0
  73. package/dist/contract/matcher.d.ts.map +1 -0
  74. package/dist/contract/matcher.js +57 -0
  75. package/dist/contract/matcher.js.map +1 -0
  76. package/dist/contract/rules/endpoints-exist.d.ts +3 -0
  77. package/dist/contract/rules/endpoints-exist.d.ts.map +1 -0
  78. package/dist/contract/rules/endpoints-exist.js +29 -0
  79. package/dist/contract/rules/endpoints-exist.js.map +1 -0
  80. package/dist/contract/rules/fields-valid.d.ts +3 -0
  81. package/dist/contract/rules/fields-valid.d.ts.map +1 -0
  82. package/dist/contract/rules/fields-valid.js +39 -0
  83. package/dist/contract/rules/fields-valid.js.map +1 -0
  84. package/dist/contract/rules/params-match.d.ts +3 -0
  85. package/dist/contract/rules/params-match.d.ts.map +1 -0
  86. package/dist/contract/rules/params-match.js +40 -0
  87. package/dist/contract/rules/params-match.js.map +1 -0
  88. package/dist/contract/rules/permissions-consistent.d.ts +3 -0
  89. package/dist/contract/rules/permissions-consistent.d.ts.map +1 -0
  90. package/dist/contract/rules/permissions-consistent.js +52 -0
  91. package/dist/contract/rules/permissions-consistent.js.map +1 -0
  92. package/dist/contract/types.d.ts +66 -0
  93. package/dist/contract/types.d.ts.map +1 -0
  94. package/dist/contract/types.js +2 -0
  95. package/dist/contract/types.js.map +1 -0
  96. package/dist/data/data-sources.d.ts +26 -0
  97. package/dist/data/data-sources.d.ts.map +1 -0
  98. package/dist/data/data-sources.js +218 -0
  99. package/dist/data/data-sources.js.map +1 -0
  100. package/dist/data/fetch.d.ts +29 -0
  101. package/dist/data/fetch.d.ts.map +1 -0
  102. package/dist/data/fetch.js +63 -0
  103. package/dist/data/fetch.js.map +1 -0
  104. package/dist/data/offline.d.ts +29 -0
  105. package/dist/data/offline.d.ts.map +1 -0
  106. package/dist/data/offline.js +48 -0
  107. package/dist/data/offline.js.map +1 -0
  108. package/dist/data/realtime.d.ts +21 -0
  109. package/dist/data/realtime.d.ts.map +1 -0
  110. package/dist/data/realtime.js +40 -0
  111. package/dist/data/realtime.js.map +1 -0
  112. package/dist/derive/evaluator.d.ts +19 -0
  113. package/dist/derive/evaluator.d.ts.map +1 -0
  114. package/dist/derive/evaluator.js +59 -0
  115. package/dist/derive/evaluator.js.map +1 -0
  116. package/dist/derive/topo-sort.d.ts +10 -0
  117. package/dist/derive/topo-sort.d.ts.map +1 -0
  118. package/dist/derive/topo-sort.js +36 -0
  119. package/dist/derive/topo-sort.js.map +1 -0
  120. package/dist/design/animation/cascade-types.d.ts +23 -0
  121. package/dist/design/animation/cascade-types.d.ts.map +1 -0
  122. package/dist/design/animation/cascade-types.js +2 -0
  123. package/dist/design/animation/cascade-types.js.map +1 -0
  124. package/dist/design/animation/cascade.d.ts +4 -0
  125. package/dist/design/animation/cascade.d.ts.map +1 -0
  126. package/dist/design/animation/cascade.js +73 -0
  127. package/dist/design/animation/cascade.js.map +1 -0
  128. package/dist/design/animation/css-keyframes.d.ts +8 -0
  129. package/dist/design/animation/css-keyframes.d.ts.map +1 -0
  130. package/dist/design/animation/css-keyframes.js +72 -0
  131. package/dist/design/animation/css-keyframes.js.map +1 -0
  132. package/dist/design/animation/index.d.ts +14 -0
  133. package/dist/design/animation/index.d.ts.map +1 -0
  134. package/dist/design/animation/index.js +9 -0
  135. package/dist/design/animation/index.js.map +1 -0
  136. package/dist/design/animation/keyframes-builder.d.ts +40 -0
  137. package/dist/design/animation/keyframes-builder.d.ts.map +1 -0
  138. package/dist/design/animation/keyframes-builder.js +140 -0
  139. package/dist/design/animation/keyframes-builder.js.map +1 -0
  140. package/dist/design/animation/reanimated-spec.d.ts +16 -0
  141. package/dist/design/animation/reanimated-spec.d.ts.map +1 -0
  142. package/dist/design/animation/reanimated-spec.js +162 -0
  143. package/dist/design/animation/reanimated-spec.js.map +1 -0
  144. package/dist/design/animation/reduced-motion.d.ts +3 -0
  145. package/dist/design/animation/reduced-motion.d.ts.map +1 -0
  146. package/dist/design/animation/reduced-motion.js +54 -0
  147. package/dist/design/animation/reduced-motion.js.map +1 -0
  148. package/dist/design/animation/resolver.d.ts +3 -0
  149. package/dist/design/animation/resolver.d.ts.map +1 -0
  150. package/dist/design/animation/resolver.js +86 -0
  151. package/dist/design/animation/resolver.js.map +1 -0
  152. package/dist/design/animation/types.d.ts +109 -0
  153. package/dist/design/animation/types.d.ts.map +1 -0
  154. package/dist/design/animation/types.js +7 -0
  155. package/dist/design/animation/types.js.map +1 -0
  156. package/dist/design/animation/validator.d.ts +44 -0
  157. package/dist/design/animation/validator.d.ts.map +1 -0
  158. package/dist/design/animation/validator.js +169 -0
  159. package/dist/design/animation/validator.js.map +1 -0
  160. package/dist/design/background/blobs/catalog.d.ts +10 -0
  161. package/dist/design/background/blobs/catalog.d.ts.map +1 -0
  162. package/dist/design/background/blobs/catalog.js +63 -0
  163. package/dist/design/background/blobs/catalog.js.map +1 -0
  164. package/dist/design/background/blobs/index.d.ts +4 -0
  165. package/dist/design/background/blobs/index.d.ts.map +1 -0
  166. package/dist/design/background/blobs/index.js +5 -0
  167. package/dist/design/background/blobs/index.js.map +1 -0
  168. package/dist/design/background/blobs/resolver.d.ts +16 -0
  169. package/dist/design/background/blobs/resolver.d.ts.map +1 -0
  170. package/dist/design/background/blobs/resolver.js +301 -0
  171. package/dist/design/background/blobs/resolver.js.map +1 -0
  172. package/dist/design/background/blobs/types.d.ts +112 -0
  173. package/dist/design/background/blobs/types.d.ts.map +1 -0
  174. package/dist/design/background/blobs/types.js +27 -0
  175. package/dist/design/background/blobs/types.js.map +1 -0
  176. package/dist/design/background/grain.d.ts +3 -0
  177. package/dist/design/background/grain.d.ts.map +1 -0
  178. package/dist/design/background/grain.js +23 -0
  179. package/dist/design/background/grain.js.map +1 -0
  180. package/dist/design/background/index.d.ts +8 -0
  181. package/dist/design/background/index.d.ts.map +1 -0
  182. package/dist/design/background/index.js +8 -0
  183. package/dist/design/background/index.js.map +1 -0
  184. package/dist/design/background/layers.d.ts +3 -0
  185. package/dist/design/background/layers.d.ts.map +1 -0
  186. package/dist/design/background/layers.js +23 -0
  187. package/dist/design/background/layers.js.map +1 -0
  188. package/dist/design/background/patterns/chevron.d.ts +8 -0
  189. package/dist/design/background/patterns/chevron.d.ts.map +1 -0
  190. package/dist/design/background/patterns/chevron.js +10 -0
  191. package/dist/design/background/patterns/chevron.js.map +1 -0
  192. package/dist/design/background/patterns/crosshatch.d.ts +8 -0
  193. package/dist/design/background/patterns/crosshatch.d.ts.map +1 -0
  194. package/dist/design/background/patterns/crosshatch.js +12 -0
  195. package/dist/design/background/patterns/crosshatch.js.map +1 -0
  196. package/dist/design/background/patterns/diagonal.d.ts +8 -0
  197. package/dist/design/background/patterns/diagonal.d.ts.map +1 -0
  198. package/dist/design/background/patterns/diagonal.js +7 -0
  199. package/dist/design/background/patterns/diagonal.js.map +1 -0
  200. package/dist/design/background/patterns/dots.d.ts +7 -0
  201. package/dist/design/background/patterns/dots.d.ts.map +1 -0
  202. package/dist/design/background/patterns/dots.js +9 -0
  203. package/dist/design/background/patterns/dots.js.map +1 -0
  204. package/dist/design/background/patterns/grid.d.ts +7 -0
  205. package/dist/design/background/patterns/grid.d.ts.map +1 -0
  206. package/dist/design/background/patterns/grid.js +8 -0
  207. package/dist/design/background/patterns/grid.js.map +1 -0
  208. package/dist/design/background/patterns/index.d.ts +8 -0
  209. package/dist/design/background/patterns/index.d.ts.map +1 -0
  210. package/dist/design/background/patterns/index.js +8 -0
  211. package/dist/design/background/patterns/index.js.map +1 -0
  212. package/dist/design/background/patterns/iso.d.ts +7 -0
  213. package/dist/design/background/patterns/iso.d.ts.map +1 -0
  214. package/dist/design/background/patterns/iso.js +11 -0
  215. package/dist/design/background/patterns/iso.js.map +1 -0
  216. package/dist/design/background/patterns/resolver.d.ts +3 -0
  217. package/dist/design/background/patterns/resolver.d.ts.map +1 -0
  218. package/dist/design/background/patterns/resolver.js +56 -0
  219. package/dist/design/background/patterns/resolver.js.map +1 -0
  220. package/dist/design/background/primitives/gradient.d.ts +3 -0
  221. package/dist/design/background/primitives/gradient.d.ts.map +1 -0
  222. package/dist/design/background/primitives/gradient.js +68 -0
  223. package/dist/design/background/primitives/gradient.js.map +1 -0
  224. package/dist/design/background/primitives/image.d.ts +3 -0
  225. package/dist/design/background/primitives/image.d.ts.map +1 -0
  226. package/dist/design/background/primitives/image.js +12 -0
  227. package/dist/design/background/primitives/image.js.map +1 -0
  228. package/dist/design/background/primitives/index.d.ts +4 -0
  229. package/dist/design/background/primitives/index.d.ts.map +1 -0
  230. package/dist/design/background/primitives/index.js +4 -0
  231. package/dist/design/background/primitives/index.js.map +1 -0
  232. package/dist/design/background/primitives/solid.d.ts +8 -0
  233. package/dist/design/background/primitives/solid.d.ts.map +1 -0
  234. package/dist/design/background/primitives/solid.js +15 -0
  235. package/dist/design/background/primitives/solid.js.map +1 -0
  236. package/dist/design/background/resolver.d.ts +3 -0
  237. package/dist/design/background/resolver.d.ts.map +1 -0
  238. package/dist/design/background/resolver.js +20 -0
  239. package/dist/design/background/resolver.js.map +1 -0
  240. package/dist/design/background/sanitizer.d.ts +2 -0
  241. package/dist/design/background/sanitizer.d.ts.map +1 -0
  242. package/dist/design/background/sanitizer.js +54 -0
  243. package/dist/design/background/sanitizer.js.map +1 -0
  244. package/dist/design/deep-tokens.d.ts +125 -0
  245. package/dist/design/deep-tokens.d.ts.map +1 -0
  246. package/dist/design/deep-tokens.js +115 -0
  247. package/dist/design/deep-tokens.js.map +1 -0
  248. package/dist/design/dna.d.ts +7 -0
  249. package/dist/design/dna.d.ts.map +1 -0
  250. package/dist/design/dna.js +210 -0
  251. package/dist/design/dna.js.map +1 -0
  252. package/dist/design/identity/color.d.ts +8 -0
  253. package/dist/design/identity/color.d.ts.map +1 -0
  254. package/dist/design/identity/color.js +64 -0
  255. package/dist/design/identity/color.js.map +1 -0
  256. package/dist/design/identity/elevation.d.ts +8 -0
  257. package/dist/design/identity/elevation.d.ts.map +1 -0
  258. package/dist/design/identity/elevation.js +31 -0
  259. package/dist/design/identity/elevation.js.map +1 -0
  260. package/dist/design/identity/index.d.ts +12 -0
  261. package/dist/design/identity/index.d.ts.map +1 -0
  262. package/dist/design/identity/index.js +14 -0
  263. package/dist/design/identity/index.js.map +1 -0
  264. package/dist/design/identity/shape.d.ts +4 -0
  265. package/dist/design/identity/shape.d.ts.map +1 -0
  266. package/dist/design/identity/shape.js +23 -0
  267. package/dist/design/identity/shape.js.map +1 -0
  268. package/dist/design/identity/surface.d.ts +18 -0
  269. package/dist/design/identity/surface.d.ts.map +1 -0
  270. package/dist/design/identity/surface.js +125 -0
  271. package/dist/design/identity/surface.js.map +1 -0
  272. package/dist/design/identity/types.d.ts +280 -0
  273. package/dist/design/identity/types.d.ts.map +1 -0
  274. package/dist/design/identity/types.js +21 -0
  275. package/dist/design/identity/types.js.map +1 -0
  276. package/dist/design/identity/typography.d.ts +7 -0
  277. package/dist/design/identity/typography.d.ts.map +1 -0
  278. package/dist/design/identity/typography.js +42 -0
  279. package/dist/design/identity/typography.js.map +1 -0
  280. package/dist/design/identity-resolver.d.ts +15 -0
  281. package/dist/design/identity-resolver.d.ts.map +1 -0
  282. package/dist/design/identity-resolver.js +52 -0
  283. package/dist/design/identity-resolver.js.map +1 -0
  284. package/dist/design/oklch.d.ts +10 -0
  285. package/dist/design/oklch.d.ts.map +1 -0
  286. package/dist/design/oklch.js +61 -0
  287. package/dist/design/oklch.js.map +1 -0
  288. package/dist/design/palette.d.ts +26 -0
  289. package/dist/design/palette.d.ts.map +1 -0
  290. package/dist/design/palette.js +73 -0
  291. package/dist/design/palette.js.map +1 -0
  292. package/dist/design/presets.d.ts +18 -0
  293. package/dist/design/presets.d.ts.map +1 -0
  294. package/dist/design/presets.js +2 -0
  295. package/dist/design/presets.js.map +1 -0
  296. package/dist/design/recipes/animations.d.ts +11 -0
  297. package/dist/design/recipes/animations.d.ts.map +1 -0
  298. package/dist/design/recipes/animations.js +180 -0
  299. package/dist/design/recipes/animations.js.map +1 -0
  300. package/dist/design/recipes/backgrounds.d.ts +3 -0
  301. package/dist/design/recipes/backgrounds.d.ts.map +1 -0
  302. package/dist/design/recipes/backgrounds.js +152 -0
  303. package/dist/design/recipes/backgrounds.js.map +1 -0
  304. package/dist/design/recipes/index.d.ts +2 -0
  305. package/dist/design/recipes/index.d.ts.map +1 -0
  306. package/dist/design/recipes/index.js +2 -0
  307. package/dist/design/recipes/index.js.map +1 -0
  308. package/dist/design/surface-to-css.d.ts +57 -0
  309. package/dist/design/surface-to-css.d.ts.map +1 -0
  310. package/dist/design/surface-to-css.js +130 -0
  311. package/dist/design/surface-to-css.js.map +1 -0
  312. package/dist/design/surface-to-rn.d.ts +57 -0
  313. package/dist/design/surface-to-rn.d.ts.map +1 -0
  314. package/dist/design/surface-to-rn.js +133 -0
  315. package/dist/design/surface-to-rn.js.map +1 -0
  316. package/dist/design/tokens.d.ts +67 -0
  317. package/dist/design/tokens.d.ts.map +1 -0
  318. package/dist/design/tokens.js +36 -0
  319. package/dist/design/tokens.js.map +1 -0
  320. package/dist/device/context.d.ts +13 -0
  321. package/dist/device/context.d.ts.map +1 -0
  322. package/dist/device/context.js +2 -0
  323. package/dist/device/context.js.map +1 -0
  324. package/dist/editor-session/clone.d.ts +4 -0
  325. package/dist/editor-session/clone.d.ts.map +1 -0
  326. package/dist/editor-session/clone.js +55 -0
  327. package/dist/editor-session/clone.js.map +1 -0
  328. package/dist/editor-session/engine.d.ts +21 -0
  329. package/dist/editor-session/engine.d.ts.map +1 -0
  330. package/dist/editor-session/engine.js +375 -0
  331. package/dist/editor-session/engine.js.map +1 -0
  332. package/dist/editor-session/persistence.d.ts +8 -0
  333. package/dist/editor-session/persistence.d.ts.map +1 -0
  334. package/dist/editor-session/persistence.js +89 -0
  335. package/dist/editor-session/persistence.js.map +1 -0
  336. package/dist/editor-session/types.d.ts +90 -0
  337. package/dist/editor-session/types.d.ts.map +1 -0
  338. package/dist/editor-session/types.js +2 -0
  339. package/dist/editor-session/types.js.map +1 -0
  340. package/dist/editor-session/validators.d.ts +5 -0
  341. package/dist/editor-session/validators.d.ts.map +1 -0
  342. package/dist/editor-session/validators.js +106 -0
  343. package/dist/editor-session/validators.js.map +1 -0
  344. package/dist/elements/composer.d.ts +109 -0
  345. package/dist/elements/composer.d.ts.map +1 -0
  346. package/dist/elements/composer.js +129 -0
  347. package/dist/elements/composer.js.map +1 -0
  348. package/dist/export/csv.d.ts +3 -0
  349. package/dist/export/csv.d.ts.map +1 -0
  350. package/dist/export/csv.js +16 -0
  351. package/dist/export/csv.js.map +1 -0
  352. package/dist/export/download.d.ts +2 -0
  353. package/dist/export/download.d.ts.map +1 -0
  354. package/dist/export/download.js +13 -0
  355. package/dist/export/download.js.map +1 -0
  356. package/dist/export/format.d.ts +3 -0
  357. package/dist/export/format.d.ts.map +1 -0
  358. package/dist/export/format.js +43 -0
  359. package/dist/export/format.js.map +1 -0
  360. package/dist/export/types.d.ts +22 -0
  361. package/dist/export/types.d.ts.map +1 -0
  362. package/dist/export/types.js +2 -0
  363. package/dist/export/types.js.map +1 -0
  364. package/dist/expressions/deep-resolve.d.ts +4 -0
  365. package/dist/expressions/deep-resolve.d.ts.map +1 -0
  366. package/dist/expressions/deep-resolve.js +20 -0
  367. package/dist/expressions/deep-resolve.js.map +1 -0
  368. package/dist/expressions/handlers/array.d.ts +19 -0
  369. package/dist/expressions/handlers/array.d.ts.map +1 -0
  370. package/dist/expressions/handlers/array.js +161 -0
  371. package/dist/expressions/handlers/array.js.map +1 -0
  372. package/dist/expressions/handlers/auth.d.ts +13 -0
  373. package/dist/expressions/handlers/auth.d.ts.map +1 -0
  374. package/dist/expressions/handlers/auth.js +90 -0
  375. package/dist/expressions/handlers/auth.js.map +1 -0
  376. package/dist/expressions/handlers/bind.d.ts +22 -0
  377. package/dist/expressions/handlers/bind.d.ts.map +1 -0
  378. package/dist/expressions/handlers/bind.js +57 -0
  379. package/dist/expressions/handlers/bind.js.map +1 -0
  380. package/dist/expressions/handlers/breakpoint.d.ts +10 -0
  381. package/dist/expressions/handlers/breakpoint.d.ts.map +1 -0
  382. package/dist/expressions/handlers/breakpoint.js +39 -0
  383. package/dist/expressions/handlers/breakpoint.js.map +1 -0
  384. package/dist/expressions/handlers/computed.d.ts +3 -0
  385. package/dist/expressions/handlers/computed.d.ts.map +1 -0
  386. package/dist/expressions/handlers/computed.js +20 -0
  387. package/dist/expressions/handlers/computed.js.map +1 -0
  388. package/dist/expressions/handlers/cond.d.ts +3 -0
  389. package/dist/expressions/handlers/cond.d.ts.map +1 -0
  390. package/dist/expressions/handlers/cond.js +57 -0
  391. package/dist/expressions/handlers/cond.js.map +1 -0
  392. package/dist/expressions/handlers/date.d.ts +14 -0
  393. package/dist/expressions/handlers/date.d.ts.map +1 -0
  394. package/dist/expressions/handlers/date.js +95 -0
  395. package/dist/expressions/handlers/date.js.map +1 -0
  396. package/dist/expressions/handlers/format.d.ts +19 -0
  397. package/dist/expressions/handlers/format.d.ts.map +1 -0
  398. package/dist/expressions/handlers/format.js +93 -0
  399. package/dist/expressions/handlers/format.js.map +1 -0
  400. package/dist/expressions/handlers/group.d.ts +25 -0
  401. package/dist/expressions/handlers/group.d.ts.map +1 -0
  402. package/dist/expressions/handlers/group.js +85 -0
  403. package/dist/expressions/handlers/group.js.map +1 -0
  404. package/dist/expressions/handlers/i18n.d.ts +8 -0
  405. package/dist/expressions/handlers/i18n.d.ts.map +1 -0
  406. package/dist/expressions/handlers/i18n.js +35 -0
  407. package/dist/expressions/handlers/i18n.js.map +1 -0
  408. package/dist/expressions/handlers/index.d.ts +4 -0
  409. package/dist/expressions/handlers/index.d.ts.map +1 -0
  410. package/dist/expressions/handlers/index.js +52 -0
  411. package/dist/expressions/handlers/index.js.map +1 -0
  412. package/dist/expressions/handlers/let.d.ts +4 -0
  413. package/dist/expressions/handlers/let.d.ts.map +1 -0
  414. package/dist/expressions/handlers/let.js +36 -0
  415. package/dist/expressions/handlers/let.js.map +1 -0
  416. package/dist/expressions/handlers/logic.d.ts +27 -0
  417. package/dist/expressions/handlers/logic.d.ts.map +1 -0
  418. package/dist/expressions/handlers/logic.js +52 -0
  419. package/dist/expressions/handlers/logic.js.map +1 -0
  420. package/dist/expressions/handlers/math.d.ts +13 -0
  421. package/dist/expressions/handlers/math.d.ts.map +1 -0
  422. package/dist/expressions/handlers/math.js +58 -0
  423. package/dist/expressions/handlers/math.js.map +1 -0
  424. package/dist/expressions/handlers/platform.d.ts +13 -0
  425. package/dist/expressions/handlers/platform.d.ts.map +1 -0
  426. package/dist/expressions/handlers/platform.js +37 -0
  427. package/dist/expressions/handlers/platform.js.map +1 -0
  428. package/dist/expressions/handlers/prop.d.ts +10 -0
  429. package/dist/expressions/handlers/prop.d.ts.map +1 -0
  430. package/dist/expressions/handlers/prop.js +18 -0
  431. package/dist/expressions/handlers/prop.js.map +1 -0
  432. package/dist/expressions/handlers/selection.d.ts +10 -0
  433. package/dist/expressions/handlers/selection.d.ts.map +1 -0
  434. package/dist/expressions/handlers/selection.js +33 -0
  435. package/dist/expressions/handlers/selection.js.map +1 -0
  436. package/dist/expressions/handlers/state.d.ts +3 -0
  437. package/dist/expressions/handlers/state.d.ts.map +1 -0
  438. package/dist/expressions/handlers/state.js +8 -0
  439. package/dist/expressions/handlers/state.js.map +1 -0
  440. package/dist/expressions/handlers/switch.d.ts +15 -0
  441. package/dist/expressions/handlers/switch.d.ts.map +1 -0
  442. package/dist/expressions/handlers/switch.js +31 -0
  443. package/dist/expressions/handlers/switch.js.map +1 -0
  444. package/dist/expressions/handlers/template.d.ts +3 -0
  445. package/dist/expressions/handlers/template.d.ts.map +1 -0
  446. package/dist/expressions/handlers/template.js +23 -0
  447. package/dist/expressions/handlers/template.js.map +1 -0
  448. package/dist/expressions/handlers/token.d.ts +3 -0
  449. package/dist/expressions/handlers/token.d.ts.map +1 -0
  450. package/dist/expressions/handlers/token.js +40 -0
  451. package/dist/expressions/handlers/token.js.map +1 -0
  452. package/dist/expressions/handlers/unique-id.d.ts +11 -0
  453. package/dist/expressions/handlers/unique-id.d.ts.map +1 -0
  454. package/dist/expressions/handlers/unique-id.js +52 -0
  455. package/dist/expressions/handlers/unique-id.js.map +1 -0
  456. package/dist/expressions/registry.d.ts +8 -0
  457. package/dist/expressions/registry.d.ts.map +1 -0
  458. package/dist/expressions/registry.js +35 -0
  459. package/dist/expressions/registry.js.map +1 -0
  460. package/dist/expressions/resolver.d.ts +15 -0
  461. package/dist/expressions/resolver.d.ts.map +1 -0
  462. package/dist/expressions/resolver.js +56 -0
  463. package/dist/expressions/resolver.js.map +1 -0
  464. package/dist/factory.d.ts +56 -0
  465. package/dist/factory.d.ts.map +1 -0
  466. package/dist/factory.js +265 -0
  467. package/dist/factory.js.map +1 -0
  468. package/dist/fetch/framework-fetch.d.ts +12 -0
  469. package/dist/fetch/framework-fetch.d.ts.map +1 -0
  470. package/dist/fetch/framework-fetch.js +36 -0
  471. package/dist/fetch/framework-fetch.js.map +1 -0
  472. package/dist/fetch/interceptors/auth.d.ts +19 -0
  473. package/dist/fetch/interceptors/auth.d.ts.map +1 -0
  474. package/dist/fetch/interceptors/auth.js +66 -0
  475. package/dist/fetch/interceptors/auth.js.map +1 -0
  476. package/dist/fetch/interceptors/logging.d.ts +8 -0
  477. package/dist/fetch/interceptors/logging.d.ts.map +1 -0
  478. package/dist/fetch/interceptors/logging.js +40 -0
  479. package/dist/fetch/interceptors/logging.js.map +1 -0
  480. package/dist/fetch/interceptors/retry.d.ts +20 -0
  481. package/dist/fetch/interceptors/retry.d.ts.map +1 -0
  482. package/dist/fetch/interceptors/retry.js +34 -0
  483. package/dist/fetch/interceptors/retry.js.map +1 -0
  484. package/dist/fetch/interceptors/timeout.d.ts +7 -0
  485. package/dist/fetch/interceptors/timeout.d.ts.map +1 -0
  486. package/dist/fetch/interceptors/timeout.js +20 -0
  487. package/dist/fetch/interceptors/timeout.js.map +1 -0
  488. package/dist/fetch/types.d.ts +30 -0
  489. package/dist/fetch/types.d.ts.map +1 -0
  490. package/dist/fetch/types.js +2 -0
  491. package/dist/fetch/types.js.map +1 -0
  492. package/dist/forms/engine.d.ts +3 -0
  493. package/dist/forms/engine.d.ts.map +1 -0
  494. package/dist/forms/engine.js +167 -0
  495. package/dist/forms/engine.js.map +1 -0
  496. package/dist/forms/types.d.ts +30 -0
  497. package/dist/forms/types.d.ts.map +1 -0
  498. package/dist/forms/types.js +2 -0
  499. package/dist/forms/types.js.map +1 -0
  500. package/dist/i18n/engine.d.ts +15 -0
  501. package/dist/i18n/engine.d.ts.map +1 -0
  502. package/dist/i18n/engine.js +61 -0
  503. package/dist/i18n/engine.js.map +1 -0
  504. package/dist/index.d.ts +161 -0
  505. package/dist/index.d.ts.map +1 -0
  506. package/dist/index.js +106 -0
  507. package/dist/index.js.map +1 -0
  508. package/dist/interactions/data-operations.d.ts +51 -0
  509. package/dist/interactions/data-operations.d.ts.map +1 -0
  510. package/dist/interactions/data-operations.js +64 -0
  511. package/dist/interactions/data-operations.js.map +1 -0
  512. package/dist/interactions/drag-drop.d.ts +14 -0
  513. package/dist/interactions/drag-drop.d.ts.map +1 -0
  514. package/dist/interactions/drag-drop.js +35 -0
  515. package/dist/interactions/drag-drop.js.map +1 -0
  516. package/dist/interactions/export.d.ts +24 -0
  517. package/dist/interactions/export.d.ts.map +1 -0
  518. package/dist/interactions/export.js +44 -0
  519. package/dist/interactions/export.js.map +1 -0
  520. package/dist/interactions/history.d.ts +16 -0
  521. package/dist/interactions/history.d.ts.map +1 -0
  522. package/dist/interactions/history.js +52 -0
  523. package/dist/interactions/history.js.map +1 -0
  524. package/dist/motion/engine.d.ts +47 -0
  525. package/dist/motion/engine.d.ts.map +1 -0
  526. package/dist/motion/engine.js +81 -0
  527. package/dist/motion/engine.js.map +1 -0
  528. package/dist/navigation/router.d.ts +36 -0
  529. package/dist/navigation/router.d.ts.map +1 -0
  530. package/dist/navigation/router.js +51 -0
  531. package/dist/navigation/router.js.map +1 -0
  532. package/dist/permissions/evaluator.d.ts +15 -0
  533. package/dist/permissions/evaluator.d.ts.map +1 -0
  534. package/dist/permissions/evaluator.js +32 -0
  535. package/dist/permissions/evaluator.js.map +1 -0
  536. package/dist/plugins/loader.d.ts +30 -0
  537. package/dist/plugins/loader.d.ts.map +1 -0
  538. package/dist/plugins/loader.js +87 -0
  539. package/dist/plugins/loader.js.map +1 -0
  540. package/dist/reference/generator.d.ts +25 -0
  541. package/dist/reference/generator.d.ts.map +1 -0
  542. package/dist/reference/generator.js +808 -0
  543. package/dist/reference/generator.js.map +1 -0
  544. package/dist/renderer/deps.d.ts +24 -0
  545. package/dist/renderer/deps.d.ts.map +1 -0
  546. package/dist/renderer/deps.js +150 -0
  547. package/dist/renderer/deps.js.map +1 -0
  548. package/dist/renderer/engine.d.ts +15 -0
  549. package/dist/renderer/engine.d.ts.map +1 -0
  550. package/dist/renderer/engine.js +1097 -0
  551. package/dist/renderer/engine.js.map +1 -0
  552. package/dist/renderer/lazy-paths.d.ts +14 -0
  553. package/dist/renderer/lazy-paths.d.ts.map +1 -0
  554. package/dist/renderer/lazy-paths.js +63 -0
  555. package/dist/renderer/lazy-paths.js.map +1 -0
  556. package/dist/renderer/prop-schemas.d.ts +17 -0
  557. package/dist/renderer/prop-schemas.d.ts.map +1 -0
  558. package/dist/renderer/prop-schemas.js +81 -0
  559. package/dist/renderer/prop-schemas.js.map +1 -0
  560. package/dist/renderer/registry.d.ts +10 -0
  561. package/dist/renderer/registry.d.ts.map +1 -0
  562. package/dist/renderer/registry.js +22 -0
  563. package/dist/renderer/registry.js.map +1 -0
  564. package/dist/renderer/variants.d.ts +54 -0
  565. package/dist/renderer/variants.d.ts.map +1 -0
  566. package/dist/renderer/variants.js +105 -0
  567. package/dist/renderer/variants.js.map +1 -0
  568. package/dist/runtime/mount-spec-runtime.d.ts +59 -0
  569. package/dist/runtime/mount-spec-runtime.d.ts.map +1 -0
  570. package/dist/runtime/mount-spec-runtime.js +73 -0
  571. package/dist/runtime/mount-spec-runtime.js.map +1 -0
  572. package/dist/security/api-spec-validator.d.ts +13 -0
  573. package/dist/security/api-spec-validator.d.ts.map +1 -0
  574. package/dist/security/api-spec-validator.js +347 -0
  575. package/dist/security/api-spec-validator.js.map +1 -0
  576. package/dist/security/app-spec-validator.d.ts +4 -0
  577. package/dist/security/app-spec-validator.d.ts.map +1 -0
  578. package/dist/security/app-spec-validator.js +200 -0
  579. package/dist/security/app-spec-validator.js.map +1 -0
  580. package/dist/security/identifier-guard.d.ts +3 -0
  581. package/dist/security/identifier-guard.d.ts.map +1 -0
  582. package/dist/security/identifier-guard.js +15 -0
  583. package/dist/security/identifier-guard.js.map +1 -0
  584. package/dist/security/identity-token-validator.d.ts +3 -0
  585. package/dist/security/identity-token-validator.d.ts.map +1 -0
  586. package/dist/security/identity-token-validator.js +121 -0
  587. package/dist/security/identity-token-validator.js.map +1 -0
  588. package/dist/security/index.d.ts +14 -0
  589. package/dist/security/index.d.ts.map +1 -0
  590. package/dist/security/index.js +8 -0
  591. package/dist/security/index.js.map +1 -0
  592. package/dist/security/protection-registry.d.ts +24 -0
  593. package/dist/security/protection-registry.d.ts.map +1 -0
  594. package/dist/security/protection-registry.js +35 -0
  595. package/dist/security/protection-registry.js.map +1 -0
  596. package/dist/security/rate-limiter.d.ts +23 -0
  597. package/dist/security/rate-limiter.d.ts.map +1 -0
  598. package/dist/security/rate-limiter.js +44 -0
  599. package/dist/security/rate-limiter.js.map +1 -0
  600. package/dist/security/spec-signing.d.ts +23 -0
  601. package/dist/security/spec-signing.d.ts.map +1 -0
  602. package/dist/security/spec-signing.js +62 -0
  603. package/dist/security/spec-signing.js.map +1 -0
  604. package/dist/security/spec-validator.d.ts +60 -0
  605. package/dist/security/spec-validator.d.ts.map +1 -0
  606. package/dist/security/spec-validator.js +903 -0
  607. package/dist/security/spec-validator.js.map +1 -0
  608. package/dist/security/state-protection.d.ts +23 -0
  609. package/dist/security/state-protection.d.ts.map +1 -0
  610. package/dist/security/state-protection.js +49 -0
  611. package/dist/security/state-protection.js.map +1 -0
  612. package/dist/security/url-whitelist.d.ts +14 -0
  613. package/dist/security/url-whitelist.d.ts.map +1 -0
  614. package/dist/security/url-whitelist.js +37 -0
  615. package/dist/security/url-whitelist.js.map +1 -0
  616. package/dist/server.d.ts +6 -0
  617. package/dist/server.d.ts.map +1 -0
  618. package/dist/server.js +8 -0
  619. package/dist/server.js.map +1 -0
  620. package/dist/spec-engine/app-elements.d.ts +5 -0
  621. package/dist/spec-engine/app-elements.d.ts.map +1 -0
  622. package/dist/spec-engine/app-elements.js +36 -0
  623. package/dist/spec-engine/app-elements.js.map +1 -0
  624. package/dist/spec-engine/app-manifest.d.ts +3 -0
  625. package/dist/spec-engine/app-manifest.d.ts.map +1 -0
  626. package/dist/spec-engine/app-manifest.js +132 -0
  627. package/dist/spec-engine/app-manifest.js.map +1 -0
  628. package/dist/spec-engine/elements.d.ts +8 -0
  629. package/dist/spec-engine/elements.d.ts.map +1 -0
  630. package/dist/spec-engine/elements.js +18 -0
  631. package/dist/spec-engine/elements.js.map +1 -0
  632. package/dist/spec-engine/engine.d.ts +3 -0
  633. package/dist/spec-engine/engine.d.ts.map +1 -0
  634. package/dist/spec-engine/engine.js +76 -0
  635. package/dist/spec-engine/engine.js.map +1 -0
  636. package/dist/spec-engine/handlers/api-handler.d.ts +5 -0
  637. package/dist/spec-engine/handlers/api-handler.d.ts.map +1 -0
  638. package/dist/spec-engine/handlers/api-handler.js +111 -0
  639. package/dist/spec-engine/handlers/api-handler.js.map +1 -0
  640. package/dist/spec-engine/handlers/app-handler.d.ts +4 -0
  641. package/dist/spec-engine/handlers/app-handler.d.ts.map +1 -0
  642. package/dist/spec-engine/handlers/app-handler.js +41 -0
  643. package/dist/spec-engine/handlers/app-handler.js.map +1 -0
  644. package/dist/spec-engine/handlers/index.d.ts +8 -0
  645. package/dist/spec-engine/handlers/index.d.ts.map +1 -0
  646. package/dist/spec-engine/handlers/index.js +17 -0
  647. package/dist/spec-engine/handlers/index.js.map +1 -0
  648. package/dist/spec-engine/handlers/screen-handler.d.ts +4 -0
  649. package/dist/spec-engine/handlers/screen-handler.d.ts.map +1 -0
  650. package/dist/spec-engine/handlers/screen-handler.js +34 -0
  651. package/dist/spec-engine/handlers/screen-handler.js.map +1 -0
  652. package/dist/spec-engine/manifest.d.ts +11 -0
  653. package/dist/spec-engine/manifest.d.ts.map +1 -0
  654. package/dist/spec-engine/manifest.js +76 -0
  655. package/dist/spec-engine/manifest.js.map +1 -0
  656. package/dist/spec-engine/types.d.ts +61 -0
  657. package/dist/spec-engine/types.d.ts.map +1 -0
  658. package/dist/spec-engine/types.js +2 -0
  659. package/dist/spec-engine/types.js.map +1 -0
  660. package/dist/spec-stores/file.d.ts +12 -0
  661. package/dist/spec-stores/file.d.ts.map +1 -0
  662. package/dist/spec-stores/file.js +32 -0
  663. package/dist/spec-stores/file.js.map +1 -0
  664. package/dist/spec-stores/memory-versioned.d.ts +22 -0
  665. package/dist/spec-stores/memory-versioned.d.ts.map +1 -0
  666. package/dist/spec-stores/memory-versioned.js +125 -0
  667. package/dist/spec-stores/memory-versioned.js.map +1 -0
  668. package/dist/spec-stores/memory.d.ts +10 -0
  669. package/dist/spec-stores/memory.d.ts.map +1 -0
  670. package/dist/spec-stores/memory.js +31 -0
  671. package/dist/spec-stores/memory.js.map +1 -0
  672. package/dist/spec-stores/sqlserver-versioned.d.ts +44 -0
  673. package/dist/spec-stores/sqlserver-versioned.d.ts.map +1 -0
  674. package/dist/spec-stores/sqlserver-versioned.js +253 -0
  675. package/dist/spec-stores/sqlserver-versioned.js.map +1 -0
  676. package/dist/spec-stores/sqlserver.d.ts +27 -0
  677. package/dist/spec-stores/sqlserver.d.ts.map +1 -0
  678. package/dist/spec-stores/sqlserver.js +78 -0
  679. package/dist/spec-stores/sqlserver.js.map +1 -0
  680. package/dist/spec-stores/supabase-versioned.d.ts +38 -0
  681. package/dist/spec-stores/supabase-versioned.d.ts.map +1 -0
  682. package/dist/spec-stores/supabase-versioned.js +197 -0
  683. package/dist/spec-stores/supabase-versioned.js.map +1 -0
  684. package/dist/spec-stores/supabase.d.ts +18 -0
  685. package/dist/spec-stores/supabase.d.ts.map +1 -0
  686. package/dist/spec-stores/supabase.js +68 -0
  687. package/dist/spec-stores/supabase.js.map +1 -0
  688. package/dist/state/reserved-paths.d.ts +41 -0
  689. package/dist/state/reserved-paths.d.ts.map +1 -0
  690. package/dist/state/reserved-paths.js +40 -0
  691. package/dist/state/reserved-paths.js.map +1 -0
  692. package/dist/state/store.d.ts +18 -0
  693. package/dist/state/store.d.ts.map +1 -0
  694. package/dist/state/store.js +114 -0
  695. package/dist/state/store.js.map +1 -0
  696. package/dist/storage/supabase.d.ts +37 -0
  697. package/dist/storage/supabase.d.ts.map +1 -0
  698. package/dist/storage/supabase.js +22 -0
  699. package/dist/storage/supabase.js.map +1 -0
  700. package/dist/storage/types.d.ts +22 -0
  701. package/dist/storage/types.d.ts.map +1 -0
  702. package/dist/storage/types.js +2 -0
  703. package/dist/storage/types.js.map +1 -0
  704. package/dist/storage/upload-action.d.ts +22 -0
  705. package/dist/storage/upload-action.d.ts.map +1 -0
  706. package/dist/storage/upload-action.js +117 -0
  707. package/dist/storage/upload-action.js.map +1 -0
  708. package/dist/storage/url.d.ts +17 -0
  709. package/dist/storage/url.d.ts.map +1 -0
  710. package/dist/storage/url.js +48 -0
  711. package/dist/storage/url.js.map +1 -0
  712. package/dist/streaming/compiler.d.ts +26 -0
  713. package/dist/streaming/compiler.d.ts.map +1 -0
  714. package/dist/streaming/compiler.js +54 -0
  715. package/dist/streaming/compiler.js.map +1 -0
  716. package/dist/streaming/patch.d.ts +19 -0
  717. package/dist/streaming/patch.d.ts.map +1 -0
  718. package/dist/streaming/patch.js +139 -0
  719. package/dist/streaming/patch.js.map +1 -0
  720. package/dist/types.d.ts +443 -0
  721. package/dist/types.d.ts.map +1 -0
  722. package/dist/types.js +8 -0
  723. package/dist/types.js.map +1 -0
  724. package/dist/util/to-array.d.ts +2 -0
  725. package/dist/util/to-array.d.ts.map +1 -0
  726. package/dist/util/to-array.js +14 -0
  727. package/dist/util/to-array.js.map +1 -0
  728. package/dist/utils/levenshtein.d.ts +3 -0
  729. package/dist/utils/levenshtein.d.ts.map +1 -0
  730. package/dist/utils/levenshtein.js +29 -0
  731. package/dist/utils/levenshtein.js.map +1 -0
  732. package/dist/validation/validators.d.ts +20 -0
  733. package/dist/validation/validators.d.ts.map +1 -0
  734. package/dist/validation/validators.js +138 -0
  735. package/dist/validation/validators.js.map +1 -0
  736. package/dist/versioning/compute-patches.d.ts +7 -0
  737. package/dist/versioning/compute-patches.d.ts.map +1 -0
  738. package/dist/versioning/compute-patches.js +62 -0
  739. package/dist/versioning/compute-patches.js.map +1 -0
  740. package/dist/versioning/index.d.ts +12 -0
  741. package/dist/versioning/index.d.ts.map +1 -0
  742. package/dist/versioning/index.js +7 -0
  743. package/dist/versioning/index.js.map +1 -0
  744. package/dist/versioning/promote-gate.d.ts +12 -0
  745. package/dist/versioning/promote-gate.d.ts.map +1 -0
  746. package/dist/versioning/promote-gate.js +166 -0
  747. package/dist/versioning/promote-gate.js.map +1 -0
  748. package/dist/versioning/rollback.d.ts +26 -0
  749. package/dist/versioning/rollback.d.ts.map +1 -0
  750. package/dist/versioning/rollback.js +67 -0
  751. package/dist/versioning/rollback.js.map +1 -0
  752. package/dist/versioning/structural-diff.d.ts +8 -0
  753. package/dist/versioning/structural-diff.d.ts.map +1 -0
  754. package/dist/versioning/structural-diff.js +287 -0
  755. package/dist/versioning/structural-diff.js.map +1 -0
  756. package/dist/versioning/types.d.ts +90 -0
  757. package/dist/versioning/types.d.ts.map +1 -0
  758. package/dist/versioning/types.js +2 -0
  759. package/dist/versioning/types.js.map +1 -0
  760. package/dist/visibility/evaluator.d.ts +12 -0
  761. package/dist/visibility/evaluator.d.ts.map +1 -0
  762. package/dist/visibility/evaluator.js +76 -0
  763. package/dist/visibility/evaluator.js.map +1 -0
  764. package/dist/watchers/engine.d.ts +19 -0
  765. package/dist/watchers/engine.d.ts.map +1 -0
  766. package/dist/watchers/engine.js +24 -0
  767. package/dist/watchers/engine.js.map +1 -0
  768. package/docs/consumer/README.md +44 -0
  769. package/docs/consumer/WHERE-TO-LOOK.md +94 -0
  770. package/docs/consumer/ai-context-api.md +195 -0
  771. package/docs/consumer/ai-context-custom-elements.md +249 -0
  772. package/docs/consumer/ai-context-patterns.md +254 -0
  773. package/docs/consumer/ai-context-primitives.md +839 -0
  774. package/docs/consumer/ai-context-runtime-semantics.md +1075 -0
  775. package/docs/consumer/ai-context.md +1374 -0
  776. package/docs/consumer/reference-doc.md +3201 -0
  777. package/docs/llms.txt +17 -0
  778. package/docs/wiki/compiled/README.md +33 -0
  779. package/docs/wiki/compiled/_gaps.md +52 -0
  780. package/docs/wiki/compiled/_index.md +354 -0
  781. package/docs/wiki/compiled/_inventory.md +2986 -0
  782. package/docs/wiki/compiled/_lint.md +66 -0
  783. package/docs/wiki/compiled/_unmapped.md +3 -0
  784. package/docs/wiki/compiled/action-apply-preset.md +63 -0
  785. package/docs/wiki/compiled/action-copy-clipboard.md +45 -0
  786. package/docs/wiki/compiled/action-drawer.md +50 -0
  787. package/docs/wiki/compiled/action-export.md +66 -0
  788. package/docs/wiki/compiled/action-fetch.md +87 -0
  789. package/docs/wiki/compiled/action-form-control.md +55 -0
  790. package/docs/wiki/compiled/action-login.md +71 -0
  791. package/docs/wiki/compiled/action-modal.md +61 -0
  792. package/docs/wiki/compiled/action-navigate.md +72 -0
  793. package/docs/wiki/compiled/action-open-url.md +38 -0
  794. package/docs/wiki/compiled/action-refresh-data-source.md +51 -0
  795. package/docs/wiki/compiled/action-selection.md +55 -0
  796. package/docs/wiki/compiled/action-set-locale.md +44 -0
  797. package/docs/wiki/compiled/action-set-state.md +61 -0
  798. package/docs/wiki/compiled/action-show-notification.md +65 -0
  799. package/docs/wiki/compiled/action-submit-form.md +69 -0
  800. package/docs/wiki/compiled/action-toggle-theme.md +50 -0
  801. package/docs/wiki/compiled/action-update-tokens.md +63 -0
  802. package/docs/wiki/compiled/action-upload-file.md +87 -0
  803. package/docs/wiki/compiled/antipattern-action-chain-no-stop.md +49 -0
  804. package/docs/wiki/compiled/antipattern-all-filter-wildcard.md +59 -0
  805. package/docs/wiki/compiled/antipattern-auth-domains-port.md +47 -0
  806. package/docs/wiki/compiled/antipattern-background-blobs-prop.md +62 -0
  807. package/docs/wiki/compiled/antipattern-background-css-token.md +53 -0
  808. package/docs/wiki/compiled/antipattern-checkbox-toggle-value.md +42 -0
  809. package/docs/wiki/compiled/antipattern-crud-id-collision.md +66 -0
  810. package/docs/wiki/compiled/antipattern-derive-server-pagination.md +58 -0
  811. package/docs/wiki/compiled/antipattern-element-variant-top-level.md +57 -0
  812. package/docs/wiki/compiled/antipattern-event-expression.md +55 -0
  813. package/docs/wiki/compiled/antipattern-input-type-name.md +43 -0
  814. package/docs/wiki/compiled/antipattern-mix-fetch-and-datasources.md +48 -0
  815. package/docs/wiki/compiled/antipattern-modal-drawer-visible.md +57 -0
  816. package/docs/wiki/compiled/antipattern-motion-entrance-token.md +53 -0
  817. package/docs/wiki/compiled/antipattern-overflow-hidden-with-shadow.md +50 -0
  818. package/docs/wiki/compiled/antipattern-required-if-equals.md +59 -0
  819. package/docs/wiki/compiled/antipattern-row-literal.md +70 -0
  820. package/docs/wiki/compiled/antipattern-row-template-capture.md +42 -0
  821. package/docs/wiki/compiled/antipattern-store-save-bypass.md +72 -0
  822. package/docs/wiki/compiled/antipattern-style-block-duplication.md +56 -0
  823. package/docs/wiki/compiled/antipattern-submit-form-in-tx-confirm.md +56 -0
  824. package/docs/wiki/compiled/cli-app-spec.md +53 -0
  825. package/docs/wiki/compiled/cli-config.md +46 -0
  826. package/docs/wiki/compiled/cli-contract.md +73 -0
  827. package/docs/wiki/compiled/cli-delete.md +37 -0
  828. package/docs/wiki/compiled/cli-docs.md +44 -0
  829. package/docs/wiki/compiled/cli-elements.md +39 -0
  830. package/docs/wiki/compiled/cli-existing-spec-edit-loop.md +24 -0
  831. package/docs/wiki/compiled/cli-history.md +38 -0
  832. package/docs/wiki/compiled/cli-lint.md +77 -0
  833. package/docs/wiki/compiled/cli-manifest.md +43 -0
  834. package/docs/wiki/compiled/cli-overview.md +77 -0
  835. package/docs/wiki/compiled/cli-patch.md +85 -0
  836. package/docs/wiki/compiled/cli-programmatic-api.md +73 -0
  837. package/docs/wiki/compiled/cli-pull.md +39 -0
  838. package/docs/wiki/compiled/cli-push.md +91 -0
  839. package/docs/wiki/compiled/cli-tokens.md +38 -0
  840. package/docs/wiki/compiled/cli-toon.md +44 -0
  841. package/docs/wiki/compiled/cli-validate.md +52 -0
  842. package/docs/wiki/compiled/cli-versioning-author.md +58 -0
  843. package/docs/wiki/compiled/concept-action-chains.md +65 -0
  844. package/docs/wiki/compiled/concept-action-middleware.md +55 -0
  845. package/docs/wiki/compiled/concept-animation-build-css.md +43 -0
  846. package/docs/wiki/compiled/concept-animation-build-rn.md +44 -0
  847. package/docs/wiki/compiled/concept-animation-caps.md +38 -0
  848. package/docs/wiki/compiled/concept-animation-cascade.md +89 -0
  849. package/docs/wiki/compiled/concept-animation-null-semantics.md +55 -0
  850. package/docs/wiki/compiled/concept-animation-recipes.md +67 -0
  851. package/docs/wiki/compiled/concept-animation-triggers.md +54 -0
  852. package/docs/wiki/compiled/concept-animations-engine.md +78 -0
  853. package/docs/wiki/compiled/concept-api-audit.md +67 -0
  854. package/docs/wiki/compiled/concept-api-auth.md +67 -0
  855. package/docs/wiki/compiled/concept-api-catalogs.md +44 -0
  856. package/docs/wiki/compiled/concept-api-crud-endpoint.md +90 -0
  857. package/docs/wiki/compiled/concept-api-endpoint-properties.md +40 -0
  858. package/docs/wiki/compiled/concept-api-endpoints-overview.md +57 -0
  859. package/docs/wiki/compiled/concept-api-handler-endpoint.md +56 -0
  860. package/docs/wiki/compiled/concept-api-login-body-contract.md +47 -0
  861. package/docs/wiki/compiled/concept-api-param-properties.md +44 -0
  862. package/docs/wiki/compiled/concept-api-public-endpoint.md +33 -0
  863. package/docs/wiki/compiled/concept-api-query-endpoint.md +53 -0
  864. package/docs/wiki/compiled/concept-api-scope-filter.md +59 -0
  865. package/docs/wiki/compiled/concept-api-spec.md +70 -0
  866. package/docs/wiki/compiled/concept-app-auto-state-paths.md +59 -0
  867. package/docs/wiki/compiled/concept-app-spec.md +89 -0
  868. package/docs/wiki/compiled/concept-auth-config.md +71 -0
  869. package/docs/wiki/compiled/concept-auth-domains.md +55 -0
  870. package/docs/wiki/compiled/concept-auth-security.md +58 -0
  871. package/docs/wiki/compiled/concept-auth-state-paths.md +48 -0
  872. package/docs/wiki/compiled/concept-auto-dark-mode.md +55 -0
  873. package/docs/wiki/compiled/concept-background-caps.md +42 -0
  874. package/docs/wiki/compiled/concept-background-layer-kinds.md +80 -0
  875. package/docs/wiki/compiled/concept-background-recipes.md +53 -0
  876. package/docs/wiki/compiled/concept-background-stack.md +55 -0
  877. package/docs/wiki/compiled/concept-blob-layer.md +92 -0
  878. package/docs/wiki/compiled/concept-blob-motion.md +58 -0
  879. package/docs/wiki/compiled/concept-blob-shapes-catalog.md +45 -0
  880. package/docs/wiki/compiled/concept-cli-tokens-inspect.md +38 -0
  881. package/docs/wiki/compiled/concept-component-variants.md +89 -0
  882. package/docs/wiki/compiled/concept-cross-tab-sync.md +35 -0
  883. package/docs/wiki/compiled/concept-css-vs-motion.md +46 -0
  884. package/docs/wiki/compiled/concept-custom-detection-pattern.md +49 -0
  885. package/docs/wiki/compiled/concept-custom-element-action-props.md +81 -0
  886. package/docs/wiki/compiled/concept-custom-element-black-box.md +56 -0
  887. package/docs/wiki/compiled/concept-custom-element-cache.md +39 -0
  888. package/docs/wiki/compiled/concept-custom-element-error-boundary.md +33 -0
  889. package/docs/wiki/compiled/concept-custom-element-prop-cascade.md +60 -0
  890. package/docs/wiki/compiled/concept-custom-element-repeat.md +53 -0
  891. package/docs/wiki/compiled/concept-custom-elements.md +71 -0
  892. package/docs/wiki/compiled/concept-custom-jwt-provider.md +63 -0
  893. package/docs/wiki/compiled/concept-customize-action.md +33 -0
  894. package/docs/wiki/compiled/concept-customize-cli-lint-rule.md +30 -0
  895. package/docs/wiki/compiled/concept-customize-expression-handler.md +30 -0
  896. package/docs/wiki/compiled/concept-customize-plugin.md +43 -0
  897. package/docs/wiki/compiled/concept-customize-server-middleware.md +36 -0
  898. package/docs/wiki/compiled/concept-customize-spec-store.md +42 -0
  899. package/docs/wiki/compiled/concept-customize-validator-rule.md +35 -0
  900. package/docs/wiki/compiled/concept-customize-versioned-store.md +37 -0
  901. package/docs/wiki/compiled/concept-data-sources-lifecycle.md +61 -0
  902. package/docs/wiki/compiled/concept-data-sources.md +96 -0
  903. package/docs/wiki/compiled/concept-debugging-runtime-pointers.md +45 -0
  904. package/docs/wiki/compiled/concept-derive-datasources-mount-order.md +72 -0
  905. package/docs/wiki/compiled/concept-derive.md +67 -0
  906. package/docs/wiki/compiled/concept-dna-seeds.md +79 -0
  907. package/docs/wiki/compiled/concept-editor-commit.md +37 -0
  908. package/docs/wiki/compiled/concept-editor-save.md +18 -0
  909. package/docs/wiki/compiled/concept-editor-sessions.md +23 -0
  910. package/docs/wiki/compiled/concept-element-children-slot.md +54 -0
  911. package/docs/wiki/compiled/concept-element-definition.md +60 -0
  912. package/docs/wiki/compiled/concept-element-key.md +56 -0
  913. package/docs/wiki/compiled/concept-element-prop-definition.md +54 -0
  914. package/docs/wiki/compiled/concept-element-properties.md +81 -0
  915. package/docs/wiki/compiled/concept-element-render-node.md +62 -0
  916. package/docs/wiki/compiled/concept-element-variants.md +67 -0
  917. package/docs/wiki/compiled/concept-environment-store.md +46 -0
  918. package/docs/wiki/compiled/concept-export-action.md +56 -0
  919. package/docs/wiki/compiled/concept-expression-contexts.md +56 -0
  920. package/docs/wiki/compiled/concept-expression-timing.md +56 -0
  921. package/docs/wiki/compiled/concept-fetch-interceptors.md +49 -0
  922. package/docs/wiki/compiled/concept-file-upload-overview.md +55 -0
  923. package/docs/wiki/compiled/concept-fire-and-forget.md +45 -0
  924. package/docs/wiki/compiled/concept-font-loading.md +52 -0
  925. package/docs/wiki/compiled/concept-form-state-paths.md +55 -0
  926. package/docs/wiki/compiled/concept-forms.md +89 -0
  927. package/docs/wiki/compiled/concept-identity-accent-application.md +48 -0
  928. package/docs/wiki/compiled/concept-identity-animations.md +48 -0
  929. package/docs/wiki/compiled/concept-identity-border-elevation-override.md +56 -0
  930. package/docs/wiki/compiled/concept-identity-color-scheme.md +74 -0
  931. package/docs/wiki/compiled/concept-identity-color-weight.md +50 -0
  932. package/docs/wiki/compiled/concept-identity-glass-rn.md +46 -0
  933. package/docs/wiki/compiled/concept-identity-gradients.md +56 -0
  934. package/docs/wiki/compiled/concept-identity-heading-color.md +40 -0
  935. package/docs/wiki/compiled/concept-identity-helpers.md +61 -0
  936. package/docs/wiki/compiled/concept-identity-icons.md +46 -0
  937. package/docs/wiki/compiled/concept-identity-images.md +36 -0
  938. package/docs/wiki/compiled/concept-identity-label-style.md +36 -0
  939. package/docs/wiki/compiled/concept-identity-overview.md +72 -0
  940. package/docs/wiki/compiled/concept-identity-radius-pattern.md +39 -0
  941. package/docs/wiki/compiled/concept-identity-surface.md +62 -0
  942. package/docs/wiki/compiled/concept-identity-text-decoration.md +48 -0
  943. package/docs/wiki/compiled/concept-identity-typography-hierarchy.md +40 -0
  944. package/docs/wiki/compiled/concept-initial-actions.md +82 -0
  945. package/docs/wiki/compiled/concept-interactive-states.md +72 -0
  946. package/docs/wiki/compiled/concept-keyframe-snapshot.md +52 -0
  947. package/docs/wiki/compiled/concept-layer-background.md +80 -0
  948. package/docs/wiki/compiled/concept-motion-field.md +77 -0
  949. package/docs/wiki/compiled/concept-mount-spec-runtime.md +47 -0
  950. package/docs/wiki/compiled/concept-mythik-renderer.md +76 -0
  951. package/docs/wiki/compiled/concept-navigation-dirty-guard.md +23 -0
  952. package/docs/wiki/compiled/concept-navigation.md +75 -0
  953. package/docs/wiki/compiled/concept-package-layout.md +35 -0
  954. package/docs/wiki/compiled/concept-path-references.md +53 -0
  955. package/docs/wiki/compiled/concept-pattern-primitives.md +54 -0
  956. package/docs/wiki/compiled/concept-preset-dropdown-pattern.md +52 -0
  957. package/docs/wiki/compiled/concept-presets.md +49 -0
  958. package/docs/wiki/compiled/concept-primitive-prop-schemas.md +53 -0
  959. package/docs/wiki/compiled/concept-primitives-overview.md +49 -0
  960. package/docs/wiki/compiled/concept-promote-gate.md +47 -0
  961. package/docs/wiki/compiled/concept-prop-cascade.md +76 -0
  962. package/docs/wiki/compiled/concept-public-package-names.md +33 -0
  963. package/docs/wiki/compiled/concept-query-envelope.md +55 -0
  964. package/docs/wiki/compiled/concept-reduced-motion.md +38 -0
  965. package/docs/wiki/compiled/concept-register-presets.md +44 -0
  966. package/docs/wiki/compiled/concept-render-error-visibility.md +57 -0
  967. package/docs/wiki/compiled/concept-repeat-grouped.md +72 -0
  968. package/docs/wiki/compiled/concept-repeat-selection.md +61 -0
  969. package/docs/wiki/compiled/concept-repeat.md +81 -0
  970. package/docs/wiki/compiled/concept-role-access.md +61 -0
  971. package/docs/wiki/compiled/concept-rollback.md +36 -0
  972. package/docs/wiki/compiled/concept-rules-catalog.md +49 -0
  973. package/docs/wiki/compiled/concept-screen-definition.md +51 -0
  974. package/docs/wiki/compiled/concept-screen-outlet.md +46 -0
  975. package/docs/wiki/compiled/concept-session-persistence.md +41 -0
  976. package/docs/wiki/compiled/concept-shape-animations.md +66 -0
  977. package/docs/wiki/compiled/concept-skeleton-auto.md +58 -0
  978. package/docs/wiki/compiled/concept-skeleton-manual.md +47 -0
  979. package/docs/wiki/compiled/concept-source-of-truth-references.md +37 -0
  980. package/docs/wiki/compiled/concept-source-reading-misleading.md +37 -0
  981. package/docs/wiki/compiled/concept-spatial-map-editor.md +22 -0
  982. package/docs/wiki/compiled/concept-spatial-map-zones.md +18 -0
  983. package/docs/wiki/compiled/concept-spec-engine.md +47 -0
  984. package/docs/wiki/compiled/concept-spec-store-interface.md +59 -0
  985. package/docs/wiki/compiled/concept-spec-store-layering.md +51 -0
  986. package/docs/wiki/compiled/concept-spec-stores-catalog.md +66 -0
  987. package/docs/wiki/compiled/concept-spec-structure.md +94 -0
  988. package/docs/wiki/compiled/concept-spec-types.md +76 -0
  989. package/docs/wiki/compiled/concept-state-change-animation.md +73 -0
  990. package/docs/wiki/compiled/concept-state-policies.md +44 -0
  991. package/docs/wiki/compiled/concept-state-protection.md +51 -0
  992. package/docs/wiki/compiled/concept-storage-adapter.md +69 -0
  993. package/docs/wiki/compiled/concept-storage-custom-names.md +69 -0
  994. package/docs/wiki/compiled/concept-storage-evolution.md +32 -0
  995. package/docs/wiki/compiled/concept-storage-idempotency.md +35 -0
  996. package/docs/wiki/compiled/concept-storage-overview.md +81 -0
  997. package/docs/wiki/compiled/concept-storage-postgres-jsonb.md +53 -0
  998. package/docs/wiki/compiled/concept-storage-postgres-triggers.md +60 -0
  999. package/docs/wiki/compiled/concept-storage-table-environments.md +40 -0
  1000. package/docs/wiki/compiled/concept-storage-table-screens.md +44 -0
  1001. package/docs/wiki/compiled/concept-storage-table-versions.md +50 -0
  1002. package/docs/wiki/compiled/concept-storage-verification.md +57 -0
  1003. package/docs/wiki/compiled/concept-template-children-marker.md +56 -0
  1004. package/docs/wiki/compiled/concept-template-interpolation.md +60 -0
  1005. package/docs/wiki/compiled/concept-templates-vs-variants.md +80 -0
  1006. package/docs/wiki/compiled/concept-templates.md +93 -0
  1007. package/docs/wiki/compiled/concept-token-categories.md +58 -0
  1008. package/docs/wiki/compiled/concept-token-system.md +61 -0
  1009. package/docs/wiki/compiled/concept-transaction-phase-timing.md +47 -0
  1010. package/docs/wiki/compiled/concept-transaction-rollback.md +38 -0
  1011. package/docs/wiki/compiled/concept-transaction-snapshot.md +37 -0
  1012. package/docs/wiki/compiled/concept-transactions.md +72 -0
  1013. package/docs/wiki/compiled/concept-validation-checks.md +63 -0
  1014. package/docs/wiki/compiled/concept-validators-catalog.md +76 -0
  1015. package/docs/wiki/compiled/concept-versioned-store.md +65 -0
  1016. package/docs/wiki/compiled/concept-versioning-snapshots-patches.md +61 -0
  1017. package/docs/wiki/compiled/concept-visibility.md +55 -0
  1018. package/docs/wiki/compiled/concept-web-only-recipes.md +37 -0
  1019. package/docs/wiki/compiled/concept-where-to-look.md +78 -0
  1020. package/docs/wiki/compiled/expression-and-or-not.md +68 -0
  1021. package/docs/wiki/compiled/expression-array.md +111 -0
  1022. package/docs/wiki/compiled/expression-auth.md +83 -0
  1023. package/docs/wiki/compiled/expression-binditem.md +52 -0
  1024. package/docs/wiki/compiled/expression-bindstate.md +63 -0
  1025. package/docs/wiki/compiled/expression-breakpoint.md +71 -0
  1026. package/docs/wiki/compiled/expression-computed.md +52 -0
  1027. package/docs/wiki/compiled/expression-cond.md +78 -0
  1028. package/docs/wiki/compiled/expression-date.md +66 -0
  1029. package/docs/wiki/compiled/expression-format.md +79 -0
  1030. package/docs/wiki/compiled/expression-group.md +84 -0
  1031. package/docs/wiki/compiled/expression-i18n.md +53 -0
  1032. package/docs/wiki/compiled/expression-item-index.md +72 -0
  1033. package/docs/wiki/compiled/expression-let-ref.md +87 -0
  1034. package/docs/wiki/compiled/expression-math.md +67 -0
  1035. package/docs/wiki/compiled/expression-platform.md +68 -0
  1036. package/docs/wiki/compiled/expression-prop.md +89 -0
  1037. package/docs/wiki/compiled/expression-selection.md +58 -0
  1038. package/docs/wiki/compiled/expression-state.md +70 -0
  1039. package/docs/wiki/compiled/expression-switch.md +68 -0
  1040. package/docs/wiki/compiled/expression-template.md +71 -0
  1041. package/docs/wiki/compiled/expression-token.md +67 -0
  1042. package/docs/wiki/compiled/path-app-screens.md +55 -0
  1043. package/docs/wiki/compiled/path-data-source-paths.md +44 -0
  1044. package/docs/wiki/compiled/path-forms.md +38 -0
  1045. package/docs/wiki/compiled/path-login.md +57 -0
  1046. package/docs/wiki/compiled/path-navigation.md +62 -0
  1047. package/docs/wiki/compiled/path-presets-available.md +44 -0
  1048. package/docs/wiki/compiled/path-tokens.md +56 -0
  1049. package/docs/wiki/compiled/path-tx-result-error.md +56 -0
  1050. package/docs/wiki/compiled/path-ui-device.md +53 -0
  1051. package/docs/wiki/compiled/path-ui-loading-error.md +40 -0
  1052. package/docs/wiki/compiled/path-ui-modals-drawers.md +46 -0
  1053. package/docs/wiki/compiled/path-ui-selected-row.md +92 -0
  1054. package/docs/wiki/compiled/path-uploads.md +32 -0
  1055. package/docs/wiki/compiled/pattern-cross-screen-data-flow.md +83 -0
  1056. package/docs/wiki/compiled/pattern-fetch-vs-datasources.md +63 -0
  1057. package/docs/wiki/compiled/pattern-file-upload-auto.md +61 -0
  1058. package/docs/wiki/compiled/pattern-file-upload-manual.md +59 -0
  1059. package/docs/wiki/compiled/pattern-form-validation-cross-field.md +58 -0
  1060. package/docs/wiki/compiled/pattern-form-validation.md +58 -0
  1061. package/docs/wiki/compiled/pattern-fullstack-coherence.md +49 -0
  1062. package/docs/wiki/compiled/pattern-git-vs-db-versioning.md +55 -0
  1063. package/docs/wiki/compiled/pattern-identity-aware-spec.md +70 -0
  1064. package/docs/wiki/compiled/pattern-loading-content-empty.md +66 -0
  1065. package/docs/wiki/compiled/pattern-login-body-template.md +47 -0
  1066. package/docs/wiki/compiled/pattern-login-screen.md +83 -0
  1067. package/docs/wiki/compiled/pattern-push-vs-patch.md +54 -0
  1068. package/docs/wiki/compiled/pattern-reusable-components.md +67 -0
  1069. package/docs/wiki/compiled/pattern-tx-create.md +76 -0
  1070. package/docs/wiki/compiled/pattern-tx-delete.md +50 -0
  1071. package/docs/wiki/compiled/pattern-tx-toggle.md +45 -0
  1072. package/docs/wiki/compiled/pattern-tx-update.md +68 -0
  1073. package/docs/wiki/compiled/primitive-accordion.md +46 -0
  1074. package/docs/wiki/compiled/primitive-area-chart.md +35 -0
  1075. package/docs/wiki/compiled/primitive-audio-player.md +27 -0
  1076. package/docs/wiki/compiled/primitive-bar-chart.md +34 -0
  1077. package/docs/wiki/compiled/primitive-box.md +58 -0
  1078. package/docs/wiki/compiled/primitive-button.md +55 -0
  1079. package/docs/wiki/compiled/primitive-camera.md +39 -0
  1080. package/docs/wiki/compiled/primitive-checkbox.md +62 -0
  1081. package/docs/wiki/compiled/primitive-divider.md +31 -0
  1082. package/docs/wiki/compiled/primitive-drawer.md +44 -0
  1083. package/docs/wiki/compiled/primitive-file-upload.md +65 -0
  1084. package/docs/wiki/compiled/primitive-grid.md +48 -0
  1085. package/docs/wiki/compiled/primitive-icon.md +106 -0
  1086. package/docs/wiki/compiled/primitive-image.md +49 -0
  1087. package/docs/wiki/compiled/primitive-input.md +81 -0
  1088. package/docs/wiki/compiled/primitive-kanban-board.md +30 -0
  1089. package/docs/wiki/compiled/primitive-line-chart.md +33 -0
  1090. package/docs/wiki/compiled/primitive-list.md +34 -0
  1091. package/docs/wiki/compiled/primitive-modal.md +51 -0
  1092. package/docs/wiki/compiled/primitive-pie-chart.md +32 -0
  1093. package/docs/wiki/compiled/primitive-screen-outlet.md +42 -0
  1094. package/docs/wiki/compiled/primitive-screen.md +43 -0
  1095. package/docs/wiki/compiled/primitive-scroll.md +33 -0
  1096. package/docs/wiki/compiled/primitive-select.md +76 -0
  1097. package/docs/wiki/compiled/primitive-signature.md +40 -0
  1098. package/docs/wiki/compiled/primitive-skeleton.md +48 -0
  1099. package/docs/wiki/compiled/primitive-slider.md +47 -0
  1100. package/docs/wiki/compiled/primitive-spacer.md +33 -0
  1101. package/docs/wiki/compiled/primitive-spatial-map.md +26 -0
  1102. package/docs/wiki/compiled/primitive-stack.md +46 -0
  1103. package/docs/wiki/compiled/primitive-table.md +127 -0
  1104. package/docs/wiki/compiled/primitive-tabs.md +52 -0
  1105. package/docs/wiki/compiled/primitive-text.md +59 -0
  1106. package/docs/wiki/compiled/primitive-textarea.md +44 -0
  1107. package/docs/wiki/compiled/primitive-toast-container.md +44 -0
  1108. package/docs/wiki/compiled/primitive-toggle.md +46 -0
  1109. package/docs/wiki/compiled/primitive-touchable.md +40 -0
  1110. package/docs/wiki/compiled/primitive-wizard.md +43 -0
  1111. package/package.json +58 -8
@@ -0,0 +1,1374 @@
1
+ # Mythik — AI Spec Reference
2
+
3
+ > Read this document completely before generating any JSON spec.
4
+ > Core reference for spec structure, expressions, actions, and rules.
5
+
6
+ **Companion modules (read as needed):**
7
+ - [ai-context-primitives.md](ai-context-primitives.md) — props tables for all 38 primitives (read when generating UI)
8
+ - [ai-context-patterns.md](ai-context-patterns.md) — expression matrix, composition anti-patterns (read when combining 2+ features)
9
+ - [ai-context-api.md](ai-context-api.md) — catalogs, endpoints, auth, audit (read when generating API specs)
10
+ - [ai-context-custom-elements.md](ai-context-custom-elements.md) — custom element authoring (Layer 3): ElementDefinition, variants, black-box contract (read when authoring or consuming custom elements)
11
+ - [ai-context-runtime-semantics.md](ai-context-runtime-semantics.md) — runtime behavior reference: expression timing, reserved state paths, server contracts, matcher semantics, store coordination (read when debugging runtime behavior or building CRUD/auth/tables)
12
+ ## Public Package Names
13
+
14
+ Public npm package names are unscoped:
15
+
16
+ - Runtime/core: `mythik`
17
+ - Browser-safe server helpers from core: `mythik/server`
18
+ - React host/runtime: `mythik-react`
19
+ - CLI binary package: `mythik-cli` (binary command: `mythik`)
20
+ - Programmatic CLI API: `mythik-cli/api`
21
+ - Node/Express server package: `mythik-server`
22
+
23
+ Use `npm install mythik mythik-react` for a React app, `npm install -D mythik-cli` for CLI workflows, and add `mythik-server` only when building a Mythik-backed Node server. The `mythik` npm package bundles the AI documentation corpus under `node_modules/mythik/docs`; use `mythik docs path` to locate it after install or `mythik docs copy ./mythik-docs` to copy it into the current project.
24
+
25
+ ## Spec Structure
26
+
27
+ Every screen is a flat tree: `root` ID + `elements` map + optional `initialActions`:
28
+
29
+ ```json
30
+ {
31
+ "root": "main-layout",
32
+ "initialActions": [
33
+ { "action": "fetch", "params": { "url": "/api/data", "target": "/items" } }
34
+ ],
35
+ "elements": {
36
+ "main-layout": {
37
+ "type": "stack",
38
+ "props": { "direction": "vertical" },
39
+ "children": ["header", "content"]
40
+ },
41
+ "header": {
42
+ "type": "text",
43
+ "props": { "content": "Hello", "variant": "heading" }
44
+ },
45
+ "content": {
46
+ "type": "box",
47
+ "props": {},
48
+ "children": ["field1"]
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### Top-Level Properties
55
+
56
+ | Property | Type | Purpose |
57
+ |----------|------|---------|
58
+ | `root` | string | ID of the root element |
59
+ | `elements` | object | Flat map of element ID → definition |
60
+ | `initialActions` | ActionBinding[] | Actions on spec mount (e.g., fetch data) |
61
+ | `derive` | object | Auto-computed reactive state (see Derive section) |
62
+ | `forms` | object | Declarative form validation (see Forms section) |
63
+ | `dataSources` | object | Reactive data fetching (see DataSources section) |
64
+ | `templates` | object | Reusable element definitions (see Templates section) |
65
+
66
+ ### Element Properties
67
+
68
+ | Property | Type | Purpose |
69
+ |----------|------|---------|
70
+ | `type` | string | Primitive name or template name |
71
+ | `props` | object | Component props (can contain expressions) |
72
+ | `children` | string[] | Child element IDs |
73
+ | `style` | object | CSS styles (can contain expressions) |
74
+ | `visible` | expression | Show/hide condition |
75
+ | `permission` | object | `{ visible, editable, readonly }` per role |
76
+ | `repeat` | object | Iterate over array: `{ statePath, key }` or `{ source, key }` |
77
+ | `on` | object | Event handlers: `{ press, change, submit }` |
78
+ | `hover` | object | Style overrides on pointer enter |
79
+ | `active` | object | Style overrides on press |
80
+ | `focus` | object | Style overrides on keyboard focus |
81
+ | `transition` | object | `{ duration, ease }` for hover/active/focus |
82
+ | `motion` | object | Framer-Motion-style mount/exit animations: `{ initial, animate, exit, transition }` |
83
+ | `animations` | object | Animation engine config: `{ mount, unmount, hover, focus, active, ambient, stateChange }` — see Animation Engine section |
84
+ | `skeleton` | boolean | `false` to opt-out of auto-skeleton |
85
+
86
+ ## CLI Workflow
87
+
88
+ ```bash
89
+ mythik docs path # Locate bundled AI documentation
90
+ mythik docs copy ./mythik-docs # Copy docs for an AI agent / local review
91
+ mythik manifest <screen> # See structural tree
92
+ mythik elements <screen> <id1,id2> # Get element details
93
+ mythik patch <screen> --from-file patch.json # Apply RFC 6902 patches
94
+ mythik pull <screen> # Export full spec for backup/review
95
+ mythik push <screen> # Create or intentionally replace a full spec
96
+ mythik validate <screen> # Validate spec
97
+ ```
98
+
99
+ ### Required edit loop for existing specs
100
+
101
+ When an AI agent modifies an existing Mythik spec, use this loop by default:
102
+
103
+ 1. `mythik manifest <screen>` - inspect the current structure and identify candidate element IDs.
104
+ 2. `mythik elements <screen> <id1,id2,...>` - inspect only the exact elements and nearby containers that will change.
105
+ 3. Write a small RFC 6902 patch file.
106
+ 4. `mythik patch <screen> --from-file patch.json` - apply the surgical change through the validated CLI path.
107
+ 5. Re-run `mythik manifest <screen>` or `mythik elements <screen> <ids>` to verify the changed surface.
108
+
109
+ Do not edit database rows directly, do not call `SpecStore.save()` from app code, and do not replace a whole screen with `push` when a targeted `patch` can express the change. `pull` is for backup, migration, review, or full-spec creation workflows; it is not the normal first step for a small edit.
110
+
111
+ **Patch rules:** `"op": "add"` with numeric index **inserts before** (not replace). Use `/-` to append. Use `"op": "replace"` to overwrite. Prefer `mythik patch <id> --from-file patch.json` for any patch containing `$state`, `$template`, `$auth`, or other shell-sensitive strings.
112
+
113
+ **Patch input precedence:** explicit sources win. `--from-file <path>` reads that file even if the host process has non-TTY stdin (common in PowerShell/agent runners). Stdin still works via `--from-file -` or by piping without `--from-file`: `cat patch.json | mythik patch <id>`.
114
+
115
+ All commands accept `--json`, `--table <name>`, `--store`, `--url`, `--key`. Never pass API keys inline — use `.mythikrc` + env vars.
116
+
117
+ ### CLI is the only approved path for spec writes
118
+
119
+ Per reference-doc rule 248: three approved forms.
120
+
121
+ - **Shell**: `mythik push <id> --from-file spec.json` and `mythik patch <id> --from-file patch.json` (cross-shell ergonomic for any spec/patch containing `$state`, `$template`, `$auth`, or `$row`)
122
+ - **Bulk**: `mythik push --from-dir <folder>` — sequential per-file push of every `*.json`. Continue-on-error: failures don't stop subsequent specs. No rollback. Partial state recovers by fixing failures and re-running.
123
+ - **Programmatic**: `import { runPush, runPatch, parsePatchInput, type PushResult } from 'mythik-cli/api'` — same code path as the binary, no shell. Pass `json: true` in options to receive structured command output via `JSON.parse(result.output)`. `runPatch` success output includes `versioned: boolean` and `version?: number` when a versioned store + `author` creates history.
124
+
125
+ `SpecStore.save()` is `@internal` — calling it from application code skips validation and produces runtime errors only at render time. The three forms above are the only validated paths.
126
+
127
+ ### Pre-push linting
128
+
129
+ Run `mythik lint` to detect anti-patterns before pushing. Three approved invocations:
130
+ - `mythik lint --from-file spec.json` — single spec file
131
+ - `mythik lint --from-dir specs/` — bulk over a directory
132
+ - `mythik lint` (no args) — auto-discovers via `.mythikrc` file store + scans `./src` for code rules
133
+
134
+ The 4 rules ship in v0.1; spec rules also surface during `mythik push` (defense-in-depth). Programmatic via `import { runLint } from 'mythik-cli/api'`.
135
+
136
+ ## Expressions
137
+
138
+ Expressions are JSON objects that resolve to dynamic values at runtime.
139
+
140
+ ### State & Binding
141
+
142
+ | Expression | Syntax | Purpose |
143
+ |------------|--------|---------|
144
+ | `$state` | `{ "$state": "/user/name" }` | Read from state |
145
+ | `$bindState` | `{ "$bindState": "/form/email" }` | Two-way binding (read + write) |
146
+ | `$auth` | `{ "$auth": "email" }` | Auth user data (whitelisted fields only) |
147
+ | `$item` | `{ "$item": "title" }` | Current repeat item field |
148
+ | `$index` | `{ "$index": true }` | Current repeat item position |
149
+ | `$bindItem` | `{ "$bindItem": "completed" }` | Two-way binding to repeat item field |
150
+ | `$prop` | `{ "$prop": "label" }` | Template prop reference |
151
+ | `$ref` | `{ "$ref": "myVar" }` | Reference a `$let` binding |
152
+
153
+ ### Values & Formatting
154
+
155
+ | Expression | Syntax | Purpose |
156
+ |------------|--------|---------|
157
+ | `$token` | `{ "$token": "colors.primary" }` | Design system token. `multiply` for numeric scaling |
158
+ | `$i18n` | `{ "$i18n": "key", "args": {...} }` | Translation key |
159
+ | `$template` | `{ "$template": "Hello, ${/user/name}!" }` | String interpolation. `${/path}` for state, `${name}` for $let bindings. **Does NOT resolve `$item` directly** — capture in `$let` first |
160
+ | `$computed` | `{ "$computed": "fn", "args": {...} }` | Registered function. **Prefer $math/$array/$date/$format** |
161
+ | `$uniqueId` | `{ "$uniqueId": true, "source": { "$state": "/items" }, "field": "id", "prefix": "item-", "padding": 2 }` | First unused deterministic id in a source array |
162
+
163
+ ### Conditionals & Logic
164
+
165
+ `$cond` — conditional value:
166
+ ```json
167
+ { "$cond": { "$state": "/form/isValid" }, "$then": "green", "$else": "gray" }
168
+ { "$cond": { "$item": "priority", "eq": "urgent" }, "$then": "#EF4444", "$else": "#22C55E" }
169
+ ```
170
+ Operators: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `not`.
171
+
172
+ **Trap:** `$state` with `eq` only works as boolean in `visible`. For `disabled`/other props, wrap in `$cond`: `{ "$cond": { "$state": "/x", "eq": 0 }, "$then": true, "$else": false }`
173
+
174
+ `$switch` — multi-branch (use for 3+ branches instead of nested $cond):
175
+ ```json
176
+ { "$switch": { "$state": "/type" }, "cases": { "1": "Expense", "2": "Income" }, "default": "Other" }
177
+ ```
178
+ `default` is required.
179
+
180
+ `$and` / `$or` / `$not` — boolean logic:
181
+ ```json
182
+ { "$and": [{ "$state": "/form/name" }, { "$state": "/form/price" }] }
183
+ { "$not": { "$state": "/form/isValid" } }
184
+ ```
185
+
186
+ ### Responsive & Cross-Platform
187
+
188
+ `$breakpoint` — viewport-based values:
189
+ ```json
190
+ { "$breakpoint": { "sm": 1, "md": 2, "lg": 3 } }
191
+ ```
192
+ Default breakpoints: sm: 0, md: 768, lg: 1024, xl: 1280.
193
+
194
+ **Always use `$breakpoint` for layout properties.** Every spec should be responsive by default — never hardcode desktop-only values for these properties:
195
+
196
+ | Property | Mobile (sm) | Tablet (md) | Desktop (lg+) |
197
+ |----------|------------|-------------|----------------|
198
+ | `direction` | `"vertical"` | `"horizontal"` | `"horizontal"` |
199
+ | `columns` | `1` | `2` | `3-4` |
200
+ | `gap` | `12` | `16` | `24` |
201
+ | `padding` | `"16px"` | `"24px"` | `"32px"` |
202
+
203
+ Example — responsive grid layout:
204
+ ```json
205
+ {
206
+ "type": "grid",
207
+ "props": { "columns": { "$breakpoint": { "sm": 1, "md": 2, "lg": 3 } } },
208
+ "style": {
209
+ "gap": { "$breakpoint": { "sm": "12px", "md": "16px", "lg": "24px" } },
210
+ "padding": { "$breakpoint": { "sm": "16px", "md": "24px", "lg": "32px" } }
211
+ }
212
+ }
213
+ ```
214
+
215
+ `$platform` — cross-platform values:
216
+ ```json
217
+ { "$platform": { "web": "blur(24px)", "native": null } }
218
+ { "$platform": { "web": "layout-web", "native": "layout-native" } }
219
+ ```
220
+ Resolves by current platform. `"native"` alias matches ios and android. Specific keys (`ios`, `android`) override `"native"`. If no key matches, resolves to `undefined` — always provide keys for all target platforms.
221
+
222
+ **When to use `$platform` vs `$breakpoint`:**
223
+ - `$breakpoint`: Layout adaptation (columns, gaps, padding, direction) — same component, different sizing
224
+ - `$platform`: Platform-specific techniques (CSS blur vs native BlurView, hover vs press, web sidebar vs native tabs) — different implementation, same feature
225
+
226
+ **Root-level `$platform`** — for fundamentally different platform layouts:
227
+ ```json
228
+ {
229
+ "root": { "$platform": { "web": "layout-web", "native": "layout-native" } },
230
+ "elements": {
231
+ "layout-web": { "type": "stack", "style": { "backdropFilter": "blur(24px)" } },
232
+ "layout-native": { "type": "screen", "props": { "title": "Dashboard" } },
233
+ "shared-form": { "type": "stack", "children": ["..."] }
234
+ }
235
+ }
236
+ ```
237
+ State, initialActions, and forms are shared — only presentation branches per platform.
238
+
239
+ ### Math & Data
240
+
241
+ `$math`:
242
+ ```json
243
+ { "$math": "multiply", "args": [{ "$state": "/price" }, { "$state": "/qty" }] }
244
+ { "$math": "round", "value": 3.14, "decimals": 2 }
245
+ ```
246
+ Operations: `add`, `subtract`, `multiply`, `divide`, `round`, `floor`, `ceil`, `abs`, `min`, `max`, `mod`. Undefined args → 0.
247
+
248
+ `$array`:
249
+ ```json
250
+ { "$array": "count", "source": { "$state": "/items" } }
251
+ { "$array": "filter", "source": { "$state": "/items" }, "where": { "field": "status", "eq": "active" } }
252
+ { "$array": "sum", "source": { "$state": "/items" }, "field": "price" }
253
+ { "$array": "sumProduct", "source": { "$state": "/items" }, "field1": "price", "field2": "qty" }
254
+ { "$array": "search", "source": { "$state": "/items" }, "query": { "$state": "/search" }, "fields": ["name"] }
255
+ { "$array": "sort", "source": { "$state": "/items" }, "field": "name", "direction": "asc" }
256
+ { "$array": "slice", "source": { "$state": "/items" }, "from": 0, "to": 10 }
257
+ { "$array": "append", "source": { "$state": "/items" }, "value": { "name": "New" } }
258
+ { "$array": "replace", "source": { "$state": "/items" }, "where": { "field": "id", "eq": 1 }, "value": { "name": "Updated" } }
259
+ { "$array": "remove", "source": { "$state": "/items" }, "where": { "field": "id", "eq": 3 } }
260
+ { "$array": "toggle", "source": { "$state": "/ids" }, "value": 5 }
261
+ { "$array": "find", "source": { "$state": "/items" }, "where": { "field": "id", "eq": 1 } }
262
+ { "$array": "includes", "source": { "$state": "/tags" }, "value": "urgent" }
263
+ { "$array": "map", "source": { "$state": "/items" }, "field": "name" }
264
+ { "$array": "first", "source": { "$state": "/items" } }
265
+ { "$array": "last", "source": { "$state": "/items" } }
266
+ ```
267
+ Where operators: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `notIn`. **Use `value` not `item` for append/replace.**
268
+
269
+ **`where` accepts ONE field + ONE operator only** — no `$and`/`$or`. For multiple conditions, chain filters:
270
+ ```json
271
+ { "$array": "filter", "source": { "$array": "filter", "source": { "$state": "/items" }, "where": { "field": "price", "gte": 10 } }, "where": { "field": "price", "lte": 100 } }
272
+ ```
273
+
274
+ `$date`:
275
+ ```json
276
+ { "$date": "now" }
277
+ { "$date": "today" }
278
+ { "$date": "age", "from": { "$state": "/birthDate" } }
279
+ { "$date": "diff", "from": { "$state": "/start" }, "to": { "$state": "/end" }, "unit": "days" }
280
+ { "$date": "format", "value": { "$state": "/date" }, "pattern": "short" }
281
+ { "$date": "add", "value": { "$state": "/date" }, "amount": 7, "unit": "days" }
282
+ ```
283
+ Units: `days`, `months`, `years`, `hours`, `minutes`. Patterns: `short`, `long`, `numeric`, `time`, `datetime`.
284
+
285
+ `$format`:
286
+ ```json
287
+ { "$format": "currency", "value": { "$state": "/price" }, "currency": "USD" }
288
+ { "$format": "number", "value": 1234.5, "decimals": 2 }
289
+ { "$format": "percent", "value": 0.75 }
290
+ { "$format": "phone", "value": { "$state": "/phone" } }
291
+ { "$format": "uppercase", "value": { "$state": "/name" } }
292
+ { "$format": "lowercase", "value": "HELLO" }
293
+ { "$format": "capitalize", "value": "hello world" }
294
+ { "$format": "truncate", "value": "long text...", "length": 20 }
295
+ ```
296
+ Extended: `locale`, `notation` (compact/scientific), `signDisplay` (always/exceptZero), `useGrouping`.
297
+
298
+ ### Named Bindings
299
+
300
+ `$let` / `$ref` — define once, use many times:
301
+ ```json
302
+ { "$let": { "total": { "$array": "count", "source": { "$state": "/items" } } }, "$in": { "$ref": "total" } }
303
+ ```
304
+ **JSONB array format** (when stored in DB, order matters):
305
+ ```json
306
+ { "$let": [["filtered", { "$array": "filter", "source": { "$state": "/items" }, "where": { "field": "status", "eq": "active" } }], ["count", { "$array": "count", "source": { "$ref": "filtered" } }]], "$in": { "$ref": "count" } }
307
+ ```
308
+
309
+ ### Group & Selection (inside repeat)
310
+
311
+ `$group` (inside repeat.groupBy):
312
+ ```json
313
+ { "$group": "key" }
314
+ { "$group": "count" }
315
+ { "$group": "sum", "field": "amount" }
316
+ ```
317
+ Operations: `key`, `count`, `index`, `items`, `sum`, `avg`, `min`, `max`. Dot-notation for pre-grouped: `{ "$group": "subtotal.total" }`. **Only valid inside groupBy context.**
318
+
319
+ `$selection` (inside repeat.selection):
320
+ ```json
321
+ { "$selection": "selected" }
322
+ { "$selection": "count" }
323
+ ```
324
+ **Only valid inside repeat with selection config.**
325
+
326
+ ## Primitives
327
+
328
+ 38 built-in visual building blocks. **See [ai-context-primitives.md](ai-context-primitives.md) for complete props reference.**
329
+
330
+ **Layout:** `box`, `text`, `image`, `icon`, `stack`, `grid`, `scroll`, `divider`, `spacer`
331
+ **Form:** `input`, `textarea`, `select`, `checkbox`, `toggle`, `slider`
332
+ **Interaction:** `button`, `touchable`, `list`
333
+ **Overlays:** `modal`, `drawer`, `tabs`, `accordion`, `wizard`, `screen`
334
+ **Charts:** `bar-chart`, `line-chart`, `pie-chart`, `area-chart`, `table`, `kanban-board`
335
+ **Spatial:** `spatial-map`
336
+ **Special:** `file-upload`, `camera`, `signature`, `audio-player`, `skeleton`, `toast-container`
337
+
338
+ All primitives accept `style`, `visible`, and `permission`. Tokens are project-defined — no framework defaults. Device context auto-tracked at `/ui/device/*` (viewportWidth, viewportHeight, platform, orientation, colorScheme).
339
+
340
+ ## Actions
341
+
342
+ Wire to events with `on`: `{ "on": { "press": { "action": "...", "params": {...} } } }`
343
+
344
+ Arrays execute sequentially: `"press": [action1, action2, action3]`
345
+
346
+ **Trap:** Action chains don't stop on failure — `validateForm` marks errors but does NOT halt the chain. Use `submitForm` with `formId` instead (validates + blocks if invalid). See [ai-context-patterns.md](ai-context-patterns.md).
347
+
348
+ Add `"fireAndForget": true` to dispatch without waiting (background re-fetch after closing modal).
349
+
350
+ ### Action Reference
351
+
352
+ | Action | Params | Purpose |
353
+ |--------|--------|---------|
354
+ | `setState` | `{ statePath, value }` | Set state value (value can contain expressions) |
355
+ | `navigateScreen` | `{ screen, ...params }` | Navigate to screen (use this, not `navigate`) |
356
+ | `goBackScreen` | — | Go to previous screen via history (use this, not `goBack`) |
357
+ | `openModal` | `{ id }` | Show modal |
358
+ | `closeModal` | `{ id }` | Hide modal |
359
+ | `openDrawer` | `{ id }` | Open drawer |
360
+ | `closeDrawer` | `{ id }` | Close drawer |
361
+ | `showNotification` | `{ message, type, title?, duration? }` | Toast notification |
362
+ | `dismissNotification` | `{ id }` | Remove toast by id |
363
+ | `toggleTheme` | — | Switch dark/light |
364
+ | `setLocale` | `{ locale }` | Change language |
365
+ | `copyToClipboard` | `{ value }` | Copy to clipboard |
366
+ | `openUrl` | `{ url }` | Open external URL |
367
+ | `fetch` | `{ url, method, body, target, headers }` | HTTP request → target state path |
368
+ | `submitForm` | `{ formId?, url, method, body, target }` | Validate + fetch + notification |
369
+ | `login` | `{ email, password }` | Auth via provider → `/auth/*` state |
370
+ | `logout` | — | Clear session, navigate to loginScreen |
371
+ | `refreshSession` | — | Manual token refresh |
372
+ | `validateForm` | `{ formId }` | Touch all fields + validate |
373
+ | `touchField` | `{ formId, field }` | Touch + validate one field |
374
+ | `resetForm` | `{ formId }` | Reset form to initial values |
375
+ | `uploadFile` | `{ bucket, target, path? }` | Upload via StorageAdapter |
376
+ | `deleteFile` | `{ path, bucket }` | Delete from storage |
377
+ | `export` | `{ source, columns, filename, format? }` | Export data (csv built-in) |
378
+ | `toggleSelection` | `{ statePath, value, mode? }` | Add/remove from selection array |
379
+ | `selectAll` | `{ statePath, values }` | Set selection array |
380
+ | `selectNone` | `{ statePath }` | Clear selection |
381
+ | `refreshDataSource` | `{ id }` | Force re-fetch a dataSource |
382
+
383
+ ### fetch Details
384
+
385
+ - Body expressions are deeply resolved before sending
386
+ - Empty strings in body → `null` (prevents DB errors)
387
+ - Sets `/ui/loading` while in flight
388
+ - On error: sets `/ui/lastError` with status and message
389
+ - Auth headers auto-injected for `authDomains` URLs
390
+
391
+ ### Transactions (Optimistic Updates)
392
+
393
+ Use `transaction` for CRUD operations. Instant UI → server confirm → auto-rollback on failure.
394
+
395
+ ```json
396
+ {
397
+ "on": {
398
+ "press": {
399
+ "transaction": {
400
+ "before": [
401
+ { "action": "closeModal", "params": { "id": "{{MODAL_ID}}" } }
402
+ ],
403
+ "optimistic": [
404
+ { "action": "setState", "params": {
405
+ "statePath": "{{ARRAY_PATH}}",
406
+ "value": { "$array": "append", "source": { "$state": "{{ARRAY_PATH}}" }, "value": {
407
+ "id": { "$template": "temp-${/form/title}" },
408
+ "{{FIELD}}": { "$state": "/form/{{FIELD}}" }
409
+ }}
410
+ }}
411
+ ],
412
+ "confirm": [
413
+ { "action": "fetch", "params": {
414
+ "method": "POST", "url": "{{API_URL}}",
415
+ "headers": { "Prefer": "return=representation" },
416
+ "body": { "{{FIELD}}": { "$state": "/form/{{FIELD}}" } },
417
+ "target": "/tx/result"
418
+ }}
419
+ ],
420
+ "onSuccess": [
421
+ { "action": "fetch", "params": { "method": "GET", "url": "{{API_URL}}?select=*", "target": "{{ARRAY_PATH}}" } }
422
+ ],
423
+ "onError": [
424
+ { "action": "showNotification", "params": { "type": "error", "message": "Could not save." } }
425
+ ]
426
+ }
427
+ }
428
+ }
429
+ }
430
+ ```
431
+
432
+ **Phase rules:**
433
+ - `before` — UI transitions, NOT rolled back (closeModal, navigate)
434
+ - `optimistic` — data changes, ROLLED BACK on error (setState for data + form reset)
435
+ - `confirm` — network request, determines success. Write to `/tx/result` via target
436
+ - `onSuccess` — post-success sync (re-fetch). `$state: "/tx/result"` reads confirm result
437
+ - `onError` — runs after rollback. `$state: "/tx/error"` has `{ message }`
438
+
439
+ **CRUD variations:**
440
+
441
+ | Operation | optimistic | confirm | onSuccess | Notes |
442
+ |-----------|-----------|---------|-----------|-------|
443
+ | CREATE | `$array: "append"` with temp id | POST | GET re-fetch | Re-fetch replaces temp with real id |
444
+ | UPDATE | `$array: "replace"` by id | PATCH `?id=eq.${id}` | **None** | Optimistic data is correct — re-fetch causes flash |
445
+ | DELETE | `$array: "remove"` by id | DELETE `?id=eq.${id}` | **None** | — |
446
+ | TOGGLE | `$not` on boolean path | PATCH | **None** | No `before` — no modal |
447
+
448
+ **Timeout:** Default 10s. Override: `{ "transaction": { "timeout": 30000, ... } }`
449
+
450
+ **Legacy (no optimistic):** Sequential action array: `[closeModal, fetch POST, fetch GET]`. Prefer transactions.
451
+
452
+ ## Validation
453
+
454
+ ```json
455
+ { "type": "input", "props": { "value": { "$bindState": "/form/email" }, "checks": [
456
+ { "type": "required", "message": "Required" },
457
+ { "type": "email", "message": "Invalid email" }
458
+ ], "validateOn": "blur" } }
459
+ ```
460
+
461
+ | Validator | Args | Purpose |
462
+ |-----------|------|---------|
463
+ | `required` | — | Non-empty |
464
+ | `email` | — | Email format |
465
+ | `minLength` / `maxLength` | `{ min }` / `{ max }` | String length |
466
+ | `pattern` | `{ pattern }` | Regex |
467
+ | `min` / `max` | `{ min }` / `{ max }` | Number range |
468
+ | `numeric` | — | Must be number |
469
+ | `url` | — | Valid URL |
470
+ | `matches` / `equalTo` | `{ other }` | Must equal another field |
471
+ | `greaterThan` / `lessThan` | `{ other }` | Compare to another field |
472
+ | `requiredIf` | `{ field }` | Required when `field` value is truthy. **Truthy check only** — does not support `eq` for specific values. To require based on a specific value, use a `$cond` to compute a boolean and reference that in `field` |
473
+
474
+ ## Repeat
475
+
476
+ ```json
477
+ "task-list": {
478
+ "type": "stack",
479
+ "repeat": { "statePath": "/tasks", "key": "id" },
480
+ "children": ["task-row"]
481
+ }
482
+ ```
483
+
484
+ Filtered/paginated: use `source` instead of `statePath`:
485
+ ```json
486
+ "repeat": {
487
+ "source": { "$array": "filter", "source": { "$state": "/tasks" }, "where": { "field": "status", "eq": "active" } },
488
+ "key": "id"
489
+ }
490
+ ```
491
+ Chain: `$array: "filter"` → `$array: "search"` → `$array: "slice"` for filter + search + pagination.
492
+
493
+ Inside repeated elements: `$item`, `$index`, `$bindItem` access current item.
494
+
495
+ ### Grouped Repeat
496
+
497
+ **Client-side** (engine groups flat array): `groupBy: "category"`
498
+ **Pre-grouped** (server already grouped): `groupKey: "name"` + `groupItems: "rows"`
499
+
500
+ ```json
501
+ "repeat": {
502
+ "source": { "$state": "/tasks" }, "key": "id",
503
+ "groupBy": "category",
504
+ "groupHeader": ["header-el"], "groupFooter": ["footer-el"],
505
+ "footer": ["grand-total"]
506
+ }
507
+ ```
508
+ Pre-grouped data format: `[{ "name": "Group A", "rows": [...], "subtotal": { "total": 50000 } }, ...]`
509
+
510
+ In groupHeader/groupFooter: use `$group` expressions. In children: use `$item`/`$index`.
511
+
512
+ ### Repeat Selection
513
+
514
+ ```json
515
+ "repeat": {
516
+ "source": { "$state": "/tasks" }, "key": "id",
517
+ "selection": { "state": "/selectedIds", "mode": "multiple" }
518
+ }
519
+ ```
520
+ Inside: `{ "$selection": "selected" }` (boolean), `{ "$selection": "count" }`. Toggle: `toggleSelection` action.
521
+
522
+ ## Visibility
523
+
524
+ ```json
525
+ "visible": { "$state": "/user/role", "eq": "admin" }
526
+ "visible": { "$auth": "role", "eq": "admin" }
527
+ "visible": { "$and": [{ "$state": "/form/isValid" }, { "$state": "/form/hasChanges" }] }
528
+ ```
529
+
530
+ ### When to Use fetch vs dataSources
531
+
532
+ | | `initialActions` + `fetch` | `dataSources` |
533
+ |---|---|---|
534
+ | **Purpose** | One-shot load on mount, CRUD in transactions | Reactive data that re-fetches when params change |
535
+ | **Loading state** | `/ui/loading` (boolean) | `/{target}Loading` (boolean) — auto-generated |
536
+ | **Error state** | `/ui/lastError` (object) | `/{target}Error` (object) — auto-generated |
537
+ | **Re-fetch** | Manual (call fetch again) | Automatic on param change, or `refreshDataSource` |
538
+ | **Use for** | Static initial data, POST/PUT/DELETE | Lists with filters, search, pagination |
539
+
540
+ **Rule:** Don't mix both for the same data target. Pick one pattern per data source.
541
+
542
+ ### Loading/Content/Empty Pattern
543
+
544
+ **With `initialActions` fetch** (uses `/ui/loading` and `/ui/lastError`):
545
+ ```json
546
+ "loading": { "visible": { "$and": [{ "$state": "/ui/loading" }, { "$not": { "$array": "count", "source": { "$state": "/items" } } }] } },
547
+ "content": { "visible": { "$array": "count", "source": { "$state": "/items" } } },
548
+ "empty": { "visible": { "$and": [{ "$not": { "$state": "/ui/loading" } }, { "$not": { "$array": "count", "source": { "$state": "/items" } } }] } },
549
+ "error": { "visible": { "$state": "/ui/lastError" } }
550
+ ```
551
+
552
+ **With `dataSources`** (uses auto-generated `/{target}Loading` and `/{target}Error`):
553
+ ```json
554
+ "loading": { "visible": { "$and": [{ "$state": "/itemsLoading" }, { "$not": { "$array": "count", "source": { "$state": "/items" } } }] } },
555
+ "content": { "visible": { "$array": "count", "source": { "$state": "/items" } } },
556
+ "empty": { "visible": { "$and": [{ "$not": { "$state": "/itemsLoading" } }, { "$not": { "$array": "count", "source": { "$state": "/items" } } }] } },
557
+ "error": { "visible": { "$state": "/itemsError" } }
558
+ ```
559
+
560
+ ## Derived State
561
+
562
+ Auto-computed reactive values. Declared at spec level. Read-only — StateGuard blocks writes.
563
+
564
+ ```json
565
+ {
566
+ "derive": {
567
+ "/stats/total": { "$array": "count", "source": { "$state": "/items" } },
568
+ "/stats/avg": { "$math": "divide", "args": [
569
+ { "$array": "sum", "source": { "$state": "/items" }, "field": "price" },
570
+ { "$array": "count", "source": { "$state": "/items" } }
571
+ ]}
572
+ }
573
+ }
574
+ ```
575
+ Derive A can reference Derive B (no cycles). Dependency-tracked — only re-evaluates on change.
576
+
577
+ **Warning:** `derive` operates on data in state only. With server-side pagination, state holds the current page — derive sums/counts will reflect the page, not the full dataset. For full-dataset totals with server pagination, fetch totals from the API.
578
+
579
+ ## Forms
580
+
581
+ Declarative form-level validation. Coordinates fields as a unit.
582
+
583
+ ```json
584
+ {
585
+ "forms": {
586
+ "task-form": {
587
+ "fields": {
588
+ "title": { "statePath": "/form/title", "rules": [{ "type": "required", "message": "Required" }] },
589
+ "email": { "statePath": "/form/email", "rules": [{ "type": "required" }, { "type": "email" }] },
590
+ "maxPrice": { "statePath": "/form/maxPrice", "rules": [
591
+ { "type": "greaterThan", "args": { "other": { "$state": "/form/minPrice" } }, "message": "Max must exceed min" }
592
+ ]}
593
+ },
594
+ "validateOn": "blur"
595
+ }
596
+ }
597
+ }
598
+ ```
599
+
600
+ **Auto-generated state:**
601
+
602
+ | Path | Type | Description |
603
+ |------|------|-------------|
604
+ | `/ui/forms/{id}/isValid` | boolean | All fields valid (even untouched — for submit button) |
605
+ | `/ui/forms/{id}/errorCount` | number | Total displayed errors |
606
+ | `/ui/forms/{id}/isDirty` | boolean | Any value changed |
607
+ | `/ui/forms/{id}/fields/{field}/errors` | string[] | Error messages (shown only when touched) |
608
+ | `/ui/forms/{id}/fields/{field}/touched` | boolean | User has interacted |
609
+ | `/ui/forms/{id}/fields/{field}/dirty` | boolean | Value differs from initial |
610
+
611
+ Disable submit: `"disabled": { "$not": { "$state": "/ui/forms/task-form/isValid" } }`
612
+ Submit with gate: `{ "action": "submitForm", "params": { "formId": "task-form", "url": "...", ... } }`
613
+ Show error: `"visible": { "$array": "count", "source": { "$state": "/ui/forms/task-form/fields/title/errors" } }` with content `{ "$array": "first", "source": { "$state": "/ui/forms/task-form/fields/title/errors" } }`
614
+ Actions: `validateForm`, `touchField`, `resetForm`. `resetForm` restores state values to initial AND clears all metadata (touched, errors, dirty). Opt-in — existing inline `checks` still work.
615
+
616
+ ## DataSources
617
+
618
+ Reactive GET fetching. Makes specs self-contained.
619
+
620
+ ```json
621
+ {
622
+ "dataSources": {
623
+ "tasks": {
624
+ "url": { "$template": "${/config/apiUrl}/rest/v1/tasks?select=*" },
625
+ "headers": { "$state": "/config/headers" },
626
+ "params": {
627
+ "status": { "$state": "/filter/status" },
628
+ "search": { "$state": "/filter/search" },
629
+ "page": { "$state": "/pagination/page" }
630
+ },
631
+ "target": "/tasks",
632
+ "trigger": "auto",
633
+ "debounce": 300,
634
+ "initialFetch": true,
635
+ "emptyWhileLoading": false
636
+ }
637
+ }
638
+ }
639
+ ```
640
+
641
+ | Property | Default | Description |
642
+ |----------|---------|-------------|
643
+ | `trigger` | `"auto"` | `auto`: re-fetch on param change. `manual`: only via `refreshDataSource` |
644
+ | `debounce` | `0` | Debounce ms for auto-trigger |
645
+ | `initialFetch` | `true` | Fetch on mount |
646
+ | `emptyWhileLoading` | `false` | Clear target while loading |
647
+
648
+ Auto-generated: `/tasks` (data), `/tasksLoading` (boolean), `/tasksError` (error or null).
649
+ Param filtering: `null`, `""`, `"all"` → omitted from query. Headers from state, NOT from spec (no keys in DB).
650
+
651
+ **`derive` and `dataSources` runtime lifecycle (v0.1.0 — Item E)**: both features execute at runtime per spec mount via internal `mountSpecRuntime` helper called from MythikRenderer (web + RN). Lifecycle: derive engine mounts first (sync), populates derive paths from current state, subscribes for reactive recompute. dataSources engine mounts second; initial fetch is skipped when URL template dependencies are undefined/null/empty — `/{target}Deferred: true` is set so consumers can render "waiting for prerequisite" UI distinct from `/{target}Loading`. The reactive subscription catches up when deps resolve. Engines self-coordinate via reactive subscriptions — no ordering dependency on `initialActions`. Renderers declare the state subscription useEffect BEFORE mountSpecRuntime so synchronous derive writes on mount trigger initial-paint correctly. URL templating requires the explicit `{ $template: '/api/${/path}' }` form; plain strings containing `${...}` are flagged as load-time validation errors (resolver does NOT substitute plain strings).
652
+
653
+ ## Templates
654
+
655
+ Reusable element definitions within specs. Reduces repetition.
656
+
657
+ ```json
658
+ {
659
+ "templates": {
660
+ "monetary-col": {
661
+ "type": "text",
662
+ "defaults": { "color": "#0F172A", "currency": "HNL" },
663
+ "props": { "content": { "$format": "currency", "value": { "$prop": "value" }, "currency": { "$prop": "currency" }, "locale": "es-HN" } },
664
+ "style": { "textAlign": "right", "fontFamily": "monospace", "color": { "$prop": "color" } }
665
+ }
666
+ },
667
+ "elements": {
668
+ "col-amount": { "type": "monetary-col", "props": { "value": { "$item": "amount" } } },
669
+ "col-total": { "type": "monetary-col", "props": { "value": { "$item": "total" }, "color": "#D97706" } }
670
+ }
671
+ }
672
+ ```
673
+
674
+ Element props override template `defaults`. `$prop` references merged props. Use `"$children"` marker to insert consuming element's children. Templates in AppSpec are available to all screens. Screen templates override app-level with same name.
675
+
676
+ **Composite templates** use `$let` to bridge `$prop` into `$template`:
677
+ ```json
678
+ "stat-card": {
679
+ "type": "text",
680
+ "defaults": { "label": "Count", "value": 0 },
681
+ "props": {
682
+ "content": { "$let": { "l": { "$prop": "label" }, "v": { "$prop": "value" } }, "$in": { "$template": "${l}: ${v}" } }
683
+ },
684
+ "style": { "padding": 16, "backgroundColor": { "$token": "colors.surface" } }
685
+ }
686
+ ```
687
+ Templates are **single elements** — one `type` with props/style/defaults. For multi-element compositions, the consuming element defines children alongside the template type.
688
+
689
+ ## AppSpec & Navigation
690
+
691
+ Multi-screen app with sidebar, auth, shared state. 100% opt-in.
692
+
693
+ ```json
694
+ {
695
+ "type": "app",
696
+ "name": "my-app",
697
+ "navigation": {
698
+ "type": "sidebar",
699
+ "initialScreen": "dashboard",
700
+ "breadcrumb": "history",
701
+ "menu": ["dashboard", "reports", "settings"],
702
+ "auth": {
703
+ "provider": "supabase",
704
+ "loginScreen": "login",
705
+ "protectedScreens": ["*"],
706
+ "roleAccess": { "admin": ["*"], "user": ["dashboard", "profile"] },
707
+ "persistence": "local",
708
+ "tokenRefresh": true,
709
+ "authDomains": ["myproject.supabase.co"],
710
+ "sessionExpiredMessage": "Session expired, please sign in again"
711
+ }
712
+ },
713
+ "screens": {
714
+ "dashboard": { "label": "Dashboard", "icon": "chart-bar", "statePolicy": "preserve" },
715
+ "new-item": { "label": "New", "icon": "plus", "statePolicy": "reset", "parent": "dashboard" },
716
+ "login": { "label": "Login", "icon": "sign-in", "statePolicy": "reset" }
717
+ },
718
+ "tokens": { "colors": { "primary": "#0D9488" } },
719
+ "sharedState": { "preferences": { "theme": "light" } },
720
+ "templates": { },
721
+ "layout": {
722
+ "root": "shell",
723
+ "elements": {
724
+ "shell": { "type": "stack", "props": { "direction": "horizontal" }, "children": ["sidebar", "screen-outlet"] },
725
+ "sidebar": { "type": "box", "children": ["nav"] },
726
+ "screen-outlet": { "type": "screen-outlet", "style": { "flex": 1 } }
727
+ }
728
+ }
729
+ }
730
+ ```
731
+
732
+ ### AppSpec Properties
733
+
734
+ | Property | Type | Required | Purpose |
735
+ |----------|------|----------|---------|
736
+ | `type` | `"app"` | yes | Identifies as AppSpec |
737
+ | `name` | string | no | App display name |
738
+ | `navigation` | object | yes | Navigation config (see below) |
739
+ | `screens` | object | yes | Screen definitions: `{ id: { label, icon, statePolicy, parent?, roles? } }` |
740
+ | `tokens` | object | no | Design tokens (colors, spacing, components). Available to all screens |
741
+ | `sharedState` | object | no | Initial shared state. Keys become root state paths (e.g., `"preferences"` → `/preferences`) |
742
+ | `templates` | object | no | Shared templates available to all screens |
743
+ | `translations` | object | no | i18n translations |
744
+ | `layout` | object | yes | `{ root, elements }` — sidebar + screen-outlet layout |
745
+
746
+ ### Navigation Properties
747
+
748
+ | Property | Type | Required | Purpose |
749
+ |----------|------|----------|---------|
750
+ | `type` | `"sidebar"` | yes | Navigation style |
751
+ | `initialScreen` | string | yes | Default screen on app load |
752
+ | `breadcrumb` | string | no | `"history"` (nav stack), `"hierarchy"` (parent chain), `"none"` |
753
+ | `menu` | string[] | no | Sidebar screen order. Omit to show all screens. Login always excluded |
754
+ | `auth` | object | no | Auth config (loginScreen, protectedScreens, roleAccess, etc.) |
755
+
756
+ ### State Policies
757
+
758
+ | Policy | On leave | On return | Use for |
759
+ |--------|----------|-----------|---------|
760
+ | `preserve` | Keep state | Restore | Lists, dashboards |
761
+ | `reset` | Clear | Fresh initialState | Create forms |
762
+ | `reload` | Clear | Re-execute initialActions | Always-fresh data |
763
+
764
+ ### Access Control
765
+
766
+ **`roleAccess` (recommended):** centralized, sole source of truth when present. Roles not listed = zero access.
767
+ **`ScreenDefinition.roles`:** fallback when `roleAccess` absent. `["*"]` = any role.
768
+ loginScreen is always accessible. Unauthenticated → redirect to login. Authenticated but unauthorized → stay + error (no redirect).
769
+
770
+ ### Auto-Generated State
771
+
772
+ | Path | Content |
773
+ |------|---------|
774
+ | `/navigation/currentScreen` | Active screen ID |
775
+ | `/navigation/history` | Visited screen IDs |
776
+ | `/navigation/breadcrumb` | Enriched array with label, icon |
777
+ | `/app/screens` | Accessible screens (filtered by role, excludes loginScreen) |
778
+
779
+ Sidebar auto-refreshes on auth changes. Breadcrumb modes: `history` (navigation stack), `hierarchy` (parent chain), `none`.
780
+
781
+ **Sidebar navigation** is built from `/app/screens` (auto-generated, filtered by role). Use a `repeat` on `/app/screens` to render nav items — each item has `id`, `label`, `icon`.
782
+
783
+ ### Auth Config
784
+
785
+ Persistence: `"local"` (survives browser close), `"session"` (lost on close), `"memory"` (lost on refresh).
786
+
787
+ Interceptors:
788
+ ```json
789
+ "interceptors": { "logging": true, "timeout": { "ms": 15000 }, "retryOnError": { "maxRetries": 2, "statuses": [502, 503] } }
790
+ ```
791
+
792
+ Security: tokens NEVER in state (engine closure only). `$auth` blocks token/password fields. Auth headers only for `authDomains`. Credentials cleared after login. Rate limit: 5/min. Cross-tab sync automatic.
793
+
794
+ Custom JWT provider response mapping: `tokenPath`, `refreshTokenPath`, and `userPath` are dot paths against the full login/refresh response. `rolePath` and `rolesPath` use a compat dual contract: plain keys like `"role"` / `"roles"` resolve inside the extracted `userPath` object; dotted paths like `"user.role"` or `"data.user.role"` resolve against the full response. If no role or roles are found, Mythik uses `defaultRole` (`"user"` by default) and warns in development.
795
+
796
+ ### Login Screen
797
+
798
+ **Use `/screens/login/...` paths** (not `/form/...`). Combined with `statePolicy: "reset"`, credentials clear on logout.
799
+
800
+ ```json
801
+ {
802
+ "root": "login-page",
803
+ "elements": {
804
+ "login-page": { "type": "box", "style": { "display": "flex", "alignItems": "center", "justifyContent": "center", "minHeight": "100vh" }, "children": ["card"] },
805
+ "card": { "type": "box", "style": { "width": 400, "padding": 32, "borderRadius": 16 }, "children": ["email", "pass", "error", "btn"] },
806
+ "email": { "type": "input", "props": { "placeholder": "Email", "value": { "$bindState": "/screens/login/email" } } },
807
+ "pass": { "type": "input", "props": { "placeholder": "Password", "type": "password", "value": { "$bindState": "/screens/login/password" } } },
808
+ "error": { "type": "text", "visible": { "$auth": "error" }, "props": { "content": { "$auth": "error" } }, "style": { "color": "#EF4444" } },
809
+ "btn": { "type": "button", "props": { "label": { "$cond": { "$auth": "loading" }, "$then": "Signing in...", "$else": "Login" }, "disabled": { "$auth": "loading" } },
810
+ "on": { "press": { "action": "login", "params": { "email": { "$state": "/screens/login/email" }, "password": { "$state": "/screens/login/password" } } } }
811
+ }
812
+ }
813
+ }
814
+ ```
815
+
816
+ Login renders fullscreen (no sidebar). After login, layout appears reactively.
817
+
818
+ `$auth` fields: `isAuthenticated`, `id`, `email`, `name`, `avatar`, `role`, `roles`, `metadata`, `metadata.*`, `user`, `loading`, `error`. Blocked: `token`, `accessToken`, `password`, `secret`, `session`.
819
+
820
+ Auth state paths (read-only, auto-managed): `/auth/isAuthenticated`, `/auth/loading`, `/auth/error`, `/auth/user/id`, `/auth/user/email`, `/auth/user/name`, `/auth/user/role`, `/auth/user/roles`, `/auth/user/metadata`. Protected by StateGuard.
821
+
822
+ ### Cross-Screen Data Flow
823
+
824
+ **Master → Detail via framework-reserved `/ui/selectedRow`:**
825
+ ```json
826
+ // List screen: row click (framework auto-writes row to /ui/selectedRow) + navigate
827
+ "onRowClick": [
828
+ { "action": "navigateScreen", "params": { "screen": "item-detail" } }
829
+ ]
830
+
831
+ // Detail screen: reads /ui/selectedRow directly
832
+ "props": { "content": { "$state": "/ui/selectedRow/name" } }
833
+ ```
834
+
835
+ The framework writes the clicked row to `/ui/selectedRow` before dispatching `onRowClick` actions (see `ai-context-runtime-semantics.md § 2.1` + § 5.1). No explicit `setState` needed to capture the row. Do NOT use the literal string `"$row"` — there is no `$row` expression.
836
+
837
+ **Column action buttons follow the same pattern.** When a button in `columns[].actions[]` is clicked, the framework auto-writes the row to `/ui/selectedRow` before dispatching the action chain. The action's `$state` / `$template` params resolve at press time (lazy, not render-time). See `ai-context-runtime-semantics.md § 1.3`.
838
+
839
+ **Navigation with params:**
840
+ ```json
841
+ // Source: navigate with extra params
842
+ { "action": "navigateScreen", "params": { "screen": "profile", "employeeId": 42 } }
843
+
844
+ // Target: read /navigation/params
845
+ "props": { "content": { "$state": "/navigation/params/employeeId" } }
846
+ ```
847
+
848
+ `/navigation/params` is reset on each navigation. Use `/ui/selected*` for data that persists across back-navigation.
849
+
850
+ ### Fullstack Coherence (API + Frontend)
851
+
852
+ When generating both API spec and frontend screens:
853
+ - Frontend `fetch` URLs must match API `endpoint.path` values
854
+ - Frontend filter dropdown options must match API `catalogs` static values
855
+ - Frontend CRUD transaction methods (POST/PUT/DELETE) must match API endpoint methods
856
+ - API `policies` role lists should align with AppSpec `roleAccess`
857
+ - API `scopeFilter.bypassRoles` should include the same admin roles as AppSpec
858
+
859
+ ## Interactive States & Animations
860
+
861
+ ### Hover / Active / Focus
862
+
863
+ ```json
864
+ "hover": { "scale": 1.03, "backgroundColor": "#F1F5F9" },
865
+ "active": { "scale": 0.97 },
866
+ "focus": { "boxShadow": "0 0 0 3px rgba(13,148,136,0.3)" },
867
+ "transition": { "duration": 150, "ease": "easeOut" }
868
+ ```
869
+
870
+ Transform props (`scale`, `x`, `y`, `rotate`, `scaleX`, `scaleY`) → Motion wrapper. CSS props → pseudo-classes (no extra DOM). Buttons/touchables have built-in transitions — only add for custom behavior. CSS hover works on: `box`, `text`, `stack`, `grid`, `scroll`, `button`, `touchable`, `table`.
871
+
872
+ ### Mount/Exit Animations
873
+
874
+ Two systems coexist. Prefer `animations` (engine) for new specs — it's cross-platform (web + RN), reduced-motion aware, and integrates with the animation engine's 15 curated recipes. `motion` is the legacy Framer-Motion-style field kept for backward compat.
875
+
876
+ **Animation engine (`animations` field — preferred):**
877
+ ```json
878
+ "animations": { "mount": { "recipe": "fade-up" }, "hover": { "recipe": "lift" } }
879
+ "animations": { "mount": [{ "recipe": "fade" }, { "recipe": "scale-in" }] }
880
+ "animations": { "ambient": { "recipe": "breathe-subtle" }, "active": { "recipe": "pop" } }
881
+ "animations": { "stateChange": { "watch": "/cart/count", "on": "increase", "recipe": "pop", "duration": 300 } }
882
+ ```
883
+ - 15 recipes: `fade`, `fade-up`, `fade-down`, `scale-in`, `slide-left`, `slide-right`, `lift`, `glow`, `pulse-primary`, `breathe-subtle`, `shimmer`, `float`, `pop`, `shake`, `spin`
884
+ - `glow` is WEB-ONLY (colored boxShadow halo; RN no-op until shadow parsing ships)
885
+ - Array per trigger = parallel animations (soft-cap 3, hard-cap 6 per trigger; 5/7 triggers soft/hard)
886
+
887
+ **Cascade — declare `animations` at any of five levels**:
888
+
889
+ 1. `tokens.identity.animations` — app-wide defaults (e.g. every element mounts with `fade-up`). Applies to every element, including primitives **inside** custom element expansions.
890
+ 2. `tokens.components.<type>.<variantName>.animations` OR `ElementDefinition.variants[name].animations` — per-variant overrides (e.g. the `ctaPulse` button variant adds `ambient: pulse-primary`). For custom elements, `ElementDefinition.variants` is checked first, then `tokens.components[type].variants` as theme-level fallback.
891
+ 3. **`elementDef`** — the author's declaration on a primitive inside a custom element's render tree. Present **only** inside custom element expansions; undefined everywhere else (inheritance-neutral). Lets authors ship per-primitive animation defaults that survive identity cascade without being overridable by the consumer.
892
+ 4. `spec.templates.<templateName>.animations` — per-template overrides; supports `$prop`/`$state`/`$cond` interpolation against the consuming element's props.
893
+ 5. `element.animations` — per-element overrides; wins over all other levels. For custom element instances, applies **only** to the outer primitive of the expansion (black-box boundary).
894
+
895
+ Merge order is identity → variant → elementDef → template → element, per-trigger. Later levels override earlier. Non-overlapping triggers from different levels combine (identity's `mount` + variant's `ambient` + element's `hover` all apply together). `$state`/`$cond`/`$token`/`$prop` expressions resolve inside any level before merging.
896
+
897
+ Null semantics (precise):
898
+ - Per-trigger `null` at any level (e.g. `element.animations: { hover: null }`) disables that trigger and blocks inheritance. Use to opt-out of an inherited default.
899
+ - Whole-field `null` (e.g. `variant.animations: null`) is inheritance-neutral — that level contributes nothing, but earlier levels still apply. Equivalent to omitting the field.
900
+ - `undefined` / omitted = inherit from earlier level (pass-through).
901
+
902
+ ```json
903
+ {
904
+ "tokens": {
905
+ "identity": { "animations": { "mount": { "recipe": "fade-up" } } },
906
+ "components": {
907
+ "button": {
908
+ "cta": { "animations": { "ambient": { "recipe": "pulse-primary" } } }
909
+ }
910
+ }
911
+ },
912
+ "templates": {
913
+ "hero-card": {
914
+ "type": "box",
915
+ "animations": { "mount": { "recipe": "scale-in" }, "hover": { "recipe": "lift" } }
916
+ }
917
+ },
918
+ "elements": {
919
+ "my-card": { "type": "hero-card", "animations": { "hover": null } },
920
+ "rating": { "type": "rating-stars", "animations": { "mount": { "recipe": "scale-in" } } }
921
+ }
922
+ }
923
+ ```
924
+ Resolves: `my-card` gets `mount: scale-in` (template wins over identity), `hover` disabled (element null wins over template's lift). `rating` outer primitive gets `scale-in` (consumer wins); inner star primitives get `fade-up` from identity (consumer cannot reach them — black-box boundary).
925
+
926
+ **Legacy Framer-Motion field (`motion` — still supported):**
927
+ ```json
928
+ "motion": { "initial": { "opacity": 0, "y": 20 }, "animate": { "opacity": 1, "y": 0 }, "transition": { "duration": 0.3 } }
929
+ "motion": { "exit": { "opacity": 0, "y": -10 } }
930
+ ```
931
+ Staggered children: parent `"transition": { "staggerChildren": 0.05 }`, each child has own initial/animate. The legacy token-driven entrance injection via `identity.motionEntrance` is no longer supported — use `animations.mount` instead.
932
+
933
+ ### Deep Design Token System
934
+
935
+ Tokens go beyond colors. Every visual property reads from tokens — shape, typography, spacing, elevation, motion, opacity. Three-layer resolution: framework defaults → DNA derivation → manual overrides.
936
+
937
+ **DNA Seed** — Define 1-8 seed values; the framework derives ALL tokens automatically via OKLCH color science:
938
+
939
+ ```json
940
+ "tokens": {
941
+ "dna": {
942
+ "primary": "#0D9488",
943
+ "harmony": "analogous",
944
+ "roundness": 0.7,
945
+ "density": 0.5,
946
+ "depth": 0.6,
947
+ "motion": "fluid",
948
+ "formality": 0.3
949
+ }
950
+ }
951
+ ```
952
+
953
+ | Seed | Range | Controls |
954
+ |------|-------|----------|
955
+ | `primary` | hex | Base color → entire palette (13-stop tonal palette in OKLCH) |
956
+ | `harmony` | `complementary` \| `analogous` \| `triadic` \| `split-complementary` | How accent color relates to primary |
957
+ | `accent` | hex (optional) | Explicit accent instead of derived |
958
+ | `neutral` | `warm` \| `cool` \| `natural` | Neutral tone tint |
959
+ | `roundness` | 0–1 | Shape: 0=sharp/brutalist → 1=pill/playful |
960
+ | `density` | 0–1 | Spacing: 0=airy → 1=compact |
961
+ | `depth` | 0–1 | Shadows: 0=flat → 1=elevated |
962
+ | `motion` | `fluid` \| `snappy` \| `gentle` \| `energetic` | Animation personality |
963
+ | `formality` | 0–1 | Typography: 0=casual (Inter) → 1=formal (Playfair Display) |
964
+
965
+ **Three control levels:**
966
+
967
+ Level 1 — Minimal: `"dna": { "primary": "#0D9488" }` → full identity from 1 color.
968
+
969
+ Level 2 — Personality: `"dna": { "primary": "#0D9488", "roundness": 0.7, "motion": "fluid" }` → complete identity from 5 values.
970
+
971
+ Level 3 — Explicit override: DNA generates base, manual values override specific tokens:
972
+ ```json
973
+ "tokens": {
974
+ "dna": { "primary": "#0D9488" },
975
+ "colors": { "error": "#DC2626" },
976
+ "shape": { "radius": { "md": 24 } }
977
+ }
978
+ ```
979
+
980
+ **Token categories and paths for `$token` references:**
981
+
982
+ ```
983
+ colors.primary, colors.surface, colors.text, colors.error, colors.accent, ...
984
+ shape.radius.none/sm/md/lg/xl/full
985
+ typography.fontFamily.base/heading/mono
986
+ typography.scale.xs/sm/md/lg/xl/2xl (each has .fontSize and .lineHeight)
987
+ typography.weight.normal/medium/semibold/bold
988
+ spacing.unit, spacing.scale.xs/sm/md/lg/xl/2xl
989
+ elevation.none/sm/md/lg/xl (web: CSS boxShadow string, RN: native shadow props)
990
+ motion.duration.fast/normal/slow, motion.easing.default/enter/exit
991
+ motion.spring.damping/stiffness/mass, motion.stagger
992
+ opacity.disabled/pressed/backdrop/muted
993
+ ```
994
+
995
+ **Auto dark mode:** DNA automatically generates `modes.dark` by inverting tonal palette stops. No manual dark theme needed. Override with explicit `modes.dark` if desired.
996
+
997
+ **Font loading:** Tokens define font names (`fontFamily.heading: "Playfair Display"`) but do NOT load fonts. Web: include `@font-face` or Google Fonts link. RN: use `expo-font`. This is the project's responsibility.
998
+
999
+ **CLI inspection:** `mythik tokens --dna '{"primary":"#0D9488","roundness":0.7}' --json` shows full resolved token set.
1000
+
1001
+ ### Identity System (Forge)
1002
+
1003
+ DNA controls continuous/color values. Identity controls **categorical** visual dimensions that make apps look genuinely different:
1004
+
1005
+ ```json
1006
+ "tokens": {
1007
+ "dna": { "primary": "#0D9488", "roundness": 0.7 },
1008
+ "identity": {
1009
+ "surface": "outlined",
1010
+ "radiusPattern": "diagonal",
1011
+ "typographyHierarchy": "editorial",
1012
+ "labelStyle": "uppercase",
1013
+ "textDecoration": ["underline-accent", "shadow"]
1014
+ }
1015
+ }
1016
+ ```
1017
+
1018
+ **Surface Treatment** — how every container, input, button, modal renders:
1019
+
1020
+ | Value | Feel | Effect |
1021
+ |-------|------|--------|
1022
+ | `elevated` | Material, floating (default) | boxShadow + border + solid bg |
1023
+ | `flat` | Minimal, Notion-like | Color blocks only, no borders/shadows |
1024
+ | `outlined` | Technical, Linear-like | 1px borders, transparent bg |
1025
+ | `glass` | Premium, Apple-like | backdrop-filter blur, semi-transparent (needs dark/colored bg) |
1026
+ | `bold` | Brutalist, confident | 2-3px solid borders, no shadows |
1027
+ | `neo` | Soft 3D, tangible | Neumorphic inset+outset shadows, no borders |
1028
+
1029
+ **Radius Pattern** — asymmetric corner shapes:
1030
+ `all` (default), `top`, `bottom`, `left`, `right`, `diagonal`, `inverse-diagonal`, `single`, `single-tr`, `single-bl`, `single-br`
1031
+
1032
+ **Typography Hierarchy** — heading scale relative to body:
1033
+ `dramatic` (3×, 800w), `uniform` (1.3×, Notion-like), `editorial` (2.2×, elegant), `display` (4×, hero), `mono` (monospace), `contrast` (2.5×, ultra-thin 300w)
1034
+
1035
+ **Label Style** — form field labels: `normal`, `uppercase` (small caps + letter-spacing), `accent-colored`
1036
+
1037
+ **Text Decoration** — heading effects, **supports array for multi-select**:
1038
+ `stroke`, `underline-accent`, `highlight`, `overline`, `shadow`
1039
+
1040
+ ```json
1041
+ "textDecoration": ["underline-accent", "shadow"]
1042
+ ```
1043
+
1044
+ **Box surface prop** — IMPORTANT: use `surface="card"` on card-like boxes:
1045
+
1046
+ ```json
1047
+ "my-card": {
1048
+ "type": "box",
1049
+ "props": { "surface": "card" },
1050
+ "style": { "padding": 24 },
1051
+ "children": ["content"]
1052
+ }
1053
+ ```
1054
+
1055
+ Without `surface` prop, box is a plain layout div. With `surface="card"`, it gets identity-driven border, shadow, bg, and borderRadius. **Always use `surface="card"` for visual containers** (stat cards, form cards, content panels). Use `surface="modal"` for overlay panels.
1056
+
1057
+ **Page background** — always set the page layout bg to `colors.background`:
1058
+ ```json
1059
+ "layout": { "type": "box", "style": { "backgroundColor": { "$token": "colors.background" } } }
1060
+ ```
1061
+ This creates depth — cards (surface #fff) float on the slightly tinted background (#f8fafc).
1062
+
1063
+ **Color Scheme** — `identity.colorScheme`: `light-surface` (default), `dark-surface` (dark cards/light text), `colored-surface` (3 configurable tonal layers from primary palette).
1064
+
1065
+ **Colored Surface Layers** — configurable tonal steps (default 25/45/65):
1066
+ ```json
1067
+ "identity": {
1068
+ "colorScheme": "colored-surface",
1069
+ "coloredSurfaceLayers": { "background": 25, "surface": 45, "primitive": 65 }
1070
+ }
1071
+ ```
1072
+ The 3 numbers are OKLCH lightness steps (0-100) applied to the primary color. Each produces a distinct layer: page bg (darkest), cards (mid), inputs (lightest). Focus ring uses accent color (not primary) in colored-surface.
1073
+
1074
+ **Color Weight** — WHERE color appears: `monochrome`, `branded-nav`, `gradient-hero`, `ambient`, `dark-native`. Layout tokens via `$token: colorWeight.navBg`.
1075
+
1076
+ **Accent Application** — WHERE accent appears: `buttons`, `navItems`, `cardLine` (array: `["top","left"]`), `links`, `backgrounds`, `iconContainers`.
1077
+
1078
+ **Architecture: structured surface styles** — `resolveSurfaceStyles()` returns platform-neutral objects (ShadowDef[], BorderDef, BlurDef — NO CSS strings). Platform serializers convert: `surfaceToCSS()` for web, `surfaceToRN()` for React Native. `resolveIdentity<T>(input, serializer)` orchestrates the full chain in one call. Surface styles are explicit — every property set (`border: 'none'` emitted explicitly, never omitted). Focus is surface-aware per type (bold keeps 2px, neo keeps inset shadow, glass uses semi-transparent border). `inputFocus` never includes `backgroundColor` (prevents checkbox override). Text/Input/Select/Textarea/Checkbox use `color: 'inherit'` — surface containers set `color: c.text`, children inherit automatically for correct dark/colored scheme text. Use `$token: "schemeColors.text"` and `$token: "colorWeight.navBg"` for scheme-aware values in specs.
1079
+
1080
+ **Runtime identity changes** — same as DNA, via `updateTokens`:
1081
+ ```json
1082
+ { "action": "updateTokens", "params": { "identity": { "surface": "bold", "radiusPattern": "diagonal" } } }
1083
+ ```
1084
+
1085
+ ### Motion Tokens
1086
+
1087
+ ```json
1088
+ "tokens": {
1089
+ "motion": {
1090
+ "duration": { "fast": 150, "normal": 250, "slow": 400 },
1091
+ "easing": { "default": "ease-out", "enter": "ease-out", "exit": "ease-in" },
1092
+ "spring": { "damping": 20, "stiffness": 100, "mass": 1 },
1093
+ "stagger": 0.06,
1094
+ "presets": { "hoverLift": { "y": -2, "scale": 1.02 }, "fadeIn": { "initial": { "opacity": 0 }, "animate": { "opacity": 1 } } }
1095
+ }
1096
+ }
1097
+ ```
1098
+ Reference: `"hover": { "$token": "motion.presets.hoverLift" }`
1099
+
1100
+ ## Component Variants
1101
+
1102
+ Token-driven styling. Define in `tokens.components.{type}.{variant}`:
1103
+
1104
+ ```json
1105
+ "tokens": {
1106
+ "components": {
1107
+ "button": {
1108
+ "primary": { "style": { "backgroundColor": "$colors.primary", "color": "#FFF", "borderRadius": "$shape.radius.md" }, "hover": { "scale": 1.05 }, "active": { "scale": 0.95 } },
1109
+ "danger": { "style": { "backgroundColor": "$colors.error", "color": "#FFF" } }
1110
+ },
1111
+ "box": {
1112
+ "card": { "style": { "backgroundColor": "$colors.surface", "borderRadius": "$shape.radius.lg", "padding": "$spacing.scale.md", "boxShadow": "$elevation.md" }, "hover": { "boxShadow": "$elevation.lg", "y": -2 } }
1113
+ }
1114
+ }
1115
+ }
1116
+ ```
1117
+ Usage: `{ "type": "button", "props": { "label": "Save", "variant": "primary" } }`
1118
+ `$path` references (`$colors.primary`) resolve against active tokens — dark mode works automatically.
1119
+ Element-level style/hover overrides variant (variant is base, element is override). Supports: `style`, `hover`, `active`, `focus`, `transition`.
1120
+
1121
+ ## Skeleton & Export
1122
+
1123
+ **Auto-skeleton:** activates when spec has `fetch` in initialActions + loading + empty data. Zero config. Set `skeleton: false` on static elements. Shape mapping: text → line, image → rect, button → button, input → rect, icon → circle, charts → large rect.
1124
+
1125
+ **Export:** `{ "action": "export", "params": { "source": "/items", "columns": [{ "field": "name", "label": "Name" }, { "field": "price", "label": "Price", "format": "currency", "formatOptions": { "currency": "USD" } }], "filename": "report", "format": "csv" } }`
1126
+ CSV built-in. XLSX/PDF via adapter. Column formats: `currency`, `number`, `percent`, `date`.
1127
+
1128
+ ## ApiSpec (Server)
1129
+
1130
+ Declarative backend API definition. **See [ai-context-api.md](ai-context-api.md) for complete reference** (catalogs, endpoints, auth, audit).
1131
+
1132
+ Quick reference: `type: "api"` at root, with `auth`, `catalogs`, `endpoints` objects. No connection strings in spec.
1133
+
1134
+ ## Storage Setup
1135
+
1136
+ Mythik stores specs in the consumer's database. Three tables are involved depending on which features the consumer opts into:
1137
+
1138
+ - **`screens`** (base, **REQUIRED**) — current spec per `id`. Used by every adapter (`SqlServerSpecStore`, `SupabaseSpecStore`, and the versioned subclasses which extend the base).
1139
+ - **`screen_versions`** (opt-in) — version history. Required only when using `SqlServerVersionedSpecStore` / `SupabaseVersionedSpecStore` (i.e., consumers calling `mythik push --author <name>` or `runPush({ author })`).
1140
+ - **`screen_environments`** (opt-in) — environment promotions. Required only when using `SqlServerEnvironmentStore` / `SupabaseEnvironmentStore`.
1141
+
1142
+ **The framework does NOT auto-create any of these tables.** Apply the schema below once during initial setup of the consumer's database, then the framework operates against the running tables.
1143
+
1144
+ **Authoritative since v0.1.0.** The framework's INSERT/SELECT/UPDATE statements (in `packages/core/src/spec-stores/sqlserver.ts`, `supabase.ts`, `sqlserver-versioned.ts`, `supabase-versioned.ts`) require these exact columns by name + semantic type. AI applying this schema in the consumer's environment MUST preserve all columns, constraints, and indexes; the SQL dialect is free to vary (NVARCHAR/VARCHAR/TEXT, BIT/BOOLEAN, DATETIME2/TIMESTAMPTZ — pick what the target DB supports).
1145
+
1146
+ **Versioned stores extend the base store.** When `SqlServerVersionedSpecStore.saveVersion(id, doc, meta)` runs, it appends to `screen_versions` AND calls the inherited base `save(id, doc)` which writes to `screens` (`packages/core/src/spec-stores/sqlserver-versioned.ts:110-111`). This means `screens` MUST exist for every consumer — there is no "versioning-only" mode that skips it.
1147
+
1148
+ ### Table 0 — `screens` (current spec — REQUIRED for all stores)
1149
+
1150
+ | Column | Semantic type | Nullable | Default | Notes |
1151
+ |---|---|---|---|---|
1152
+ | `id` | short string (≤255) | NOT NULL | — | Spec identifier; PK. Framework reads/writes via `WHERE id = ?` |
1153
+ | `name` | short string (≤255) | NULL | — | Display name. Framework's INSERT populates with the same value as `id` (`sqlserver.ts:76` MERGE: `INSERT (id, name, spec, version, is_active) VALUES (@id, @id, @spec, 1, 1)`) |
1154
+ | `spec` | long string (≥1MB capacity) | NOT NULL | — | JSON-encoded current spec. SQL Server uses `NVARCHAR(MAX)` text + defensive parse (`sqlserver.ts:58`); Postgres / Supabase MUST be `jsonb` (see below) |
1155
+ | `version` | integer | NOT NULL | `1` | Incremented on every UPDATE (SQL Server: app-level at `sqlserver.ts:74`; Postgres: via TRIGGER, see below) |
1156
+ | `is_active` | boolean | NOT NULL | `true` | Framework's INSERT sets `1`/`true` (`sqlserver.ts:76`); UPDATE never touches it |
1157
+ | `created_at` | UTC timestamp | — | — | OPTIONAL — framework does not read or write this column. If you add it for consumer hygiene (audit trail), make it `NOT NULL` with a NOW UTC default; otherwise omit entirely. |
1158
+ | `updated_at` | UTC timestamp | NOT NULL | NOW UTC | Required. Updated on every UPDATE (SQL Server: app-level via `updated_at = GETUTCDATE()` at `sqlserver.ts:74`; Postgres: via TRIGGER, see below). Framework's INSERT at `sqlserver.ts:76` omits this column, so initial value comes from the column DEFAULT. |
1159
+
1160
+ **Constraints**:
1161
+ - `PRIMARY KEY (id)` — required (every framework query filters by `id`)
1162
+
1163
+ **Indexes** (all RECOMMENDED, none framework-required):
1164
+ - `(is_active, id)` — useful for consumer queries filtering active screens. The framework's `list()` uses only `ORDER BY id` (`sqlserver.ts:83`, `supabase.ts:66`) and does not filter by `is_active`, so this index is consumer-hygiene only.
1165
+
1166
+ ### Table 1 — `screen_versions` (version history — opt-in: VersionedSpecStore)
1167
+
1168
+ | Column | Semantic type | Nullable | Default | Notes |
1169
+ |---|---|---|---|---|
1170
+ | `id` | auto-increment integer, PK | NOT NULL | DB-managed | Surrogate PK; framework never writes it |
1171
+ | `screen_id` | short string (≤255) | NOT NULL | — | Spec doc identifier |
1172
+ | `version` | integer | NOT NULL | — | Sequential per-`screen_id`; framework computes via `MAX(version) + 1` |
1173
+ | `is_snapshot` | boolean | NOT NULL | `false` | `true` for full-spec rows, `false` for patch rows |
1174
+ | `spec` | long string (≥1MB capacity) | NULL | — | JSON-encoded full spec; populated only when `is_snapshot = true` |
1175
+ | `patches` | long string (≥1MB capacity) | NULL | — | JSON-encoded patch array; populated only when `is_snapshot = false` |
1176
+ | `author` | short string (≤255) | NOT NULL | `'system'` | Provided via `--author` flag; bootstrapped to `'system'` for lazy v1 backfill |
1177
+ | `source_type` | short string (≤50) | NOT NULL | `'push'` | Source channel (`push`, `patch`, etc.) |
1178
+ | `description` | medium string (≤1000) | NULL | — | Optional description from `--description` flag |
1179
+ | `created_at` | UTC timestamp | NOT NULL | NOW UTC | Set by DB on insert |
1180
+
1181
+ **Constraints**:
1182
+ - `PRIMARY KEY (id)` — surrogate key on the auto-increment column
1183
+ - `UNIQUE (screen_id, version)` — framework relies on per-screen uniqueness to compute next version
1184
+
1185
+ **Indexes** (required for query performance):
1186
+ - `(screen_id, version)` — supports `WHERE screen_id = ? ORDER BY version DESC`
1187
+ - `(screen_id, version) WHERE is_snapshot = true` (partial index) — accelerates `loadVersion`'s nearest-snapshot lookup. If the target DB doesn't support partial indexes, omit and accept full-scan fallback (correctness preserved, performance degrades on long histories)
1188
+
1189
+ ### Table 2 — `screen_environments` (environment promotions — opt-in: EnvironmentStore)
1190
+
1191
+ | Column | Semantic type | Nullable | Default | Notes |
1192
+ |---|---|---|---|---|
1193
+ | `screen_id` | short string (≤255) | NOT NULL | — | PK part 1 |
1194
+ | `environment` | short string (≤100) | NOT NULL | — | PK part 2 (`dev`, `staging`, `prod`, etc.) |
1195
+ | `version` | integer | NOT NULL | — | Promoted spec version (logical reference to `screen_versions.version`; not enforced as FK in v0.1.0) |
1196
+ | `promoted_at` | UTC timestamp | NOT NULL | NOW UTC | Set by DB on insert; UPDATE on re-promotion |
1197
+ | `promoted_by` | short string (≤255) | NOT NULL | `'system'` | Author who promoted |
1198
+
1199
+ **Constraints**:
1200
+ - `PRIMARY KEY (screen_id, environment)` — one promotion record per `(spec, env)` pair; re-promote upserts via MERGE/UPSERT
1201
+
1202
+ ### Postgres / Supabase: `jsonb` for `spec` and `patches`
1203
+
1204
+ On Postgres-flavored backends (Supabase, plain Postgres), the JSON columns MUST be `jsonb`, not `text`:
1205
+
1206
+ - `screens.spec` — Supabase code path returns `rows[0].spec` directly (`packages/core/src/spec-stores/supabase.ts:41`) without `typeof === 'string' ? JSON.parse(...) : raw` defense. A `text` column would return a string and downstream consumers (e.g., `MythikInstance.getSpec`, `MythikRenderer`) would receive a stringified spec instead of an object.
1207
+ - `screen_versions.spec` and `screen_versions.patches` — Supabase versioned path consumes these as already-parsed objects from PostgREST (`packages/core/src/spec-stores/supabase-versioned.ts:132`, `:146`, `:149`); a `text` column would cause `applyPatches` / `structuredClone` to receive a string instead of an object, silent corruption.
1208
+
1209
+ SQL Server stores parse `NVARCHAR(MAX)` defensively (`typeof === 'string' ? JSON.parse(...) : raw` at `sqlserver.ts:58`, `sqlserver-versioned.ts:133-135` and `:153`) and tolerate either form, but Postgres-flavored stores have no such defense.
1210
+
1211
+ ### Postgres / Supabase: triggers for `screens.updated_at` and `screens.version`
1212
+
1213
+ On Postgres-flavored backends, `screens.updated_at` and `screens.version` MUST be maintained by `BEFORE UPDATE` triggers because the Supabase save path sends only the `spec` field (`packages/core/src/spec-stores/supabase.ts:55`: `body: JSON.stringify({ spec })`); it does NOT update `updated_at` or `version` itself. SQL Server stores set both columns app-level inside the MERGE (`sqlserver.ts:74`: `UPDATE SET spec = @spec, updated_at = GETUTCDATE(), version = version + 1`) and do not need triggers.
1214
+
1215
+ Recommended trigger pair on Postgres:
1216
+
1217
+ ```sql
1218
+ CREATE OR REPLACE FUNCTION screens_update_updated_at()
1219
+ RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql;
1220
+
1221
+ CREATE OR REPLACE FUNCTION screens_increment_version()
1222
+ RETURNS TRIGGER AS $$ BEGIN NEW.version = OLD.version + 1; RETURN NEW; END; $$ LANGUAGE plpgsql;
1223
+
1224
+ CREATE TRIGGER screens_updated_at_trigger
1225
+ BEFORE UPDATE ON screens
1226
+ FOR EACH ROW EXECUTE FUNCTION screens_update_updated_at();
1227
+
1228
+ CREATE TRIGGER screens_version_trigger
1229
+ BEFORE UPDATE ON screens
1230
+ FOR EACH ROW EXECUTE FUNCTION screens_increment_version();
1231
+ ```
1232
+
1233
+ Trigger function names are arbitrary (use any unique name); the framework does not introspect them.
1234
+
1235
+ `screen_versions` and `screen_environments` do NOT need such triggers — those tables are append-only / upsert-on-PK and the framework writes all columns explicitly on each INSERT/UPSERT (`supabase-versioned.ts:61-69`, `:77-85`, `:89-97`, `:243-249`).
1236
+
1237
+ ### Idempotency requirement
1238
+
1239
+ The applied DDL MUST be idempotent — re-running it on a database that already has the tables MUST NOT fail and MUST NOT recreate. Use the target dialect's "if not exists" form:
1240
+ - SQL Server: `IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '...') CREATE TABLE ...`
1241
+ - Postgres / Supabase: `CREATE TABLE IF NOT EXISTS ...`
1242
+ - MySQL / MariaDB: `CREATE TABLE IF NOT EXISTS ...`
1243
+
1244
+ ### Verification (post-apply)
1245
+
1246
+ After applying the DDL, verify the relevant tables exist with correct columns by querying the target's information schema. The query below covers all three tables; consumers using only the base store can drop `screen_versions` + `screen_environments` from the `IN (...)` list.
1247
+
1248
+ ```sql
1249
+ -- Standard ANSI:
1250
+ SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE
1251
+ FROM INFORMATION_SCHEMA.COLUMNS
1252
+ WHERE TABLE_NAME IN ('screens', 'screen_versions', 'screen_environments')
1253
+ ORDER BY TABLE_NAME, ORDINAL_POSITION;
1254
+ ```
1255
+
1256
+ Confirm: 7 columns for `screens` (`id`, `name`, `spec`, `version`, `is_active`, `created_at`, `updated_at`), 10 columns for `screen_versions` (`id` through `created_at`), 5 columns for `screen_environments` (`screen_id` through `promoted_by`). If any column is missing or has a wrong NULL/NOT NULL flag, abort and report — the framework's INSERT/SELECT/UPDATE will fail at runtime otherwise.
1257
+
1258
+ On Postgres / Supabase, additionally verify the two triggers on `screens` are present (`information_schema.triggers` WHERE `event_object_table = 'screens'`); without them, `updated_at` and `version` will silently stop advancing on save.
1259
+
1260
+ ### Custom table names
1261
+
1262
+ All three table names are independently configurable; overriding one does not require overriding the others:
1263
+
1264
+ ```ts
1265
+ new SqlServerSpecStore({ ..., table: 'my_screens' })
1266
+ new SqlServerVersionedSpecStore({ ..., table: 'my_screens', versionsTable: 'my_versions' })
1267
+ new SqlServerEnvironmentStore({ ..., table: 'my_envs' })
1268
+ ```
1269
+
1270
+ (`SqlServerVersionedSpecStore` accepts both `table` from the base config and `versionsTable` from its own config, since it extends `SqlServerSpecStore`.)
1271
+
1272
+ If a consumer overrides any name, AI applies the same schema under the consumer-chosen name.
1273
+
1274
+ **Identifier safety scope**: SQL Server stores enforce `assertValidIdentifier` on every configured name (regex `/^[a-zA-Z_][a-zA-Z0-9_.]*$/`, max 128 chars — see `packages/core/src/security/identifier-guard.ts`). The validator is invoked in the constructor of `SqlServerSpecStore` (`sqlserver.ts:26`), `SqlServerVersionedSpecStore` (`sqlserver-versioned.ts:25`), and `SqlServerEnvironmentStore`. This blocks SQL injection via table-name interpolation in `[${table}]` / `[${versionsTable}]` template literals. Supabase stores do NOT validate any configured name (it flows directly into the REST URL via `${this.tableName}`); consumer code passing user-controlled table names to a Supabase store must validate them upstream.
1275
+
1276
+ ### Canonical reference (SQL Server)
1277
+
1278
+ A working SQL Server bootstrap script for the **versioning tables only** (`screen_versions` + `screen_environments`) exists at `Demos/Mythik/demo-sqlserver/setup-versioning.ts` (in the demos workspace, outside the framework repo). It implements those two tables idempotently using `mssql` directly and is the canonical reference if the AI is uncertain about idempotent SQL Server syntax. There is no separate canonical script for the base `screens` table — AI applies this spec directly (the base table is short enough that translating the spec to a `CREATE TABLE` statement is unambiguous). For non-SQL-Server targets, AI translates both the spec and (if useful) the versioning script's structure to the target dialect.
1279
+
1280
+ ### Schema evolution
1281
+
1282
+ When the framework changes the schema in a future version, this section will gain an "Evolution from v0.X.0" subsection listing per-version diffs (additive columns, new indexes, etc.) with idempotent ALTER instructions. AI inspecting the consumer's existing schema first, then applying the smallest set of ALTER statements to converge on the current version, is the canonical evolution path. v0.1.0 is the baseline — no evolution diffs yet.
1283
+
1284
+ ## Rules
1285
+
1286
+ > Primitive-specific rules → [ai-context-primitives.md](ai-context-primitives.md). API rules → [ai-context-api.md](ai-context-api.md). Composition anti-patterns → [ai-context-patterns.md](ai-context-patterns.md).
1287
+
1288
+ 1. Always use flat tree — root + elements map with string IDs for children
1289
+ 2. Field IDs must be unique within the spec — use descriptive names: `patient-name`, `submit-btn`
1290
+ 3. Arrays for ordered collections — never objects
1291
+ 4. Use `$let` array format when stored in JSONB — `[["a", expr], ["b", expr]]` preserves order
1292
+ 5. Use `$token` for all visual values — never hardcode colors, spacing, fonts
1293
+ 6. Use `$bindState` for form inputs — enables two-way binding
1294
+ 7. Use `$template` for computed strings — interpolation over concatenation
1295
+ 8. Use `$math`, `$array`, `$date`, `$format` instead of `$computed` — built-in ops cover 90%+
1296
+ 9. Use `$switch` for 3+ branches — replaces nested `$cond`. `default` required
1297
+ 10. `$array: 'append'` and `$array: 'replace'` use `value`, not `item` — `item` silently does nothing
1298
+ 11. `$group` only inside groupBy context — throws error outside
1299
+ 12. `$selection` only inside repeat with selection — throws error outside
1300
+ 13. Use `$auth` for user data, not `$state` — whitelisted, blocks tokens/passwords
1301
+ 14. CSS hover only works on: `box`, `text`, `stack`, `grid`, `scroll`, `button`, `touchable`, `table`
1302
+ 15. Don't use `overflow: hidden` with `box-shadow` hover — clips the shadow
1303
+ 16. Use `transaction` for all CRUD operations — instant UX with auto-rollback
1304
+ 17. In transactions: `closeModal` in `before`, data changes in `optimistic`
1305
+ 18. UPDATE transactions don't need `onSuccess` — re-fetch causes flash
1306
+ 19. Use `navigateScreen`/`goBackScreen` — not `navigate`/`goBack`
1307
+ 20. Use `repeat.source` for paginated/filtered lists — chain filter → search → slice
1308
+ 21. Use `derive` for computed stats — dependency-tracked, read-only
1309
+ 22. Use `dataSources` for reactive GET — `fetch` action for POST/PATCH/DELETE
1310
+ 23. Table `mode: "server"` for large datasets — writes sort/page to state
1311
+ 24. Use templates for repetitive elements — `$prop` parameterization
1312
+ 25. Use `forms` for coordinated validation — `isValid`, cross-field rules, submit gate
1313
+ 26. Use AppSpec for multi-screen apps — sidebar, navigation, shared state
1314
+ 27. Use `roleAccess` for centralized access — sole source when present
1315
+ 28. loginScreen always accessible — prevents redirect loops
1316
+ 29. Login renders fullscreen (no layout) — appears automatically when not authenticated
1317
+ 30. Login paths: `/screens/login/...` not `/form/...` — clears on logout with statePolicy reset
1318
+ 31. Auth headers auto-injected for `authDomains` — no manual headers in fetch
1319
+ 32. Use `variant` prop for component styling — don't copy style objects
1320
+ 33. `$path` references in variants resolve with dark mode automatically
1321
+ 34. Use `mythik push` for spec creation — no seed scripts
1322
+ 35. AppSpec patches use `/layout/elements/` not `/elements/`
1323
+ 36. Export columns support formatting — same as `$format`
1324
+ 37. `$token` auto-reads `/preferences/theme` — use `toggleTheme` action for dark mode
1325
+ 38. `emptyWhileLoading: false` keeps previous data during re-fetch — better UX
1326
+ 39. Set `tokens.identity` for app visual personality — at minimum `surface` + `typographyHierarchy`
1327
+ 40. Use `surface="card"` on card-like boxes — without it, boxes ignore identity surface treatment
1328
+ 41. Set app background via `tokens.identity.background` as a LayerBackground — `{ "color": "#0a0a0a", "layers": [...] }`. MythikRenderer mounts a root <BackgroundStack> that composes layers (solid/gradient/pattern/grain/image/blobs) with per-layer `blendMode` / `opacity` / `zIndex`. Palette threads from `tokens.colors.{primary,accent}` so blob layers render at render-time. Do not use the legacy `{ "$token": "backgroundCSS" }` pattern or `identity.background.style` shape.
1329
+ 42. `textDecoration` supports array for multi-select — `["underline-accent", "shadow"]` merges effects
1330
+ 43. Select dropdown uses `surface.modal` (always opaque) — never `surface.card` (transparent in outlined)
1331
+ 44. `_motion.whileTap` and `_motion.whileHover` forward to Framer Motion — use `"Infinity"` (string) for `repeat` in JSON, renderer converts to JS `Infinity`
1332
+ 45. `Element.key` forces remount on value change — use dynamic expression (e.g., `{ "$template": "preview-${/internal/version}" }`) to re-trigger mount animations on state change
1333
+ 46. Input supports `type: "color"` — renders native OS color picker, use with `$bindState`
1334
+ 47. Slider `label` is display-only — does NOT append current value. Use `$template` to include it: `"label": { "$template": "Roundness: ${/dna/roundness}%" }`
1335
+ 48. Identity icons: `weight` from tokens is default (spec prop overrides), `container` auto-wraps ('circle'/'square'/'rounded-square') unless `container={false}` in spec
1336
+ 49. Identity images: `corners` from tokens is default borderRadius (spec `style.borderRadius` overrides), `overlay` adds gradient/tint (spec `overlay="none"` suppresses)
1337
+ 50. `gradients.text = true` applies gradient clip on headings — spec `style.color` overrides. Web-only
1338
+ 51. `gradients.buttons = true` applies gradient bg on primary buttons — spec `style.background` overrides. Web-only
1339
+ 52. `identity.background` is a `LayerBackground` — `{ color?: string, layers?: LayerConfig[] }`. Legacy `identity.background.style`, `resolveBackgroundCSS()`, and `resolveBlobStyles()` are not part of the public contract. Layer kinds: `'solid'|'gradient'|'pattern'|'grain'|'image'|'blobs'`. Each carries `opacity?` + `blendMode?` + `zIndex?` (LayerCommonProps). Example: `"layers": [{ "type": "gradient", "kind": "radial", "stops": [...] }, { "type": "grain", "intensity": 0.04 }]`
1340
+ 53. Blob layer v2 — `{ "type": "blobs", "preset": "organic-duo"|"organic-trio"|"circle-pair", "palette": ["primary", "accent"], "motion": "drift-gentle"|"drift-fluid"|"drift-snappy"|"static", "blobOpacity"?: 0..1 }` for preset form, OR `{ "type": "blobs", "blobs": [{ "shape": "organic-1"|...|"circle"|"custom-svg", "position": {x,y}, "size": {width,height}, "color": "primary"|"accent"|hex, "opacity"?, "blur"?, "motion"?: {drift?, rotate?, scale?} }] }` for explicit form. Custom-svg requires `path` + `viewBox`. Motion converts to ambient animations via useShapeAnimations. RN: `blur` is currently not rendered; treat it as a web-only visual until filter parity ships.
1341
+ 54. **Do not emit `identity.motionEntrance` or `identity.motionHover`.** Per-element mount animation is now `element.animations.mount: { recipe: 'fade-up' | 'fade' | 'scale-in' | 'slide-right' | ... }` (15 recipes available; `glow` is web-only). Mapping from the old values: `motionEntrance: 'fade'` → `animations.mount.recipe: 'fade'`; `'slide-up'` → `'fade-up'`; `'scale'` → `'scale-in'`; `'slide-left'` → `'slide-right'`. Hover similarly uses `animations.hover`
1342
+ 55. `gradients.text` and `gradients.buttons` accept `'vibrant'` (OKLCH), `'soft'` (light tones), `'muted'` (sRGB desaturated center), `true` (=vibrant), or `false`
1343
+ 56. **Do not emit `backgroundBlobs`.** Box `backgroundBlobs` and legacy per-element blob rendering are not part of the public primitive contract. App-level background lives exclusively at `tokens.identity.background` (rule 41/52) and mounts at MythikRenderer via <BackgroundStack>.
1344
+ 57. **Do not emit `$token: "backgroundCSS"`.** `$token: "backgroundCSS"` does not resolve. Use the LayerBackground shape at `tokens.identity.background` (rule 41) instead.
1345
+ 58. Border/elevation override requires opt-in — `identity.overrideSurfaceBorders: true` overrides card+modal borders/shadows, `identity.overrideInputButtons: true` overrides input+button borders/shadows. Both default `false` (surface type controls everything). `borderColor`: 'neutral'|'primary'|'accent'|'text'. `elevationStyle`: 'none'|'diffuse'|'solid'|'color'. `elevationColor`: 'dark'|'primary'|'accent'
1346
+ 59. `identity.headingColor` ('default'|'primary'|'accent'|'primary-dark') controls heading text color. Gradient text overrides when active. Default = 'inherit'
1347
+ 60. Object composition in action params works without `$object` — `{ "dna": { "$state": "/dna" }, "identity": { "$state": "/identity" } }` resolves each `$state` recursively. Same in element props
1348
+ 61. `$event` is NOT a valid expression — do NOT use `{ "$event": "value" }` in action params. For select/control `on:change`, use `$bindState` on the value prop for two-way binding, then read the value with `$state` in the action: `"value": { "$bindState": "/path" }` + `"on": { "change": [{ "action": "myAction", "params": { "val": { "$state": "/path" } } }] }`
1349
+ 62. Preset dropdown pattern — `applyPreset` action applies registered presets. Use `$bindState` + `$state` pattern (rule 61). `'custom'` is a no-op. Every control that modifies tokens should add `{ "action": "setState", "params": { "statePath": "/ui/currentPreset", "value": "custom" } }` to its `on:change` to reset the preset indicator
1350
+ 63. Custom elements are first-class primitives — `plugins.registerElement` registers a type that consumers use with identical syntax to built-ins: `{ "type": "rating-stars", "props": { ... }, "animations": { ... }, "hover": { ... }, "visible": ..., "key": ... }`. All instance-level fields apply to the outer primitive of the expansion. See [ai-context-custom-elements.md](ai-context-custom-elements.md) for authoring
1351
+ 64. Custom element black-box boundary — consumer's instance-level `animations`, `hover`, `active`, `focus`, `motion`, `style`, `visible`, and `key` apply to the OUTER primitive only. Inner primitives are the author's domain and are not reachable from the consumer. Identity cascade (rule 63 / cascade level 1) still reaches inner primitives; consumer cannot override them directly
1352
+ 65. `$prop` is nearest-enclosing-custom-element-scoped — inside a custom element's render tree, `$prop` resolves against THAT element's merged props. Nesting a custom element inside another pushes a new prop context; the outer's props are shadowed, not merged. Pass values explicitly via prop declarations when nested access is needed
1353
+ 66. `$children` marker in custom element render trees — authors write `"$children"` as a string item in their render tree `children` array to mark where consumer children are inserted during expansion. Multiple markers each splice the full consumer children. Same slotting semantics as spec templates
1354
+ 67. `variant` is a PROP — place it inside `props`, never as a top-level element field. Applies to built-in primitives and Layer 3 custom elements alike: `{ "type": "stat-card", "props": { "variant": "primary", ... } }`. Top-level `variant` is silently ignored (the renderer reads `props.variant` only). Consumer may drive it dynamically via an expression: `"variant": { "$switch": { "$state": "/filter/recordType" }, "cases": { "1": "active" }, "default": "inactive" }`
1355
+ 68. Custom elements may expose action-chain props — author declares a prop (e.g. `onSelect`, type `"array"`) and the render tree's `on:<event>` references it as `{ "$prop": "onSelect" }`. Consumers supply the full action array as the prop value; inner `$state` / `$template` / `$item` inside those actions resolve at press time with the current state (not at render time). Enables tabs, menu items, and similar patterns where the consumer owns the action chain
1356
+ 69. Never use `$row` literal — there is no `$row` expression handler. Read row data via `$state: '/ui/selectedRow/<key>'` (framework writes clicked row before column action dispatch).
1357
+ 70. Never combine `crud: {}` with `endpoint.path` ending in `/:id`. CRUD operations auto-append `/:id` to PUT/DELETE routes. Declaring `path: '/api/x/:id'` produces `/api/x/:id/:id`.
1358
+ 71. Never include `:port` in `auth.authDomains[]` entries. The matcher uses `URL.hostname` for comparison — ports are silently stripped, leading to apparent matches that don't actually match.
1359
+ 72. `spatial-map` is the generic SVG/data-first primitive for floor plans, seating maps, parking maps, warehouse layouts, hospital beds, and similar spatial workflows. JSON `onItemPress` actions write item context to `/ui/selectedSpatialItem` before lazy dispatch. Compose domain menus/drawers/modals externally; do not encode restaurant-specific behavior into the primitive. Use `{ "$state": "/path" }` expressions for dynamic `items`, `zones`, `mode`, and `statusStyles`; do not invent `*Path` prop aliases.
1360
+ 73. For `spatial-map` editing, use `editPolicy` for movement rules and `onItemChange` for persistence. Do not use `interactionPolicy` for drag/keyboard movement. In JSON specs, persist moved items with `$array: "replace"` reading from `/ui/spatialItemChange` or the configured `itemChangePath`; use plain `setState` for non-undoable screens and wrap the same value in `editorCommit` for undoable editors.
1361
+ 74. For JSON-created client-side item ids, use `$uniqueId` with an explicit `source`, `field`, `prefix`, and optional `padding`. It is deterministic and scoped to the source array; use it for local/editor objects, not as a substitute for database primary keys when a backend owns identity.
1362
+ 75. For `spatial-map` lifecycle editing, compose create/duplicate/delete outside the primitive. Add/place uses consumer-owned `placeMode` + `canvasPressPath` + `$array: "append"`; duplicate copies the selected full item, generates a new `$uniqueId`, offsets position, and preserves shape/status/metadata; delete captures a candidate, opens a modal, confirms with `$array: "remove"`, then clears draft/selection state. Do not set `props.visible` on modals/drawers; `openModal`/`closeModal` drive `/ui/modals/{id}` automatically.
1363
+ 76. In `spatial-map`, item `status` is semantic/visual only; never treat `status: "inactive"` as non-interactive. Use `disabled: true` to intentionally lock an item. For add/place workflows, drive `canvasGuide.visible` from consumer state such as `/ui/floorEditor/placeMode` to show a generic dotted SVG crosshair without writing placement state on pointer move.
1364
+ 77. For `spatial-map` snap/guides, configure `editPolicy.snap` and `editPolicy.guides`; do not invent domain-specific placement props. Snap is generic and applies to drag, keyboard movement, item/zone resize handles, and canvas placement. Grid threshold is per-axis, so X and Y can snap independently; keyboard movement with grid snap advances by grid stops on the moved axis. In JSON add/place flows, read `/ui/spatialCanvasPress/point` as the effective coordinate and `/ui/spatialCanvasPress/rawPoint` only when the original pointer coordinate is needed. Snap/guide overlays are visual authoring aids and do not persist data by themselves.
1365
+ 78. For `spatial-map` resize/rotate, use item `transform.scaleX/scaleY` plus `rotation`; do not rewrite `shape` dimensions/points/path data as the primary resize model. For arbitrary `path` items, provide `localBounds` if resize handles are required. Persist runtime resize/rotate through `onItemChange` and `/ui/spatialItemChange/nextItem` with `$array: "replace"`; use `editorCommit` when the edit must be undoable. Snap for resize handles is world/map-coordinate snap, not a hidden per-item rotated grid.
1366
+ 79. For `spatial-map` zone editing, use `selectedZonePath`, `zoneChangePath`, `onZonePress`, and `onZoneChange`; do not overload item paths for zones. Runtime zone movement writes `nextZone.position`; runtime zone resize writes `nextZone.transform.scaleX/scaleY`; both preserve `nextZone.shape`, so polygon/path geometry is not rewritten as a side effect of editing. Zone movement participates in `editPolicy.snap`/`editPolicy.guides` using the center of transformed derived zone bounds as its snap anchor, or `position` when no bounds exist. Persist with `$array: "replace"` from `/ui/spatialZoneChange/nextZone` or the configured custom path; use `editorCommit` when the edit must be undoable. Use `interactionPolicy.selectZones`/`activateZones` and `editPolicy.dragZones`/`keyboardMoveZones`/`resizeZones`/`keyboardResizeZones` explicitly when a map is an editor.
1367
+
1368
+ 80. For element `style`, use `backgroundColor` for solid colors and `backgroundImage` for gradients. Never use the `background` shorthand. The framework's surface treatments (`box`/`button` with `props.surface: "card"|"modal"`, etc.) emit `backgroundColor` longhand into the merged style; spec `style.background` shorthand triggers React shorthand/longhand conflict warnings on every rerender (`Updating a style property during rerender (backgroundColor) when a conflicting property is set (background)`). Same applies to gradient text on headings — when `identity.gradients.text` is set, the framework already drives `backgroundImage` via `background-clip: text`; do not override with `style.background`.
1369
+ 81. Use `editorSessions` for generic JSON-first editor undo/redo/dirty workflows. Declare tracked document paths such as `/layout/items` and `/layout/zones`; the framework writes metadata under `/ui/editorSessions/<id>` and protects that subtree. Use `editorCommit` for one atomic undoable edit, `editorUndo`/`editorRedo` for history navigation, `editorDiscard` to restore the last saved snapshot, and `editorValidate` for configured validators. For normal saves, configure `editorSessions.<id>.persistence` and dispatch `editorSave`; reserve `editorMarkSaved` for low-level/advanced integrations that have already completed their own persistence successfully. Do not track transient `/ui/*` drafts or selections as editor document paths.
1370
+ 82. Use `editorSessions.<id>.persistence` plus `editorSave` for generic editor document persistence. The AI should not hand-compose `transaction` + `editorMarkSaved` for normal editor saves. `editorSave` captures the tracked paths snapshot, persists it through the host fetcher with URL-guard checks, and marks only the sent snapshot as saved after success. Failed saves keep `dirty: true` and expose save metadata under `/ui/editorSessions/<id>`.
1371
+ 83. Use `navigation.editorSessionGuard` for generic unsaved-changes protection in app specs instead of hand-rolled JSON dirty checks. Configure `sessions`, render your own JSON modal from `/ui/navigationGuard/pending`, call `navigationGuardCancel`, `navigationGuardSaveAndProceed`, `navigationGuardProceed`, or `navigationGuardDiscardAndProceed`, and keep `pendingPath` under a consumer-owned `/ui/<segment>` path that does not collide with reserved framework paths. `navigationGuardSaveAndProceed` is the normal save-first UX for persisted editor sessions; `navigationGuardProceed` is a low-level non-destructive retry that only resumes after the pending editor sessions are already clean; use `navigationGuardDiscardAndProceed` when the user explicitly chooses to abandon unsaved tracked-path changes.
1372
+ 84. In React apps without auth framework fetch, pass `fetcher` to `MythikApp` when editor sessions use `editorSave` or `navigationGuardSaveAndProceed`. Auth-enabled apps continue to use the framework fetch produced by auth interceptors. Do not route save-and-continue through `/ui/lastError` or a hand-composed fetch action; the editor session engine owns save metadata under `/ui/editorSessions/<id>`.
1373
+ 85. For existing spec edits, the required AI loop is `mythik manifest` -> `mythik elements` -> `mythik patch --from-file` -> verify. Manifest tells you the structure; elements gives the exact JSON you are changing; patch is the validated write path. Do not skip directly to full-spec `pull`/rewrite/push for a local change, do not mutate DB rows manually, and do not call `SpecStore.save()` from app code. Use `push` for new specs or intentional full replacement only.
1374
+ 86. Mythik's AI documentation ships with the `mythik` npm package. Before generating or modifying specs, locate it with `mythik docs path` and start from `docs/llms.txt`, `docs/consumer/ai-context.md`, and `docs/wiki/compiled/README.md`. Use `mythik docs copy ./mythik-docs` when a project-local copy is easier to hand to an AI agent.