@holoscript/core 8.0.7 → 8.0.9

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 (462) hide show
  1. package/bin/holoscript.cjs +5 -1
  2. package/dist/GLTFPipeline-L76YTXKA.js +15 -0
  3. package/dist/GLTFPipeline-ZWJN7GI6.cjs +36 -0
  4. package/dist/HoloCompositionParser-K76KTEEE.js +12 -0
  5. package/dist/HoloCompositionParser-UZH6Y4HO.cjs +45 -0
  6. package/dist/HoloScriptCodeParser-2D4ERFUZ.js +6 -0
  7. package/dist/HoloScriptCodeParser-UDRLDA7I.cjs +23 -0
  8. package/dist/HoloScriptPlusParser-FTMCGWXD.js +13 -0
  9. package/dist/HoloScriptPlusParser-LQR5GIKF.cjs +30 -0
  10. package/dist/HoloScriptRuntime-UTRLJI5L.js +12 -0
  11. package/dist/HoloScriptRuntime-YBYXJHJN.cjs +21 -0
  12. package/dist/SceneIRCompiler-63KA3M2F.js +17 -0
  13. package/dist/SceneIRCompiler-KWUFHZ4O.cjs +42 -0
  14. package/dist/{USDZExporter-AUHZODOF.cjs → USDZExporter-ML4UMIGC.cjs} +3 -3
  15. package/dist/{USDZExporter-GXB4AUSG.js → USDZExporter-ZFKLQ76G.js} +3 -3
  16. package/dist/agents/index.cjs +1 -1
  17. package/dist/agents/index.js +1 -1
  18. package/dist/audit/AuditLogger.d.ts +106 -0
  19. package/dist/audit/AuditQueryBuilder.d.ts +79 -0
  20. package/dist/audit/ComplianceReporter.d.ts +90 -0
  21. package/dist/audit/index.d.ts +13 -0
  22. package/dist/{chunk-FGMDMJM7.js → chunk-2BYAUHBO.js} +3 -3
  23. package/dist/{chunk-EDPYCLRC.cjs → chunk-2E6PP5UE.cjs} +83 -59
  24. package/dist/{chunk-GASCWJK5.js → chunk-2EGGAZT3.js} +65 -287
  25. package/dist/{chunk-SIEXCILW.js → chunk-2I3XAGMF.js} +3 -3
  26. package/dist/{chunk-OS533P33.cjs → chunk-2KKOYZYI.cjs} +1074 -1655
  27. package/dist/chunk-2MQKNDNH.js +51 -0
  28. package/dist/{chunk-7DMMMBCY.cjs → chunk-2X3IPCBK.cjs} +10 -10
  29. package/dist/chunk-2ZOTBO25.cjs +202 -0
  30. package/dist/chunk-356N4NPM.cjs +152 -0
  31. package/dist/{chunk-X3GJPRVK.cjs → chunk-36NPLOI4.cjs} +92 -81
  32. package/dist/{chunk-SLU6UPJI.cjs → chunk-37HHY7RH.cjs} +5 -5
  33. package/dist/{chunk-YDPEHCCI.cjs → chunk-3CDDRUER.cjs} +3 -118
  34. package/dist/chunk-3F7ZZWIN.js +1651 -0
  35. package/dist/chunk-3ILD7TKP.cjs +187 -0
  36. package/dist/{chunk-X27QRG4C.cjs → chunk-3IUHTGDD.cjs} +153 -41
  37. package/dist/{chunk-PXNZ6TME.js → chunk-4376VHNJ.js} +60 -36
  38. package/dist/{chunk-YKGPCZEE.cjs → chunk-4FIBOJW6.cjs} +10 -10
  39. package/dist/chunk-4Q7RKQQI.cjs +14195 -0
  40. package/dist/{chunk-YCM6QQRT.cjs → chunk-566ZB4LZ.cjs} +180 -8
  41. package/dist/{chunk-2Y3V22SG.js → chunk-5CURIYGT.js} +3 -3
  42. package/dist/{chunk-QBWNJXNR.js → chunk-5FYMCVBY.js} +5 -5
  43. package/dist/{chunk-ZA34AN3R.js → chunk-5LVFTGKH.js} +841 -12
  44. package/dist/chunk-63AUAIL6.js +48 -0
  45. package/dist/chunk-655FATJU.js +110 -0
  46. package/dist/{chunk-TQ377OLB.cjs → chunk-65S62L4D.cjs} +28 -22
  47. package/dist/chunk-6NTAZN5Z.cjs +502 -0
  48. package/dist/chunk-6TRX6AR2.js +9376 -0
  49. package/dist/chunk-6ZCCLKS2.cjs +51 -0
  50. package/dist/{chunk-MDR235RZ.js → chunk-734OB5SK.js} +721 -8
  51. package/dist/{chunk-Q2Q34NF3.js → chunk-77QI552M.js} +6 -6
  52. package/dist/{chunk-WKX5AMOY.js → chunk-7I74JWPW.js} +3 -3
  53. package/dist/{chunk-5FSKKMR7.cjs → chunk-7IDJDMPU.cjs} +232 -4
  54. package/dist/chunk-7VBKRGIZ.cjs +847 -0
  55. package/dist/{chunk-KCPHASCO.js → chunk-AATYYLYK.js} +5 -5
  56. package/dist/{chunk-WFKVS2K4.cjs → chunk-AUZRKIHQ.cjs} +1101 -55
  57. package/dist/{chunk-DTGBOSEM.cjs → chunk-AWXFEAQL.cjs} +12 -12
  58. package/dist/{chunk-THCK6ECW.js → chunk-B3CWTCK2.js} +231 -3
  59. package/dist/chunk-BCP4E7MD.cjs +997 -0
  60. package/dist/chunk-BG7RPYJP.js +91 -0
  61. package/dist/{chunk-VF257YKO.js → chunk-BP4KTMLY.js} +117 -5
  62. package/dist/{chunk-YN6IETRZ.js → chunk-BQJ3YBF3.js} +6424 -987
  63. package/dist/{chunk-KOUAQL2B.cjs → chunk-CANAL6CT.cjs} +1569 -168
  64. package/dist/{chunk-FDSGHPAK.js → chunk-CBSDJF3B.js} +3 -3
  65. package/dist/{chunk-FEWUHQNM.cjs → chunk-CFVK26P4.cjs} +4 -4
  66. package/dist/{chunk-M7K4LE66.cjs → chunk-CI33NINL.cjs} +4 -4
  67. package/dist/{chunk-2OWDB4FB.js → chunk-CKV5NYAE.js} +6 -6
  68. package/dist/{chunk-LPS5AMQD.cjs → chunk-CM4NHXVO.cjs} +24 -24
  69. package/dist/chunk-D3HSRXYB.js +115 -0
  70. package/dist/{chunk-FNHJRI32.js → chunk-DBH3D2MU.js} +1561 -160
  71. package/dist/{chunk-GW3LKD5C.js → chunk-DJNH4HFW.js} +3 -3
  72. package/dist/{chunk-2GCNOI2U.cjs → chunk-DN6F4DHH.cjs} +9 -3
  73. package/dist/chunk-DQRJ5RJG.js +432 -0
  74. package/dist/{chunk-C7ZBSV2Q.js → chunk-DUG3OQAS.js} +106 -43
  75. package/dist/chunk-ECUYJOJ2.cjs +199 -0
  76. package/dist/chunk-EEMTCAK7.js +182 -0
  77. package/dist/{chunk-3SKLAUDD.cjs → chunk-EI3J6LTW.cjs} +359 -581
  78. package/dist/{chunk-SSSN7VAM.js → chunk-EM2OGPYE.js} +4 -4
  79. package/dist/{chunk-56VOWURB.cjs → chunk-ENZCIQZC.cjs} +522 -453
  80. package/dist/chunk-ESBXUYOC.cjs +836 -0
  81. package/dist/{chunk-L5U4W6JC.js → chunk-ESSEF6U2.js} +4 -4
  82. package/dist/chunk-ET3AN4W3.js +824 -0
  83. package/dist/chunk-EXKSFGSX.cjs +14 -14
  84. package/dist/{chunk-I76GIKN7.cjs → chunk-F3YT6GUF.cjs} +17 -17
  85. package/dist/{chunk-WRWEX5ZF.js → chunk-F75DZBBI.js} +3 -3
  86. package/dist/{chunk-4JGRWHZJ.js → chunk-FG6PYGIZ.js} +12 -6
  87. package/dist/chunk-FGGJQRLZ.js +14 -14
  88. package/dist/{chunk-SXOSDZD6.js → chunk-FWCHPCD4.js} +128 -10
  89. package/dist/{chunk-XW6IXEQH.cjs → chunk-G35CAQ7I.cjs} +5 -5
  90. package/dist/{chunk-7VMGP2FW.js → chunk-G6KACNMO.js} +132 -188
  91. package/dist/{chunk-FJPADH77.cjs → chunk-GAWJJAGT.cjs} +6 -6
  92. package/dist/chunk-GGR7QUKK.cjs +4724 -0
  93. package/dist/chunk-GIBF4BHH.js +14098 -0
  94. package/dist/{chunk-AWB7QYY6.cjs → chunk-GILYQ5VH.cjs} +6 -6
  95. package/dist/{chunk-FWVYAMNW.cjs → chunk-GKFCHGCM.cjs} +4 -4
  96. package/dist/{chunk-Y3ZFVUUU.js → chunk-GLEJ2TLS.js} +3 -3
  97. package/dist/{chunk-3GWWJT7L.js → chunk-GP3OKSKT.js} +13 -13
  98. package/dist/chunk-GTIPOEHN.js +196 -0
  99. package/dist/{chunk-LMJ5EBV7.cjs → chunk-GZPUA2TL.cjs} +16 -15
  100. package/dist/{chunk-IELX2OKI.js → chunk-H4LJ4HEA.js} +3 -115
  101. package/dist/{chunk-ACVWFGBI.cjs → chunk-HCX4SMFK.cjs} +3 -3
  102. package/dist/{chunk-HYNTS5CP.js → chunk-HHRZ6STP.js} +24 -2
  103. package/dist/chunk-HIDEIEFG.js +48 -0
  104. package/dist/{chunk-W6RW64BB.cjs → chunk-HSWBIDZM.cjs} +228 -5
  105. package/dist/{chunk-GSOUNWEL.js → chunk-HVX7QQYK.js} +1035 -1616
  106. package/dist/{chunk-TRCGG42I.cjs → chunk-IFW5IW4L.cjs} +6502 -1019
  107. package/dist/{chunk-F5LKJ6F5.cjs → chunk-IJU6AS67.cjs} +32 -28
  108. package/dist/{chunk-TVANHNJ7.js → chunk-IK6Z2HNC.js} +173 -3
  109. package/dist/{chunk-QGMUTVVH.cjs → chunk-IS7NTKY5.cjs} +20 -20
  110. package/dist/{chunk-YFVQWSNJ.js → chunk-IXWGYWH6.js} +3 -3
  111. package/dist/chunk-J2DAS2PL.js +148 -0
  112. package/dist/chunk-JBQXZIWB.js +148 -0
  113. package/dist/chunk-JBYBMBMW.js +261 -0
  114. package/dist/{chunk-LWUOUCYL.js → chunk-JEJ7TT54.js} +5 -5
  115. package/dist/{chunk-DUCB6LGL.js → chunk-JOTCTHN5.js} +211 -5
  116. package/dist/{chunk-47RUFYKR.js → chunk-K56UVEXV.js} +3 -3
  117. package/dist/{chunk-XSFNHP2E.js → chunk-KB26H447.js} +3 -3
  118. package/dist/{chunk-3NGDZZR4.js → chunk-KEYG7HGY.js} +430 -37
  119. package/dist/{chunk-DY72BMU5.js → chunk-KFVNCW4Q.js} +4 -4
  120. package/dist/chunk-KPGC7SK2.js +192 -0
  121. package/dist/chunk-KROXXBK5.cjs +53 -0
  122. package/dist/{chunk-ZPZAVHXL.cjs → chunk-LB3ZZMKT.cjs} +137 -19
  123. package/dist/chunk-LDYZWNJW.cjs +1654 -0
  124. package/dist/{chunk-ULMSSHCJ.cjs → chunk-LMB555QB.cjs} +405 -38
  125. package/dist/{chunk-CBJY23VL.js → chunk-MD4IVS42.js} +3 -3
  126. package/dist/{chunk-VMLKSV26.js → chunk-MDDWEBCX.js} +226 -3
  127. package/dist/chunk-MUWH4QK5.cjs +94 -0
  128. package/dist/{chunk-T6W3Z3SH.cjs → chunk-N2ILK7BF.cjs} +4 -4
  129. package/dist/{chunk-6EX3I5P4.cjs → chunk-N74QRJGP.cjs} +6 -6
  130. package/dist/chunk-NFFHLX37.cjs +132 -0
  131. package/dist/chunk-NJSYWX7H.js +190 -0
  132. package/dist/{chunk-SH5PPVK7.cjs → chunk-NQN5LFN4.cjs} +165 -221
  133. package/dist/chunk-NTQRFOPP.cjs +56 -0
  134. package/dist/{chunk-YFWRJW4B.js → chunk-NWMJPTVL.js} +51 -55
  135. package/dist/{chunk-63ZGNR2T.cjs → chunk-OC6GV5QH.cjs} +42 -42
  136. package/dist/{chunk-7E7GCQCK.js → chunk-OG3MBHM3.js} +9 -3
  137. package/dist/chunk-OMNHTCS4.cjs +264 -0
  138. package/dist/chunk-OQXB6NNC.cjs +117 -0
  139. package/dist/{chunk-Y57W2CT5.cjs → chunk-OV46CCA2.cjs} +51 -55
  140. package/dist/{chunk-6PRZIHGL.cjs → chunk-OV6HHKLE.cjs} +21 -266
  141. package/dist/{chunk-C37BHB7N.cjs → chunk-P26YYPOO.cjs} +5 -5
  142. package/dist/{chunk-2BZHWUSR.cjs → chunk-P7JEKJTZ.cjs} +16 -16
  143. package/dist/{chunk-NGBXXZLL.cjs → chunk-PDXX5UI4.cjs} +45 -45
  144. package/dist/{chunk-FHQFPYV4.js → chunk-PJFTTSKE.js} +8 -7
  145. package/dist/{chunk-GVFJ6T4S.cjs → chunk-PVODJEJ7.cjs} +721 -8
  146. package/dist/{chunk-ZZ7RO2UQ.js → chunk-Q265VZJ4.js} +3 -3
  147. package/dist/{chunk-E7JP3BS3.cjs → chunk-Q47JEE2C.cjs} +4 -4
  148. package/dist/chunk-QBY7LRN2.js +281 -0
  149. package/dist/{chunk-Z6PMDS4G.js → chunk-QDQWKSU3.js} +1090 -53
  150. package/dist/{chunk-GH6C2QGW.cjs → chunk-QEDMOGF3.cjs} +857 -16
  151. package/dist/{chunk-5WUNN6ZN.cjs → chunk-QHSAVOOL.cjs} +24 -2
  152. package/dist/chunk-QJNCDVYM.cjs +137 -0
  153. package/dist/chunk-QM7FJB5W.js +4717 -0
  154. package/dist/chunk-QQFB4RT2.cjs +448 -0
  155. package/dist/chunk-QSYBHQAD.cjs +196 -0
  156. package/dist/{chunk-UGXHYIWT.cjs → chunk-QUJ3ZB55.cjs} +28 -28
  157. package/dist/{chunk-2YSNA2F2.cjs → chunk-QVJMDVYZ.cjs} +5 -5
  158. package/dist/chunk-RAJMAX6D.js +131 -0
  159. package/dist/{chunk-VVKVQZI6.js → chunk-RAN3ECAS.js} +3 -3
  160. package/dist/chunk-RKGUZBOC.js +79 -0
  161. package/dist/{chunk-HLFDZ35S.cjs → chunk-RRQIAJLQ.cjs} +8 -8
  162. package/dist/{chunk-PABONWKI.js → chunk-RXQNRZ5F.js} +3 -3
  163. package/dist/{chunk-7ZHYEITD.cjs → chunk-S4O7CFHQ.cjs} +10 -11
  164. package/dist/chunk-SE7ANBGN.js +128 -0
  165. package/dist/{chunk-X2AVEAZM.cjs → chunk-SJIRCTIS.cjs} +176 -2
  166. package/dist/{chunk-WXQ57LAO.js → chunk-SQXAZHDG.js} +4 -4
  167. package/dist/chunk-SR73L5ZP.cjs +84 -0
  168. package/dist/{chunk-OABEO6HH.js → chunk-SZOLTWWD.js} +2349 -214
  169. package/dist/{chunk-5JEU52DW.js → chunk-TPZ3BN2D.js} +3 -3
  170. package/dist/{chunk-QFU53KRH.js → chunk-TSTFYGGX.js} +4 -5
  171. package/dist/{chunk-EBS32AJI.cjs → chunk-TZCFKZ6Z.cjs} +5 -5
  172. package/dist/chunk-UCVZXQ63.js +724 -0
  173. package/dist/chunk-UGQ3QNV6.js +992 -0
  174. package/dist/chunk-UNMVGZVW.js +142 -0
  175. package/dist/{chunk-TEVX443G.js → chunk-UTUD6GJI.js} +178 -6
  176. package/dist/chunk-UXBYA7DV.cjs +155 -0
  177. package/dist/chunk-V6GXFSK7.cjs +443 -0
  178. package/dist/chunk-VHORVGCG.cjs +761 -0
  179. package/dist/{chunk-B4EKV6HQ.js → chunk-VKCTYLDN.js} +500 -442
  180. package/dist/{chunk-O3MGZDCT.cjs → chunk-VTEXJOSD.cjs} +63 -63
  181. package/dist/chunk-VVAAZITA.cjs +287 -0
  182. package/dist/{chunk-V7AKE5VT.cjs → chunk-W2GA3EQB.cjs} +435 -42
  183. package/dist/chunk-W4GABFCR.js +37 -0
  184. package/dist/chunk-WKEK4NCA.js +490 -0
  185. package/dist/{chunk-5A4TCHOC.cjs → chunk-WNYXT4TE.cjs} +4 -4
  186. package/dist/{chunk-S762UEV5.js → chunk-WTH23ISI.js} +6 -6
  187. package/dist/{chunk-BTKZGHAV.js → chunk-WWNCM473.js} +10 -6
  188. package/dist/{chunk-7X5PNIQJ.js → chunk-X3YFRH6K.js} +27 -25
  189. package/dist/{chunk-4YNYPHH3.cjs → chunk-X75H75UY.cjs} +2351 -213
  190. package/dist/{chunk-LYJJI7ZK.cjs → chunk-XCUDDFKC.cjs} +216 -9
  191. package/dist/chunk-YAO4HPJL.cjs +120 -0
  192. package/dist/chunk-YKY2JBER.cjs +9443 -0
  193. package/dist/chunk-YP5CHEYU.cjs +154 -0
  194. package/dist/{chunk-WRNEH5MO.js → chunk-YW3I2FQL.js} +18 -7
  195. package/dist/{chunk-BRNUPDHJ.js → chunk-Z557DVYN.js} +386 -19
  196. package/dist/{chunk-VSACG2AR.js → chunk-Z6LZUYZF.js} +21 -264
  197. package/dist/chunk-ZHPMP447.cjs +43 -0
  198. package/dist/{chunk-LODTHGST.cjs → chunk-ZK7KX5CD.cjs} +133 -70
  199. package/dist/{chunk-CCPSNT6B.cjs → chunk-ZRPALBQB.cjs} +5 -5
  200. package/dist/chunk-ZVFHPMC5.js +824 -0
  201. package/dist/chunk-ZVQMKUGJ.js +443 -0
  202. package/dist/cli/holoscript-runner.cjs +86 -48
  203. package/dist/cli/holoscript-runner.js +54 -16
  204. package/dist/codebase/index.cjs +1 -1
  205. package/dist/codebase/index.js +1 -1
  206. package/dist/compiler/agent-inference.cjs +11 -11
  207. package/dist/compiler/agent-inference.js +9 -6
  208. package/dist/compiler/android-xr.cjs +13 -12
  209. package/dist/compiler/android-xr.js +11 -10
  210. package/dist/compiler/android.cjs +12 -12
  211. package/dist/compiler/android.js +10 -10
  212. package/dist/compiler/business-quest.cjs +10 -10
  213. package/dist/compiler/business-quest.js +2 -2
  214. package/dist/compiler/coco.cjs +1 -1
  215. package/dist/compiler/coco.js +1 -1
  216. package/dist/compiler/context.cjs +9 -9
  217. package/dist/compiler/context.js +6 -6
  218. package/dist/compiler/daimon-seed.cjs +36 -0
  219. package/dist/compiler/daimon-seed.js +12 -0
  220. package/dist/compiler/domain-block-utils.cjs +205 -156
  221. package/dist/compiler/domain-block-utils.js +8 -7
  222. package/dist/compiler/dtdl.cjs +10 -10
  223. package/dist/compiler/dtdl.js +7 -7
  224. package/dist/compiler/gltf-pipeline.cjs +9 -9
  225. package/dist/compiler/gltf-pipeline.js +2 -2
  226. package/dist/compiler/godot.cjs +10 -9
  227. package/dist/compiler/godot.js +9 -8
  228. package/dist/compiler/incremental.cjs +11 -11
  229. package/dist/compiler/incremental.js +6 -6
  230. package/dist/compiler/index.cjs +2585 -3273
  231. package/dist/compiler/index.d.ts +149 -35
  232. package/dist/compiler/index.js +2197 -3102
  233. package/dist/compiler/ios.cjs +11 -11
  234. package/dist/compiler/ios.js +9 -9
  235. package/dist/compiler/llm-provider-capabilities.cjs +9 -9
  236. package/dist/compiler/llm-provider-capabilities.js +6 -6
  237. package/dist/compiler/nodetoy.cjs +1 -1
  238. package/dist/compiler/nodetoy.js +1 -1
  239. package/dist/compiler/openxr.cjs +11 -10
  240. package/dist/compiler/openxr.js +10 -9
  241. package/dist/compiler/remotion.cjs +1 -1
  242. package/dist/compiler/remotion.js +1 -1
  243. package/dist/compiler/reproducibility.cjs +1 -1
  244. package/dist/compiler/reproducibility.js +1 -1
  245. package/dist/compiler/sdf.cjs +11 -10
  246. package/dist/compiler/sdf.js +9 -8
  247. package/dist/compiler/semantic-scene.cjs +7 -7
  248. package/dist/compiler/semantic-scene.js +2 -2
  249. package/dist/compiler/state.cjs +9 -9
  250. package/dist/compiler/state.js +7 -7
  251. package/dist/compiler/trait-composition.cjs +11 -11
  252. package/dist/compiler/trait-composition.js +7 -7
  253. package/dist/compiler/traits/ProvenanceSemiring.d.ts +167 -0
  254. package/dist/compiler/traits/Semiring.d.ts +26 -0
  255. package/dist/compiler/unity.cjs +11 -10
  256. package/dist/compiler/unity.js +10 -9
  257. package/dist/compiler/unreal.cjs +12 -11
  258. package/dist/compiler/unreal.js +10 -9
  259. package/dist/compiler/urdf.cjs +18 -17
  260. package/dist/compiler/urdf.js +9 -8
  261. package/dist/compiler/usd-physics.cjs +11 -10
  262. package/dist/compiler/usd-physics.js +8 -7
  263. package/dist/compiler/visionos.cjs +11 -10
  264. package/dist/compiler/visionos.js +10 -9
  265. package/dist/compiler/vrchat.cjs +11 -10
  266. package/dist/compiler/vrchat.js +9 -8
  267. package/dist/compiler/wasm.cjs +14 -13
  268. package/dist/compiler/wasm.js +9 -8
  269. package/dist/compiler/webgpu.cjs +10 -9
  270. package/dist/compiler/webgpu.js +9 -8
  271. package/dist/constants.cjs +398 -0
  272. package/dist/constants.js +9 -0
  273. package/dist/coordinators/index.cjs +4 -1
  274. package/dist/coordinators/index.js +4 -1
  275. package/dist/debugger.cjs +11 -9
  276. package/dist/debugger.js +9 -7
  277. package/dist/{dist-ACXG6IH5.cjs → dist-GRMOP2UL.cjs} +341 -65
  278. package/dist/{dist-VD4L6V7Q.js → dist-ZBUKU2JG.js} +333 -63
  279. package/dist/entries/interop.cjs +23 -23
  280. package/dist/entries/interop.js +3 -3
  281. package/dist/entries/scripting.cjs +12 -11
  282. package/dist/entries/scripting.js +8 -7
  283. package/dist/evolution/index.cjs +66 -0
  284. package/dist/evolution/index.d.ts +162 -0
  285. package/dist/evolution/index.js +17 -0
  286. package/dist/hololand/index.cjs +41 -37
  287. package/dist/hololand/index.js +3 -3
  288. package/dist/index.cjs +12394 -3224
  289. package/dist/index.d.ts +260 -18
  290. package/dist/index.js +10755 -2182
  291. package/dist/keyword-registry/PluginKeywordRegistry.d.ts +138 -0
  292. package/dist/keyword-registry/index.cjs +29 -0
  293. package/dist/keyword-registry/index.d.ts +1 -0
  294. package/dist/keyword-registry/index.js +4 -0
  295. package/dist/math/tropical-spmv.cjs +11 -11
  296. package/dist/math/tropical-spmv.d.ts +1 -0
  297. package/dist/math/tropical-spmv.js +2 -2
  298. package/dist/math/tropicalSpmv.d.ts +43 -0
  299. package/dist/math/vec3.cjs +1 -1
  300. package/dist/math/vec3.js +1 -1
  301. package/dist/matter/StagedMatter.d.ts +82 -0
  302. package/dist/matter/index.cjs +17 -0
  303. package/dist/matter/index.d.ts +1 -0
  304. package/dist/matter/index.js +4 -0
  305. package/dist/{ml-dsa-Z7JDKW4L.js → ml-dsa-J6VKVT4K.js} +3 -3
  306. package/dist/{ml-dsa-FSKBTE3W.cjs → ml-dsa-MTIK4ZUQ.cjs} +23 -23
  307. package/dist/paper-0c-spike/index.cjs +1 -1
  308. package/dist/paper-0c-spike/index.js +1 -1
  309. package/dist/parameter-envelope/ParameterEnvelope.d.ts +128 -0
  310. package/dist/parameter-envelope/index.cjs +17 -0
  311. package/dist/parameter-envelope/index.d.ts +2 -0
  312. package/dist/parameter-envelope/index.js +4 -0
  313. package/dist/parser/HoloCompositionTypes.d.ts +2013 -0
  314. package/dist/parser/PipelineParser.d.ts +162 -0
  315. package/dist/parser.cjs +36 -20
  316. package/dist/parser.js +13 -9
  317. package/dist/plugin-manifest/ManifestAutoLoader.d.ts +35 -0
  318. package/dist/plugin-manifest/PluginManifest.d.ts +156 -0
  319. package/dist/plugin-manifest/index.cjs +25 -0
  320. package/dist/plugin-manifest/index.d.ts +2 -0
  321. package/dist/plugin-manifest/index.js +4 -0
  322. package/dist/plugin-solver-contract/PluginSolverContract.d.ts +288 -0
  323. package/dist/plugin-solver-contract/index.cjs +41 -0
  324. package/dist/plugin-solver-contract/index.d.ts +1 -0
  325. package/dist/plugin-solver-contract/index.js +4 -0
  326. package/dist/policy/ContentPolicyGate.d.ts +51 -0
  327. package/dist/policy/PolicyPack.d.ts +120 -0
  328. package/dist/policy/blocklist.d.ts +32 -0
  329. package/dist/policy/defaults.d.ts +44 -0
  330. package/dist/policy/index.cjs +106 -0
  331. package/dist/policy/index.d.ts +17 -0
  332. package/dist/policy/index.js +5 -0
  333. package/dist/policy/jsonLogic.d.ts +31 -0
  334. package/dist/policy/types.d.ts +174 -0
  335. package/dist/proof-composition/ProofCompositionLaw.d.ts +93 -0
  336. package/dist/proof-composition/index.cjs +25 -0
  337. package/dist/proof-composition/index.d.ts +1 -0
  338. package/dist/proof-composition/index.js +4 -0
  339. package/dist/receipts/hash-policy.d.ts +85 -0
  340. package/dist/reconstruction/index.cjs +75 -47
  341. package/dist/reconstruction/index.js +5 -5
  342. package/dist/runtime/plugin-trait-registrar.d.ts +36 -0
  343. package/dist/runtime.cjs +81 -79
  344. package/dist/runtime.js +9 -7
  345. package/dist/scene-presets-EDKYZ5GW.js +4 -0
  346. package/dist/scene-presets-NCW2CFRS.cjs +17 -0
  347. package/dist/self-improvement/index.cjs +1 -1
  348. package/dist/self-improvement/index.js +1 -1
  349. package/dist/{src-PT2FERDV.cjs → src-G3D7ZATQ.cjs} +545 -21
  350. package/dist/{src-J6CM4AUR.js → src-UXYA7HM6.js} +539 -16
  351. package/dist/storage/index.cjs +10 -10
  352. package/dist/storage/index.js +3 -3
  353. package/dist/testing.cjs +1 -1
  354. package/dist/testing.js +1 -1
  355. package/dist/tools/index.cjs +3631 -0
  356. package/dist/tools/index.js +3581 -0
  357. package/dist/traitDocs/traitDocs.cjs +9 -9
  358. package/dist/traitDocs/traitDocs.d.ts +1 -0
  359. package/dist/traitDocs/traitDocs.js +3 -3
  360. package/dist/traits/ControlLoopTrait.d.ts +154 -0
  361. package/dist/traits/KinematicChainTrait.d.ts +116 -0
  362. package/dist/traits/SensorSamplingTrait.d.ts +154 -0
  363. package/dist/traits/TraitTypes.d.ts +270 -0
  364. package/dist/traits/TransactionTrait.d.ts +121 -0
  365. package/dist/traits/botanical-lotus.cjs +54 -50
  366. package/dist/traits/botanical-lotus.js +2 -5
  367. package/dist/traits/control-loop.cjs +21 -0
  368. package/dist/traits/control-loop.d.ts +1 -0
  369. package/dist/traits/control-loop.js +4 -0
  370. package/dist/traits/engines/cloth-verlet.d.ts +65 -0
  371. package/dist/traits/engines/index.cjs +19 -19
  372. package/dist/traits/engines/index.d.ts +15 -275
  373. package/dist/traits/engines/index.js +3 -3
  374. package/dist/traits/engines/motion-data-schema.d.ts +119 -0
  375. package/dist/traits/engines/motion-matching.d.ts +102 -0
  376. package/dist/traits/engines/noise.d.ts +25 -0
  377. package/dist/traits/engines/onnx-adapter.d.ts +173 -0
  378. package/dist/traits/engines/onnx-motion-matching.d.ts +163 -0
  379. package/dist/traits/engines/pfnn-network.d.ts +92 -0
  380. package/dist/traits/engines/synthetic-walk-cycle.d.ts +38 -0
  381. package/dist/traits/engines/tensor-ops.d.ts +15 -0
  382. package/dist/traits/index.cjs +2789 -1259
  383. package/dist/traits/index.d.ts +35 -0
  384. package/dist/traits/index.js +1692 -411
  385. package/dist/traits/kinematic-chain.cjs +25 -0
  386. package/dist/traits/kinematic-chain.d.ts +1 -0
  387. package/dist/traits/kinematic-chain.js +4 -0
  388. package/dist/traits/sensor-sampling.cjs +33 -0
  389. package/dist/traits/sensor-sampling.d.ts +1 -0
  390. package/dist/traits/sensor-sampling.js +4 -0
  391. package/dist/traits/simulation-solver-factory.cjs +1 -1
  392. package/dist/traits/simulation-solver-factory.js +1 -1
  393. package/dist/traits/transaction.cjs +29 -0
  394. package/dist/traits/transaction.d.ts +1 -0
  395. package/dist/traits/transaction.js +4 -0
  396. package/dist/traits/webcam-gaze.cjs +1 -1
  397. package/dist/traits/webcam-gaze.js +1 -1
  398. package/dist/type-checker.cjs +7 -6
  399. package/dist/type-checker.js +5 -4
  400. package/dist/types/AdvancedTypeSystem.d.ts +489 -0
  401. package/dist/types/HoloScriptPlus.d.ts +810 -0
  402. package/dist/types/base.d.ts +248 -0
  403. package/dist/types.d.ts +799 -0
  404. package/dist/world/index.cjs +3 -4
  405. package/dist/world/index.js +3 -4
  406. package/dist/world-model/index.cjs +1 -1
  407. package/dist/world-model/index.js +1 -1
  408. package/dist/wot/index.cjs +1 -1
  409. package/dist/wot/index.js +1 -1
  410. package/package.json +80 -13
  411. package/dist/GLTFPipeline-3EJLL3TS.cjs +0 -38
  412. package/dist/GLTFPipeline-3OWJV2VK.js +0 -17
  413. package/dist/HoloScriptPlusParser-ADWRY5OS.cjs +0 -698
  414. package/dist/HoloScriptPlusParser-JLJDXHSC.js +0 -693
  415. package/dist/HoloScriptPlusParser-QCGFPWIL.cjs +0 -27
  416. package/dist/HoloScriptPlusParser-WENAFEFV.js +0 -10
  417. package/dist/HoloScriptRuntime-GGRVEU4T.cjs +0 -19
  418. package/dist/HoloScriptRuntime-GJK6VJPH.js +0 -10
  419. package/dist/chunk-22Q5A6RV.js +0 -979
  420. package/dist/chunk-4C57PR42.js +0 -468
  421. package/dist/chunk-4W5G5QVL.cjs +0 -847
  422. package/dist/chunk-5ET6L4NS.js +0 -487
  423. package/dist/chunk-C4GSLCHE.cjs +0 -7153
  424. package/dist/chunk-F2G6CWFT.js +0 -7089
  425. package/dist/chunk-G6PNEASF.cjs +0 -814
  426. package/dist/chunk-GTA4Q3A3.js +0 -1491
  427. package/dist/chunk-HCCQLAA4.cjs +0 -74
  428. package/dist/chunk-HFSVMKM3.cjs +0 -72
  429. package/dist/chunk-KAIVDEIG.cjs +0 -4539
  430. package/dist/chunk-KQU64CIX.cjs +0 -1508
  431. package/dist/chunk-MSYSQ2AJ.js +0 -4533
  432. package/dist/chunk-NHJLP37F.js +0 -70
  433. package/dist/chunk-NHYRRAGI.cjs +0 -490
  434. package/dist/chunk-OIQYIIO3.cjs +0 -473
  435. package/dist/chunk-OL46QLBJ.js +0 -61
  436. package/dist/chunk-SKZPC5AG.cjs +0 -984
  437. package/dist/chunk-SLHLXUMO.js +0 -445
  438. package/dist/chunk-UOIGFQXC.cjs +0 -9750
  439. package/dist/chunk-UOL6Y5TD.cjs +0 -759
  440. package/dist/chunk-UVFI7XIR.cjs +0 -452
  441. package/dist/chunk-VEPGBETF.js +0 -844
  442. package/dist/chunk-XQ5MWMP2.js +0 -756
  443. package/dist/chunk-XT6JY5W5.js +0 -9684
  444. package/dist/chunk-YRRAUB35.js +0 -811
  445. package/dist/compiler/GasOptimizationAnalyzer.d.ts +0 -73
  446. package/dist/compiler/NFTMarketplaceCompiler.d.ts +0 -23
  447. package/dist/compiler/ar.cjs +0 -23
  448. package/dist/compiler/ar.js +0 -11
  449. package/dist/compiler/babylon.cjs +0 -21
  450. package/dist/compiler/babylon.js +0 -15
  451. package/dist/compiler/multi-layer.cjs +0 -24
  452. package/dist/compiler/multi-layer.js +0 -15
  453. package/dist/compiler/playcanvas.cjs +0 -19
  454. package/dist/compiler/playcanvas.js +0 -13
  455. package/dist/compiler/r3f.cjs +0 -39
  456. package/dist/compiler/r3f.d.ts +0 -22
  457. package/dist/compiler/r3f.js +0 -17
  458. package/dist/compiler/vrr.cjs +0 -24
  459. package/dist/compiler/vrr.js +0 -12
  460. package/dist/parser/NFTMarketplaceTypes.d.ts +0 -191
  461. package/dist/playwright-3AT3AKTV.cjs +0 -98673
  462. package/dist/playwright-VZPDVUEQ.js +0 -98660
@@ -1,4 +1,5 @@
1
1
  import { parsePipeline } from './chunk-SYTRBGDS.js';
2
+ import { ErrorRecovery } from './chunk-Z6LZUYZF.js';
2
3
 
3
4
  // src/parser/TypoDetector.ts
4
5
  var TypoDetector = class {
@@ -170,6 +171,17 @@ var KEYWORDS = {
170
171
  waypoints: "WAYPOINTS",
171
172
  constraint: "CONSTRAINT",
172
173
  terrain: "TERRAIN",
174
+ // MMO/AAA game constructs (v6.2)
175
+ loot_table: "LOOT_TABLE",
176
+ world_chunk: "WORLD_CHUNK",
177
+ spawn_point: "SPAWN_POINT",
178
+ game_trigger: "GAME_TRIGGER",
179
+ movement_path: "MOVEMENT_PATH",
180
+ reaction_trigger: "REACTION_TRIGGER",
181
+ world_layer: "WORLD_LAYER",
182
+ dungeon_instance: "DUNGEON_INSTANCE",
183
+ world_shard: "WORLD_SHARD",
184
+ real_estate: "REAL_ESTATE",
173
185
  // IoT / Digital Twin
174
186
  sensor: "IOT_SENSOR",
175
187
  device: "IOT_DEVICE",
@@ -250,6 +262,10 @@ var KEYWORDS = {
250
262
  bridge: "WEB3_CONTRACT",
251
263
  // Perception & simulation layer (v4.2 — March 2026)
252
264
  material: "MATERIAL",
265
+ material_graph: "MATERIAL_GRAPH",
266
+ light_field: "LIGHT_FIELD",
267
+ nav_field: "NAV_FIELD",
268
+ physics_contract: "PHYSICS_CONTRACT",
253
269
  pbr_material: "PBR_MATERIAL",
254
270
  unlit_material: "UNLIT_MATERIAL",
255
271
  shader: "SHADER",
@@ -271,6 +287,7 @@ var KEYWORDS = {
271
287
  particles: "PARTICLES",
272
288
  emitter: "EMITTER",
273
289
  vfx: "VFX",
290
+ particle_field: "PARTICLE_FIELD",
274
291
  post_processing: "POST_PROCESSING",
275
292
  post_fx: "POST_FX",
276
293
  render_pipeline: "POST_PROCESSING",
@@ -286,6 +303,7 @@ var KEYWORDS = {
286
303
  climate: "WEATHER",
287
304
  simulation: "SIMULATION",
288
305
  procedural: "PROCEDURAL",
306
+ pcg_graph: "PCG_GRAPH",
289
307
  generate: "PROCEDURAL",
290
308
  scatter: "SCATTER",
291
309
  distribute: "SCATTER",
@@ -329,6 +347,11 @@ var KEYWORDS = {
329
347
  payment_gate: "PAYMENT_GATE",
330
348
  subscription: "SUBSCRIPTION",
331
349
  tip_jar: "TIP_JAR",
350
+ // SimulationContract block (v6.3 — NORTH_STAR thesis: simulation IS the proof)
351
+ sim_contract: "HOLO_CONTRACT",
352
+ // Pub/sub messaging primitives (v6.4)
353
+ topic: "HOLO_TOPIC",
354
+ channel: "HOLO_CHANNEL",
332
355
  // v6 Universal domains (v5.4 — Domains Unified)
333
356
  service: "SERVICE_BLOCK",
334
357
  endpoint: "ENDPOINT_BLOCK",
@@ -760,6 +783,7 @@ var KEYWORDS_AS_IDENTIFIERS = [
760
783
  "EFFECTS",
761
784
  "CAMERA",
762
785
  "BIND",
786
+ "CONNECT",
763
787
  "TIMELINE",
764
788
  "AUDIO",
765
789
  "ZONE",
@@ -792,7 +816,9 @@ var KEYWORDS_AS_IDENTIFIERS = [
792
816
  "COMPOSITION",
793
817
  "SPATIAL_GROUP",
794
818
  "SPATIAL_AGENT",
795
- "SPATIAL_CONTAINER"
819
+ "SPATIAL_CONTAINER",
820
+ "HOLO_TOPIC",
821
+ "HOLO_CHANNEL"
796
822
  ];
797
823
  function isKeywordAsIdentifierType(api, type) {
798
824
  if (api.DOMAIN_TOKENS.has(type)) return true;
@@ -1048,7 +1074,6 @@ function parseObjectExpression(api) {
1048
1074
 
1049
1075
  // src/parser/HoloCompositionParser.ts
1050
1076
  var _HoloCompositionParser = class _HoloCompositionParser {
1051
- // Track parsing context for better errors
1052
1077
  constructor(options = {}) {
1053
1078
  this.tokens = [];
1054
1079
  this.pos = 0;
@@ -1061,6 +1086,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1061
1086
  strict: false,
1062
1087
  ...options
1063
1088
  };
1089
+ this.errorRecovery = new ErrorRecovery(this.options.knownTraits);
1090
+ }
1091
+ /**
1092
+ * The error-recovery engine for this parser, seeded with the injected
1093
+ * `knownTraits` union when one was supplied via parser options. Exposed so
1094
+ * tooling (and tests) can verify the trait-vocabulary seam is wired through.
1095
+ */
1096
+ getErrorRecovery() {
1097
+ return this.errorRecovery;
1064
1098
  }
1065
1099
  /** Instance accessor for the static DOMAIN_TOKENS set — satisfies ExpressionParserApi. */
1066
1100
  get DOMAIN_TOKENS() {
@@ -1135,7 +1169,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1135
1169
  domainBlocks: [],
1136
1170
  // v4.5 additions — CRSEC norm lifecycle
1137
1171
  norms: [],
1138
- metanorms: []
1172
+ metanorms: [],
1173
+ // v6.2 additions — MMO/AAA game constructs
1174
+ spawnPoints: [],
1175
+ triggers: [],
1176
+ lootTables: [],
1177
+ worldChunks: [],
1178
+ worldLayers: [],
1179
+ dungeonInstances: [],
1180
+ worldShards: [],
1181
+ movementPaths: [],
1182
+ reactionTriggers: [],
1183
+ policyPacks: []
1139
1184
  };
1140
1185
  while (!this.isAtEnd()) {
1141
1186
  try {
@@ -1179,8 +1224,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1179
1224
  } else if (decoratorName === "state") {
1180
1225
  composition.state = this.parseStateBody();
1181
1226
  } else if (decoratorName === "state_machine") {
1227
+ const name = this.parseOptionalStateMachineName("implicit");
1182
1228
  if (this.check("LBRACE")) {
1183
- composition.stateMachines.push(this.parseStateMachineFromDecorator());
1229
+ composition.stateMachines.push(this.parseStateMachineFromDecorator(name));
1184
1230
  }
1185
1231
  } else {
1186
1232
  composition.traits = composition.traits || [];
@@ -1210,7 +1256,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1210
1256
  composition.logic = this.parseLogic();
1211
1257
  } else if (this.check("TIMELINE")) {
1212
1258
  composition.timelines.push(this.parseTimeline());
1213
- } else if (this.check("STATE")) {
1259
+ } else if (this.check("STATE") && this.peek(1).type !== "COLON") {
1214
1260
  composition.state = this.parseState();
1215
1261
  } else if (this.check("IMPORT")) {
1216
1262
  composition.imports.push(this.parseImport());
@@ -1245,8 +1291,53 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1245
1291
  composition.norms.push(this.parseNormBlock());
1246
1292
  } else if (this.check("METANORM")) {
1247
1293
  composition.metanorms.push(this.parseMetanormBlock());
1294
+ } else if (this.check("HOLO_CONTRACT")) {
1295
+ composition.contract = this.parseContractBlock();
1296
+ } else if (this.check("IDENTIFIER") && this.current().value === "policy_pack") {
1297
+ composition.policyPacks.push(this.parsePolicyPackBlock());
1298
+ } else if (this.check("HOLO_TOPIC")) {
1299
+ if (!composition.topics) composition.topics = [];
1300
+ composition.topics.push(this.parseTopicBlock());
1301
+ } else if (this.check("HOLO_CHANNEL")) {
1302
+ if (!composition.channels) composition.channels = [];
1303
+ composition.channels.push(this.parseChannelBlock());
1304
+ } else if (this.check("CONNECT")) {
1305
+ if (!composition.connections) composition.connections = [];
1306
+ composition.connections.push(this.parseConnectionStmt());
1307
+ } else if (this.check("IDENTIFIER") && this.current().value === "shareplay") {
1308
+ composition.metadata = {
1309
+ ...composition.metadata ?? {},
1310
+ shareplay: this.parseSharePlayBlock()
1311
+ };
1312
+ } else if (this.isLooseOnHandlerStart()) {
1313
+ this.skipLooseOnHandler();
1314
+ } else if (this.check("LOOT_TABLE")) {
1315
+ composition.lootTables.push(this.parseLootTable());
1316
+ } else if (this.check("WORLD_CHUNK")) {
1317
+ composition.worldChunks.push(this.parseWorldChunk());
1318
+ } else if (this.check("SPAWN_POINT")) {
1319
+ composition.spawnPoints.push(this.parseSpawnPoint());
1320
+ } else if (this.check("GAME_TRIGGER")) {
1321
+ composition.triggers.push(this.parseGameTrigger());
1322
+ } else if (this.check("MOVEMENT_PATH")) {
1323
+ composition.movementPaths.push(this.parseMovementPath());
1324
+ } else if (this.check("REACTION_TRIGGER")) {
1325
+ composition.reactionTriggers.push(this.parseReactionTrigger());
1326
+ } else if (this.check("WORLD_LAYER")) {
1327
+ composition.worldLayers.push(this.parseWorldLayer());
1328
+ } else if (this.check("DUNGEON_INSTANCE")) {
1329
+ composition.dungeonInstances.push(this.parseDungeonInstance());
1330
+ } else if (this.check("WORLD_SHARD")) {
1331
+ composition.worldShards.push(this.parseWorldShard());
1332
+ } else if (this.check("REAL_ESTATE")) {
1333
+ composition.domainBlocks.push(this.parseDomainBlock());
1334
+ } else if (this.check("SCENE")) {
1335
+ if (!composition.scenes) composition.scenes = [];
1336
+ composition.scenes.push(this.parseScene());
1248
1337
  } else if (this.isDomainBlockToken()) {
1249
1338
  composition.domainBlocks.push(this.parseDomainBlock());
1339
+ } else if (this.isLooseDomainBlockStart() || this.isLooseNamedDomainBlockStart()) {
1340
+ composition.domainBlocks.push(this.parseDomainBlock());
1250
1341
  } else if (this.check("MODULE")) {
1251
1342
  this.advance();
1252
1343
  if (this.check("STRING")) this.expectString();
@@ -1302,12 +1393,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1302
1393
  this.expect("LBRACE");
1303
1394
  this.skipNewlines();
1304
1395
  while (!this.check("RBRACE") && !this.isAtEnd()) {
1305
- this.skipNewlines();
1396
+ this.skipBlockMemberSeparators();
1306
1397
  if (this.check("RBRACE")) break;
1307
- const key = this.expectIdentifier();
1308
- this.expect("COLON");
1309
- const value = this.parseValue();
1310
- properties.push({ type: "EnvironmentProperty", key, value });
1398
+ if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
1399
+ const key = this.parsePropertyKey();
1400
+ const value = this.parseBlockTraitConfig();
1401
+ properties.push({ type: "EnvironmentProperty", key, value });
1402
+ } else {
1403
+ const key = this.parsePropertyKey();
1404
+ this.expect("COLON");
1405
+ const value = this.parseValue();
1406
+ properties.push({ type: "EnvironmentProperty", key, value });
1407
+ }
1311
1408
  this.skipNewlines();
1312
1409
  }
1313
1410
  this.expect("RBRACE");
@@ -1337,15 +1434,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1337
1434
  this.expect("LBRACE");
1338
1435
  this.skipNewlines();
1339
1436
  while (!this.check("RBRACE") && !this.isAtEnd()) {
1340
- this.skipNewlines();
1437
+ this.skipBlockMemberSeparators();
1341
1438
  if (this.check("RBRACE")) break;
1342
1439
  if (this.check("AT")) {
1343
1440
  this.advance();
1344
1441
  const traitName = this.expectIdentifier();
1345
1442
  const config = this.parseOptionalTraitConfig();
1346
1443
  traits.push({ type: "ObjectTrait", name: traitName, config });
1347
- } else if (this.check("IDENTIFIER")) {
1348
- const key = this.expectIdentifier();
1444
+ } else if (this.isPropertyName()) {
1445
+ const key = this.parsePropertyKey();
1349
1446
  if (this.check("COLON")) {
1350
1447
  this.advance();
1351
1448
  properties.push({ type: "ObjectProperty", key, value: this.parseValue() });
@@ -1433,13 +1530,31 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1433
1530
  domainBlocks: [],
1434
1531
  // v4.5 additions — CRSEC norm lifecycle
1435
1532
  norms: [],
1436
- metanorms: []
1533
+ metanorms: [],
1534
+ // v6.2 additions — MMO/AAA game constructs
1535
+ spawnPoints: [],
1536
+ triggers: [],
1537
+ lootTables: [],
1538
+ worldChunks: [],
1539
+ worldLayers: [],
1540
+ dungeonInstances: [],
1541
+ worldShards: [],
1542
+ movementPaths: [],
1543
+ reactionTriggers: [],
1544
+ policyPacks: []
1437
1545
  };
1438
1546
  while (!this.check("RBRACE") && !this.isAtEnd()) {
1439
1547
  try {
1440
- this.skipNewlines();
1548
+ this.skipBlockMemberSeparators();
1441
1549
  if (this.check("RBRACE")) break;
1442
- if (this.check("IMPORT")) {
1550
+ if (this.peek(1).type === "COLON" && (this.isPropertyName() || this.check("METADATA_BLOCK"))) {
1551
+ const key = this.advance().value;
1552
+ this.advance();
1553
+ const value = !this.check("RBRACE") && !this.isAtEnd() ? this.parseValue() : null;
1554
+ if (key === "metadata" && value && typeof value === "object" && !Array.isArray(value)) {
1555
+ composition.metadata = { ...composition.metadata ?? {}, ...value };
1556
+ }
1557
+ } else if (this.check("IMPORT")) {
1443
1558
  composition.imports.push(this.parseImport());
1444
1559
  } else if (this.check("THEME")) {
1445
1560
  composition.theme = this.parseTheme();
@@ -1448,7 +1563,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1448
1563
  } else if (this.check("SCENE")) {
1449
1564
  if (!composition.scenes) composition.scenes = [];
1450
1565
  composition.scenes.push(this.parseScene());
1451
- } else if (this.check("STATE")) {
1566
+ } else if (this.check("STATE") && this.peek(1).type !== "COLON") {
1452
1567
  composition.state = this.parseState();
1453
1568
  } else if (this.check("METADATA_BLOCK")) {
1454
1569
  this.advance();
@@ -1520,8 +1635,48 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1520
1635
  composition.norms.push(this.parseNormBlock());
1521
1636
  } else if (this.check("METANORM")) {
1522
1637
  composition.metanorms.push(this.parseMetanormBlock());
1638
+ } else if (this.check("HOLO_CONTRACT")) {
1639
+ composition.contract = this.parseContractBlock();
1640
+ } else if (this.check("IDENTIFIER") && this.current().value === "policy_pack") {
1641
+ composition.policyPacks.push(this.parsePolicyPackBlock());
1642
+ } else if (this.check("HOLO_TOPIC")) {
1643
+ if (!composition.topics) composition.topics = [];
1644
+ composition.topics.push(this.parseTopicBlock());
1645
+ } else if (this.check("HOLO_CHANNEL")) {
1646
+ if (!composition.channels) composition.channels = [];
1647
+ composition.channels.push(this.parseChannelBlock());
1648
+ } else if (this.check("CONNECT")) {
1649
+ if (!composition.connections) composition.connections = [];
1650
+ composition.connections.push(this.parseConnectionStmt());
1651
+ } else if (this.check("IDENTIFIER") && this.current().value === "shareplay") {
1652
+ composition.metadata = {
1653
+ ...composition.metadata ?? {},
1654
+ shareplay: this.parseSharePlayBlock()
1655
+ };
1656
+ } else if (this.check("LOOT_TABLE")) {
1657
+ composition.lootTables.push(this.parseLootTable());
1658
+ } else if (this.check("WORLD_CHUNK")) {
1659
+ composition.worldChunks.push(this.parseWorldChunk());
1660
+ } else if (this.check("SPAWN_POINT")) {
1661
+ composition.spawnPoints.push(this.parseSpawnPoint());
1662
+ } else if (this.check("GAME_TRIGGER")) {
1663
+ composition.triggers.push(this.parseGameTrigger());
1664
+ } else if (this.check("MOVEMENT_PATH")) {
1665
+ composition.movementPaths.push(this.parseMovementPath());
1666
+ } else if (this.check("REACTION_TRIGGER")) {
1667
+ composition.reactionTriggers.push(this.parseReactionTrigger());
1668
+ } else if (this.check("WORLD_LAYER")) {
1669
+ composition.worldLayers.push(this.parseWorldLayer());
1670
+ } else if (this.check("DUNGEON_INSTANCE")) {
1671
+ composition.dungeonInstances.push(this.parseDungeonInstance());
1672
+ } else if (this.check("WORLD_SHARD")) {
1673
+ composition.worldShards.push(this.parseWorldShard());
1674
+ } else if (this.check("REAL_ESTATE")) {
1675
+ composition.domainBlocks.push(this.parseDomainBlock());
1523
1676
  } else if (this.isDomainBlockToken()) {
1524
1677
  composition.domainBlocks.push(this.parseDomainBlock());
1678
+ } else if (this.isLooseDomainBlockStart() || this.isLooseNamedDomainBlockStart()) {
1679
+ composition.domainBlocks.push(this.parseDomainBlock());
1525
1680
  } else if (this.check("MODULE")) {
1526
1681
  composition.domainBlocks.push(this.parseDomainBlock());
1527
1682
  } else if (this.check("AT")) {
@@ -1562,8 +1717,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1562
1717
  } else if (decoratorName === "world" || decoratorName === "environment") {
1563
1718
  composition.environment = this.parseEnvironmentBody();
1564
1719
  } else if (decoratorName === "state_machine") {
1720
+ const name2 = this.parseOptionalStateMachineName("implicit");
1565
1721
  if (this.check("LBRACE")) {
1566
- composition.stateMachines.push(this.parseStateMachineFromDecorator());
1722
+ composition.stateMachines.push(this.parseStateMachineFromDecorator(name2));
1567
1723
  }
1568
1724
  } else {
1569
1725
  composition.traits = composition.traits || [];
@@ -1574,6 +1730,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1574
1730
  } else if (this.check("ACTION") || this.check("ASYNC")) {
1575
1731
  composition.actions = composition.actions || [];
1576
1732
  composition.actions.push(this.parseAction());
1733
+ } else if (this.check("FUNCTION")) {
1734
+ this.skipFunctionDeclaration();
1577
1735
  } else if (this.check("USING")) {
1578
1736
  this.advance();
1579
1737
  if (this.check("STRING") || this.check("IDENTIFIER")) this.advance();
@@ -1581,27 +1739,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1581
1739
  this.advance();
1582
1740
  if (this.check("IDENTIFIER")) this.advance();
1583
1741
  }
1584
- } else if (this.check("IDENTIFIER") && this.current().value === "on" && this.peek(1).type === "IDENTIFIER") {
1585
- const eventName = this.peek(1).value;
1586
- this.advance();
1587
- this.advance();
1588
- while (this.check("DOT")) {
1589
- this.advance();
1590
- if (this.check("IDENTIFIER")) this.advance();
1591
- }
1592
- let parameters = [];
1593
- if (this.check("LPAREN")) {
1594
- parameters = this.parseParameterList();
1595
- }
1596
- if (this.check("LBRACE")) this.skipBlock();
1597
- composition.eventHandlers = composition.eventHandlers || [];
1598
- composition.eventHandlers.push({
1599
- type: "EventHandler",
1600
- event: eventName,
1601
- parameters,
1602
- body: []
1603
- // Skipped body
1604
- });
1742
+ } else if (this.isLooseOnHandlerStart()) {
1743
+ this.skipLooseOnHandler();
1605
1744
  } else if (this.check("COLON")) {
1606
1745
  this.advance();
1607
1746
  if (!this.check("RBRACE") && !this.isAtEnd()) this.parseValue();
@@ -1630,6 +1769,10 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1630
1769
  if (this.check("COLON")) {
1631
1770
  this.advance();
1632
1771
  if (!this.check("RBRACE") && !this.isAtEnd()) this.parseValue();
1772
+ } else if (this.check("LBRACKET")) {
1773
+ this.advance();
1774
+ while (!this.check("RBRACKET") && !this.isAtEnd()) this.advance();
1775
+ if (this.check("RBRACKET")) this.advance();
1633
1776
  } else {
1634
1777
  if (this.check("STRING") || this.check("IDENTIFIER")) this.advance();
1635
1778
  if (this.check("LPAREN")) this.skipParens();
@@ -1778,7 +1921,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1778
1921
  this.skipNewlines();
1779
1922
  const properties = [];
1780
1923
  while (!this.check("RBRACE") && !this.isAtEnd()) {
1781
- this.skipNewlines();
1924
+ this.skipBlockMemberSeparators();
1782
1925
  if (this.check("RBRACE")) break;
1783
1926
  if (this.check("PARTICLES") || this.check("PARTICLE_SYSTEM")) {
1784
1927
  const ps = this.parseParticleSystem();
@@ -1787,15 +1930,16 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1787
1930
  key: ps.name,
1788
1931
  value: ps
1789
1932
  });
1933
+ } else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
1934
+ const key = this.parsePropertyKey();
1935
+ const value = this.parseBlockTraitConfig();
1936
+ properties.push({ type: "EnvironmentProperty", key, value });
1790
1937
  } else {
1791
- const key = this.expectIdentifier();
1938
+ const key = this.parsePropertyKey();
1792
1939
  this.expect("COLON");
1793
1940
  const value = this.parseValue();
1794
1941
  properties.push({ type: "EnvironmentProperty", key, value });
1795
1942
  }
1796
- if (this.check("SEMICOLON")) {
1797
- this.advance();
1798
- }
1799
1943
  this.skipNewlines();
1800
1944
  }
1801
1945
  this.expect("RBRACE");
@@ -1825,14 +1969,19 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1825
1969
  let environment;
1826
1970
  const objects = [];
1827
1971
  while (!this.check("RBRACE") && !this.isAtEnd()) {
1828
- this.skipNewlines();
1972
+ this.skipBlockMemberSeparators();
1829
1973
  if (this.check("RBRACE")) break;
1830
1974
  if (this.check("ENVIRONMENT")) {
1831
1975
  environment = this.parseEnvironment();
1832
1976
  } else if (this.check("OBJECT")) {
1833
1977
  objects.push(this.parseObject());
1978
+ } else if (this.check("LBRACE")) {
1979
+ this.skipBlock();
1834
1980
  } else {
1835
1981
  this.advance();
1982
+ if (this.check("STRING") || this.check("IDENTIFIER")) this.advance();
1983
+ if (this.check("LPAREN")) this.skipParens();
1984
+ if (this.check("LBRACE")) this.skipBlock();
1836
1985
  }
1837
1986
  }
1838
1987
  this.expect("RBRACE");
@@ -1856,7 +2005,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1856
2005
  this.skipNewlines();
1857
2006
  const properties = {};
1858
2007
  while (!this.check("RBRACE") && !this.isAtEnd()) {
1859
- this.skipNewlines();
2008
+ this.skipBlockMemberSeparators();
1860
2009
  if (this.check("RBRACE")) break;
1861
2010
  const key = this.expectIdentifier();
1862
2011
  this.expect("COLON");
@@ -1894,24 +2043,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1894
2043
  this.advance();
1895
2044
  }
1896
2045
  }
2046
+ const inlineTraitProperties = [];
2047
+ while (this.check("AT")) {
2048
+ inlineTraitProperties.push(this.parseTraitAsLightProperty(true));
2049
+ }
1897
2050
  this.expect("LBRACE");
1898
2051
  this.skipNewlines();
1899
- const properties = [];
2052
+ const properties = [...inlineTraitProperties];
1900
2053
  while (!this.check("RBRACE") && !this.isAtEnd()) {
1901
- this.skipNewlines();
2054
+ this.skipBlockMemberSeparators();
1902
2055
  if (this.check("RBRACE")) break;
1903
2056
  if (this.check("AT")) {
1904
- this.advance();
1905
- const traitName = this.parseTraitName();
1906
- const cfg = this.parseOptionalTraitConfig();
1907
- const cfgKeys = Object.keys(cfg);
1908
- let traitValue;
1909
- if (cfgKeys.length === 0) traitValue = true;
1910
- else if (cfgKeys.every((k) => /^_arg\d+$/.test(k))) {
1911
- const arr = cfgKeys.sort().map((k) => cfg[k]);
1912
- traitValue = arr.length === 1 ? arr[0] : arr;
1913
- } else traitValue = cfg;
1914
- properties.push({ type: "LightProperty", key: traitName, value: traitValue });
2057
+ properties.push(this.parseTraitAsLightProperty());
1915
2058
  this.skipNewlines();
1916
2059
  continue;
1917
2060
  }
@@ -1947,6 +2090,19 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1947
2090
  properties
1948
2091
  };
1949
2092
  }
2093
+ parseTraitAsLightProperty(requireBodyAfterBareBrace = false) {
2094
+ this.expect("AT");
2095
+ const traitName = this.parseTraitName();
2096
+ const cfg = this.parseOptionalTraitConfig(requireBodyAfterBareBrace);
2097
+ const cfgKeys = Object.keys(cfg);
2098
+ let traitValue;
2099
+ if (cfgKeys.length === 0) traitValue = true;
2100
+ else if (cfgKeys.every((k) => /^_arg\d+$/.test(k))) {
2101
+ const arr = cfgKeys.sort().map((k) => cfg[k]);
2102
+ traitValue = arr.length === 1 ? arr[0] : arr;
2103
+ } else traitValue = cfg;
2104
+ return { type: "LightProperty", key: traitName, value: traitValue };
2105
+ }
1950
2106
  // ===========================================================================
1951
2107
  // EFFECTS (post-processing block)
1952
2108
  // ===========================================================================
@@ -1957,14 +2113,14 @@ var _HoloCompositionParser = class _HoloCompositionParser {
1957
2113
  this.skipNewlines();
1958
2114
  const effects = [];
1959
2115
  while (!this.check("RBRACE") && !this.isAtEnd()) {
1960
- this.skipNewlines();
2116
+ this.skipBlockMemberSeparators();
1961
2117
  if (this.check("RBRACE")) break;
1962
2118
  const effectType = this.expectIdentifier();
1963
2119
  this.expect("LBRACE");
1964
2120
  this.skipNewlines();
1965
2121
  const properties = {};
1966
2122
  while (!this.check("RBRACE") && !this.isAtEnd()) {
1967
- this.skipNewlines();
2123
+ this.skipBlockMemberSeparators();
1968
2124
  if (this.check("RBRACE")) break;
1969
2125
  const key = this.expectIdentifier();
1970
2126
  this.expect("COLON");
@@ -2006,7 +2162,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2006
2162
  this.skipNewlines();
2007
2163
  const properties = [];
2008
2164
  while (!this.check("RBRACE") && !this.isAtEnd()) {
2009
- this.skipNewlines();
2165
+ this.skipBlockMemberSeparators();
2010
2166
  if (this.check("RBRACE")) break;
2011
2167
  if (this.check("AT")) {
2012
2168
  this.advance();
@@ -2047,7 +2203,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2047
2203
  let autoplay;
2048
2204
  let loop;
2049
2205
  while (!this.check("RBRACE") && !this.isAtEnd()) {
2050
- this.skipNewlines();
2206
+ this.skipBlockMemberSeparators();
2051
2207
  if (this.check("RBRACE")) break;
2052
2208
  if (this.check("IDENTIFIER") && (this.current().value === "autoplay" || this.current().value === "loop")) {
2053
2209
  const key = this.advance().value;
@@ -2086,7 +2242,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2086
2242
  this.skipNewlines();
2087
2243
  const properties = {};
2088
2244
  while (!this.check("RBRACE") && !this.isAtEnd()) {
2089
- this.skipNewlines();
2245
+ this.skipBlockMemberSeparators();
2090
2246
  if (this.check("RBRACE")) break;
2091
2247
  const key = this.expectIdentifier();
2092
2248
  this.expect("COLON");
@@ -2131,7 +2287,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2131
2287
  this.skipNewlines();
2132
2288
  const properties = [];
2133
2289
  while (!this.check("RBRACE") && !this.isAtEnd()) {
2134
- this.skipNewlines();
2290
+ this.skipBlockMemberSeparators();
2135
2291
  if (this.check("RBRACE")) break;
2136
2292
  if (this.check("AT")) {
2137
2293
  this.advance();
@@ -2170,7 +2326,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2170
2326
  const properties = [];
2171
2327
  const handlers = [];
2172
2328
  while (!this.check("RBRACE") && !this.isAtEnd()) {
2173
- this.skipNewlines();
2329
+ this.skipBlockMemberSeparators();
2174
2330
  if (this.check("RBRACE")) break;
2175
2331
  if (this.check("IDENTIFIER") && this.current().value.startsWith("on_")) {
2176
2332
  const event = this.advance().value;
@@ -2210,7 +2366,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2210
2366
  this.skipNewlines();
2211
2367
  const elements = [];
2212
2368
  while (!this.check("RBRACE") && !this.isAtEnd()) {
2213
- this.skipNewlines();
2369
+ this.skipBlockMemberSeparators();
2214
2370
  if (this.check("RBRACE")) break;
2215
2371
  if (this.check("ELEMENT")) {
2216
2372
  elements.push(this.parseUIElement());
@@ -2235,7 +2391,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2235
2391
  this.skipNewlines();
2236
2392
  const properties = [];
2237
2393
  while (!this.check("RBRACE") && !this.isAtEnd()) {
2238
- this.skipNewlines();
2394
+ this.skipBlockMemberSeparators();
2239
2395
  if (this.check("RBRACE")) break;
2240
2396
  const key = this.expectIdentifier();
2241
2397
  this.expect("COLON");
@@ -2262,7 +2418,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2262
2418
  this.skipNewlines();
2263
2419
  const properties = [];
2264
2420
  while (!this.check("RBRACE") && !this.isAtEnd()) {
2265
- this.skipNewlines();
2421
+ this.skipBlockMemberSeparators();
2266
2422
  if (this.check("RBRACE")) break;
2267
2423
  const key = this.expectIdentifier();
2268
2424
  this.expect("COLON");
@@ -2396,7 +2552,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2396
2552
  this.skipNewlines();
2397
2553
  const properties = [];
2398
2554
  while (!this.check("RBRACE") && !this.isAtEnd()) {
2399
- this.skipNewlines();
2555
+ this.skipBlockMemberSeparators();
2400
2556
  if (this.check("RBRACE")) break;
2401
2557
  const key = this.expectIdentifier();
2402
2558
  this.expect("COLON");
@@ -2431,11 +2587,11 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2431
2587
  // Initialize directives
2432
2588
  };
2433
2589
  while (!this.check("RBRACE") && !this.isAtEnd()) {
2434
- this.skipNewlines();
2590
+ this.skipBlockMemberSeparators();
2435
2591
  if (this.check("RBRACE")) break;
2436
- if (this.check("STATE")) {
2592
+ if (this.check("STATE") && this.peek(1).type !== "COLON") {
2437
2593
  template.state = this.parseState();
2438
- } else if (this.check("ACTION") || this.check("ASYNC")) {
2594
+ } else if (this.check("ACTION") && this.peek(1).type !== "COLON" || this.check("ASYNC")) {
2439
2595
  const action = this.parseAction();
2440
2596
  template.actions.push(action);
2441
2597
  template.directives.push({
@@ -2500,7 +2656,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2500
2656
  body: []
2501
2657
  });
2502
2658
  } else if (this.isPropertyName() && this.peek(1).type === "LPAREN") {
2503
- const methodName = this.expectIdentifier();
2659
+ const methodName = this.parsePropertyKey();
2504
2660
  this.skipParens();
2505
2661
  if (this.check("LBRACE")) {
2506
2662
  this.skipBlock();
@@ -2512,7 +2668,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2512
2668
  });
2513
2669
  }
2514
2670
  } else if (this.isPropertyName() && (this.peek(1).type === "IDENTIFIER" || this.peek(1).type === "STRING")) {
2515
- const blockType = this.expectIdentifier();
2671
+ const blockType = this.parsePropertyKey();
2516
2672
  const blockName = this.check("STRING") ? this.advance().value : this.expectIdentifier();
2517
2673
  if (this.check("LPAREN")) {
2518
2674
  this.skipParens();
@@ -2527,7 +2683,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2527
2683
  });
2528
2684
  }
2529
2685
  } else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
2530
- const blockType = this.expectIdentifier();
2686
+ const blockType = this.parsePropertyKey();
2531
2687
  if (this.check("LBRACE")) {
2532
2688
  this.skipBlock();
2533
2689
  template.directives.push({
@@ -2538,12 +2694,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2538
2694
  });
2539
2695
  }
2540
2696
  } else {
2541
- const key = this.expectIdentifier();
2697
+ const key = this.parsePropertyKey();
2542
2698
  this.expect("COLON");
2543
2699
  const value = this.parseValue();
2544
2700
  template.properties.push({ type: "TemplateProperty", key, value });
2545
2701
  }
2546
- this.skipNewlines();
2702
+ this.skipBlockMemberSeparators();
2547
2703
  }
2548
2704
  this.expect("RBRACE");
2549
2705
  template.loc = { start: startLoc, end: this.currentLocation() };
@@ -2563,8 +2719,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2563
2719
  let name = "";
2564
2720
  if (this.check("STRING")) {
2565
2721
  name = this.expectString();
2566
- } else if (this.check("IDENTIFIER")) {
2567
- name = this.expectIdentifier();
2722
+ } else if (this.isObjectNameToken()) {
2723
+ name = this.advance().value;
2568
2724
  } else if (typeOverride === "behavior" && this.check("LBRACE")) {
2569
2725
  name = "behavior";
2570
2726
  } else {
@@ -2598,14 +2754,14 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2598
2754
  const directives = [];
2599
2755
  let state;
2600
2756
  while (!this.check("RBRACE") && !this.check("EOF")) {
2601
- this.skipNewlines();
2757
+ this.skipBlockMemberSeparators();
2602
2758
  if (this.check("RBRACE")) break;
2603
- if (this.check("OBJECT") || this.check("SPATIAL_AGENT") || this.check("TOOL_SLOT") || this.check("BEHAVIOR") || this.current().type.startsWith("UI_")) {
2759
+ if (this.check("OBJECT") || this.check("SPATIAL_AGENT") || this.check("TOOL_SLOT") || this.check("BEHAVIOR") && this.peek(1).type !== "COLON" || this.current().type.startsWith("UI_")) {
2604
2760
  const nestedType = this.check("OBJECT") ? void 0 : this.current().value.toLowerCase();
2605
2761
  children.push(this.parseObject(nestedType));
2606
2762
  } else if (this.check("SUB_ORB")) {
2607
2763
  subOrbs.push(this.parseSubOrb());
2608
- } else if (this.check("ACTION") || this.check("ASYNC")) {
2764
+ } else if (this.check("ACTION") && this.peek(1).type !== "COLON" || this.check("ASYNC")) {
2609
2765
  const action = this.parseAction();
2610
2766
  directives.push({
2611
2767
  type: "method",
@@ -2656,7 +2812,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2656
2812
  config: config2,
2657
2813
  platformConstraint: constraint
2658
2814
  });
2659
- } else if (this.check("OBJECT") || this.check("SPATIAL_AGENT") || this.check("TOOL_SLOT") || this.check("BEHAVIOR") || this.current().type.startsWith("UI_")) {
2815
+ } else if (this.check("OBJECT") || this.check("SPATIAL_AGENT") || this.check("TOOL_SLOT") || this.check("BEHAVIOR") && this.peek(1).type !== "COLON" || this.current().type.startsWith("UI_")) {
2660
2816
  const nestedType = this.check("OBJECT") ? void 0 : this.current().value.toLowerCase();
2661
2817
  const child = this.parseObject(nestedType);
2662
2818
  child.platformConstraint = constraint;
@@ -2669,7 +2825,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2669
2825
  const trait = { type: "ObjectTrait", name: traitName, config };
2670
2826
  traits.push(trait);
2671
2827
  directives.push({ type: "trait", name: traitName, config });
2672
- } else if (this.check("STATE")) {
2828
+ } else if (this.check("STATE") && this.peek(1).type !== "COLON") {
2673
2829
  state = this.parseState();
2674
2830
  } else if (this.isDomainBlockToken() && this.peek(1).type !== "COLON") {
2675
2831
  const domainBlock = this.parseDomainBlock();
@@ -2681,7 +2837,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2681
2837
  const physicsValue = this.parseValue();
2682
2838
  properties.push({ type: "ObjectProperty", key, value: physicsValue });
2683
2839
  } else if (this.isPropertyName()) {
2684
- const key = this.advance().value;
2840
+ const key = this.parsePropertyKey();
2685
2841
  if (this.check("COLON")) {
2686
2842
  this.advance();
2687
2843
  if (this.check("LBRACE")) {
@@ -2715,7 +2871,11 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2715
2871
  if (this.check("LPAREN")) this.skipParens();
2716
2872
  let parsedBody = "";
2717
2873
  if (this.check("LBRACE")) {
2718
- parsedBody = this.parseBlockTraitConfig();
2874
+ if (key === "on" || key.startsWith("on_") || /^on[A-Z]/.test(key)) {
2875
+ this.skipBlock();
2876
+ } else {
2877
+ parsedBody = this.parseBlockTraitConfig();
2878
+ }
2719
2879
  }
2720
2880
  directives.push({ type: key, name: blockName, parameters: [], body: parsedBody });
2721
2881
  } else if (this.check("LBRACE")) {
@@ -2863,6 +3023,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2863
3023
  this.expect("LBRACE");
2864
3024
  this.skipNewlines();
2865
3025
  const objects = [];
3026
+ const lights = [];
2866
3027
  const groups = [];
2867
3028
  const body = [];
2868
3029
  while (!this.check("RBRACE") && !this.isAtEnd()) {
@@ -2870,6 +3031,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2870
3031
  if (this.check("RBRACE")) break;
2871
3032
  if (this.check("OBJECT")) {
2872
3033
  objects.push(this.parseObject());
3034
+ } else if (this.check("LIGHT")) {
3035
+ lights.push(this.parseLight());
2873
3036
  } else if (this.check("SPATIAL_GROUP")) {
2874
3037
  groups.push(this.parseSpatialGroup());
2875
3038
  } else if (this.check("TEMPLATE")) {
@@ -2922,6 +3085,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2922
3085
  name,
2923
3086
  properties,
2924
3087
  objects,
3088
+ lights: lights.length > 0 ? lights : void 0,
2925
3089
  groups: groups.length > 0 ? groups : void 0,
2926
3090
  body: body.length > 0 ? body : void 0
2927
3091
  };
@@ -2941,6 +3105,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
2941
3105
  if (this.check("RBRACE")) break;
2942
3106
  if (this.check("ACTION") || this.check("ASYNC")) {
2943
3107
  actions.push(this.parseAction());
3108
+ } else if (this.check("FUNCTION")) {
3109
+ this.skipFunctionDeclaration();
3110
+ } else if (this.check("IDENTIFIER") && this.current().value === "on" && (this.peek(1).type === "STRING" || this.peek(1).type === "IDENTIFIER")) {
3111
+ this.advance();
3112
+ const event = this.advance().value;
3113
+ const parameters = this.check("LPAREN") ? this.parseParameterList() : [];
3114
+ if (this.check("LBRACE")) {
3115
+ this.skipBlock();
3116
+ handlers.push({ type: "EventHandler", event, parameters, body: [] });
3117
+ } else {
3118
+ handlers.push({ type: "EventHandler", event, parameters, body: [] });
3119
+ }
2944
3120
  } else if (this.check("IDENTIFIER")) {
2945
3121
  const name = this.advance().value;
2946
3122
  if (this.check("IDENTIFIER")) {
@@ -3321,6 +3497,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3321
3497
  isKeywordAsIdentifier() {
3322
3498
  return isKeywordAsIdentifier(this._exprApi);
3323
3499
  }
3500
+ isObjectNameToken() {
3501
+ const type = this.current().type;
3502
+ if (type === "IDENTIFIER") return true;
3503
+ if (type === "OBJECT") return false;
3504
+ return this.isKeywordAsIdentifierType(type);
3505
+ }
3324
3506
  // ===========================================================================
3325
3507
  // VALUES
3326
3508
  // ===========================================================================
@@ -3348,14 +3530,22 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3348
3530
  return this.parseBindValue();
3349
3531
  }
3350
3532
  if (this.match("AT")) {
3351
- if (this.check("IDENTIFIER")) {
3352
- return `@${this.advance().value}`;
3353
- }
3533
+ const traitName = this.parseTraitName();
3534
+ if (traitName) return `@${traitName}`;
3354
3535
  this.error(`Expected trait name after '@', got ${this.current().type}`);
3355
3536
  return null;
3356
3537
  }
3357
- if (this.match("IDENTIFIER")) {
3358
- return this.previous().value;
3538
+ if (this.match("HASH")) {
3539
+ return this.parseHashLiteral();
3540
+ }
3541
+ if (this.check("ENUM")) {
3542
+ return this.parseEnumTypeSpec();
3543
+ }
3544
+ if (this.check("FUNCTION")) {
3545
+ return this.parseFunctionValue();
3546
+ }
3547
+ if (this.isBarewordPathToken()) {
3548
+ return this.parseBarewordPathValue();
3359
3549
  }
3360
3550
  if (this.match("LBRACKET")) {
3361
3551
  return this.parseArrayValue();
@@ -3363,13 +3553,148 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3363
3553
  if (this.match("LBRACE")) {
3364
3554
  return this.parseObjectValue();
3365
3555
  }
3366
- if (_HoloCompositionParser.DOMAIN_TOKENS.has(this.current().type) || this.isKeywordAsIdentifierType(this.current().type)) {
3367
- return this.advance().value;
3368
- }
3369
3556
  this.error(`Expected value, got ${this.current().type}`);
3370
3557
  this.advance();
3371
3558
  return null;
3372
3559
  }
3560
+ /**
3561
+ * Parse an `enum(...)` type-spec expression, e.g.:
3562
+ * enum("button" | "slider" | "checkbox")
3563
+ *
3564
+ * Returns the canonical string representation so trait loaders and schema
3565
+ * emitters can read it as a type annotation. Called from parseValue() when
3566
+ * the current token is ENUM (the keyword `enum` tokenized as 'ENUM' rather
3567
+ * than 'IDENTIFIER').
3568
+ *
3569
+ * The opening `enum` token is consumed here. The caller should check for a
3570
+ * trailing `= defaultValue` if the context supports it (e.g. parseObjectValue).
3571
+ */
3572
+ parseEnumTypeSpec() {
3573
+ this.advance();
3574
+ let spec = "enum";
3575
+ if (this.check("LPAREN")) {
3576
+ spec += this.parseParenthesizedLiteral();
3577
+ }
3578
+ return spec;
3579
+ }
3580
+ parseFunctionValue() {
3581
+ this.expect("FUNCTION");
3582
+ let name = "";
3583
+ if (this.check("STRING") || this.check("IDENTIFIER")) {
3584
+ name = this.advance().value;
3585
+ }
3586
+ const params = this.check("LPAREN") ? this.collectFunctionParameterNames() : [];
3587
+ if (this.check("LBRACE")) {
3588
+ this.skipBlock();
3589
+ }
3590
+ return {
3591
+ type: "FunctionValue",
3592
+ name,
3593
+ params
3594
+ };
3595
+ }
3596
+ skipFunctionDeclaration() {
3597
+ this.expect("FUNCTION");
3598
+ if (this.check("STRING") || this.check("IDENTIFIER")) {
3599
+ this.advance();
3600
+ }
3601
+ if (this.check("LPAREN")) {
3602
+ this.skipParens();
3603
+ }
3604
+ if (this.check("LBRACE")) {
3605
+ this.skipBlock();
3606
+ }
3607
+ }
3608
+ collectFunctionParameterNames() {
3609
+ const params = [];
3610
+ if (!this.check("LPAREN")) return params;
3611
+ this.advance();
3612
+ let parenDepth = 1;
3613
+ while (parenDepth > 0 && !this.isAtEnd()) {
3614
+ if (this.check("LPAREN")) {
3615
+ parenDepth++;
3616
+ this.advance();
3617
+ continue;
3618
+ }
3619
+ if (this.check("RPAREN")) {
3620
+ parenDepth--;
3621
+ this.advance();
3622
+ continue;
3623
+ }
3624
+ if (parenDepth === 1 && this.check("IDENTIFIER")) {
3625
+ params.push(this.advance().value);
3626
+ continue;
3627
+ }
3628
+ this.advance();
3629
+ }
3630
+ return params;
3631
+ }
3632
+ isBarewordPathToken(token = this.current()) {
3633
+ const type = token.type;
3634
+ return type === "IDENTIFIER" || type === "STATE" || _HoloCompositionParser.DOMAIN_TOKENS.has(type) || this.isKeywordAsIdentifierType(type);
3635
+ }
3636
+ parseBarewordPathValue() {
3637
+ let value = this.advance().value;
3638
+ while (this.match("DOT")) {
3639
+ if (!this.isBarewordPathToken()) {
3640
+ this.error(`Expected identifier after '.', got ${this.current().type}`);
3641
+ break;
3642
+ }
3643
+ value += `.${this.advance().value}`;
3644
+ }
3645
+ while (this.check("COLON") && this.isBarewordPathToken(this.peek(1))) {
3646
+ this.advance();
3647
+ value += `:${this.advance().value}`;
3648
+ }
3649
+ if (this.match("LESS")) {
3650
+ value += "<";
3651
+ let depth = 1;
3652
+ while (depth > 0 && !this.isAtEnd()) {
3653
+ if (this.check("LESS")) {
3654
+ depth++;
3655
+ value += this.advance().value;
3656
+ continue;
3657
+ }
3658
+ if (this.check("GREATER")) {
3659
+ depth--;
3660
+ this.advance();
3661
+ value += ">";
3662
+ if (depth === 0) break;
3663
+ continue;
3664
+ }
3665
+ value += this.advance().value;
3666
+ }
3667
+ }
3668
+ if (this.check("LPAREN")) {
3669
+ value += this.parseParenthesizedLiteral();
3670
+ }
3671
+ return value;
3672
+ }
3673
+ parseHashLiteral() {
3674
+ let value = "#";
3675
+ while (!this.isAtEnd()) {
3676
+ if (this.check("IDENTIFIER") || this.check("NUMBER") || this.check("MINUS") || this.check("DOT")) {
3677
+ value += this.advance().value;
3678
+ continue;
3679
+ }
3680
+ break;
3681
+ }
3682
+ return value;
3683
+ }
3684
+ parseParenthesizedLiteral() {
3685
+ let value = "";
3686
+ if (!this.check("LPAREN")) return value;
3687
+ let depth = 0;
3688
+ while (!this.isAtEnd()) {
3689
+ const token = this.current();
3690
+ if (token.type === "LPAREN") depth++;
3691
+ if (token.type === "RPAREN") depth--;
3692
+ value += token.type === "STRING" ? `"${token.value}"` : token.value;
3693
+ this.advance();
3694
+ if (depth === 0) break;
3695
+ }
3696
+ return value;
3697
+ }
3373
3698
  parseBindValue() {
3374
3699
  this.expect("BIND");
3375
3700
  this.expect("LPAREN");
@@ -3395,9 +3720,10 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3395
3720
  const elements = [];
3396
3721
  while (!this.check("RBRACKET") && !this.isAtEnd()) {
3397
3722
  this.skipNewlines();
3723
+ if (this.check("RBRACKET")) break;
3398
3724
  elements.push(this.parseValue());
3399
3725
  this.skipNewlines();
3400
- if (!this.match("COMMA")) break;
3726
+ this.match("COMMA");
3401
3727
  this.skipNewlines();
3402
3728
  }
3403
3729
  this.skipNewlines();
@@ -3408,13 +3734,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3408
3734
  this.skipNewlines();
3409
3735
  const obj = {};
3410
3736
  while (!this.check("RBRACE") && !this.isAtEnd()) {
3411
- this.skipNewlines();
3737
+ this.skipBlockMemberSeparators();
3412
3738
  if (this.check("RBRACE")) break;
3413
- this.match("COMMA");
3414
- if (this.isPropertyName() && this.peek(1).type === "COLON") {
3415
- const key = this.expectIdentifier();
3739
+ if (this.isPropertyAssignmentStart()) {
3740
+ const key = this.parsePropertyKey();
3416
3741
  this.expect("COLON");
3417
3742
  obj[key] = this.parseValue();
3743
+ if (this.match("EQUALS")) {
3744
+ this.parseValue();
3745
+ }
3418
3746
  } else if (this.check("RBRACE")) {
3419
3747
  break;
3420
3748
  } else {
@@ -3497,7 +3825,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3497
3825
  this.skipNewlines();
3498
3826
  const properties = [];
3499
3827
  while (!this.check("RBRACE") && !this.isAtEnd()) {
3500
- this.skipNewlines();
3828
+ this.skipBlockMemberSeparators();
3501
3829
  if (this.check("RBRACE")) break;
3502
3830
  const key = this.expectIdentifier();
3503
3831
  this.expect("COLON");
@@ -3538,6 +3866,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3538
3866
  "QUEST",
3539
3867
  "ABILITY",
3540
3868
  "DIALOGUE",
3869
+ "BEHAVIOR",
3541
3870
  "SHAPE",
3542
3871
  "IMPORT",
3543
3872
  "USING",
@@ -3556,10 +3885,42 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3556
3885
  "WAYPOINTS",
3557
3886
  "CONSTRAINT",
3558
3887
  "TERRAIN",
3559
- "PARTICLES"
3888
+ "PARTICLES",
3889
+ "METADATA_BLOCK",
3890
+ "HOLO_TOPIC",
3891
+ "HOLO_CHANNEL",
3892
+ "CONNECT",
3893
+ "BIND"
3560
3894
  ];
3561
3895
  return validPropertyKeywords.includes(type);
3562
3896
  }
3897
+ isPropertyNameToken(token) {
3898
+ return token.type === "IDENTIFIER" || _HoloCompositionParser.DOMAIN_TOKENS.has(token.type) || this.isKeywordAsIdentifierType(token.type);
3899
+ }
3900
+ isPropertyAssignmentStart() {
3901
+ if (!this.isPropertyName()) return false;
3902
+ let index = this.pos + 1;
3903
+ if (this.tokens[index]?.type === "QUESTION") index++;
3904
+ while (this.tokens[index]?.type === "DOT" && this.isPropertyNameToken(this.tokens[index + 1])) {
3905
+ index += 2;
3906
+ if (this.tokens[index]?.type === "QUESTION") index++;
3907
+ }
3908
+ return this.tokens[index]?.type === "COLON";
3909
+ }
3910
+ parsePropertyKey() {
3911
+ const parts = [];
3912
+ parts.push(this.isPropertyName() ? this.advance().value : this.expectIdentifier());
3913
+ while (this.match("DOT")) {
3914
+ if (!this.isPropertyName()) {
3915
+ this.error(`Expected identifier after '.', got ${this.current().type}`);
3916
+ break;
3917
+ }
3918
+ parts.push(this.advance().value);
3919
+ }
3920
+ let key = parts.join(".");
3921
+ if (this.match("QUESTION")) key += "?";
3922
+ return key;
3923
+ }
3563
3924
  /**
3564
3925
  * Parse primitive#id or primitive #id { } syntax
3565
3926
  * Examples:
@@ -3597,15 +3958,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3597
3958
  this.expect("LBRACE");
3598
3959
  this.skipNewlines();
3599
3960
  while (!this.check("RBRACE") && !this.isAtEnd()) {
3600
- this.skipNewlines();
3961
+ this.skipBlockMemberSeparators();
3601
3962
  if (this.check("RBRACE")) break;
3602
3963
  if (this.check("AT")) {
3603
3964
  this.advance();
3604
3965
  const name = this.parseTraitName();
3605
3966
  const config = this.parseOptionalTraitConfig();
3606
3967
  traits.push({ type: "ObjectTrait", name, config });
3607
- } else if (this.check("IDENTIFIER")) {
3608
- const key = this.expectIdentifier();
3968
+ } else if (this.isPropertyName()) {
3969
+ const key = this.parsePropertyKey();
3609
3970
  if (this.check("COLON")) {
3610
3971
  this.advance();
3611
3972
  properties.push({ type: "ObjectProperty", key, value: this.parseValue() });
@@ -3741,6 +4102,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3741
4102
  while (this.match("NEWLINE")) {
3742
4103
  }
3743
4104
  }
4105
+ skipBlockMemberSeparators() {
4106
+ this.skipNewlines();
4107
+ while (this.matchBlockMemberSeparator()) {
4108
+ this.skipNewlines();
4109
+ }
4110
+ }
4111
+ matchBlockMemberSeparator() {
4112
+ return this.match("COMMA") || this.match("SEMICOLON");
4113
+ }
3744
4114
  currentLocation() {
3745
4115
  const token = this.current();
3746
4116
  return { line: token.line, column: token.column };
@@ -3828,16 +4198,14 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3828
4198
  while (!this.check("RPAREN") && !this.check("EOF")) {
3829
4199
  this.skipNewlines();
3830
4200
  if (this.check("RPAREN")) break;
3831
- if (!this.isPropertyName() || this.peek(1).type !== "COLON") {
4201
+ if (!this.isPropertyAssignmentStart()) {
3832
4202
  config[`_arg${argIndex++}`] = this.parseValue();
3833
4203
  } else {
3834
- const key = this.expectIdentifier();
4204
+ const key = this.parsePropertyKey();
3835
4205
  this.expect("COLON");
3836
4206
  config[key] = this.parseValue();
3837
4207
  }
3838
- if (this.check("COMMA")) {
3839
- this.advance();
3840
- }
4208
+ this.matchBlockMemberSeparator();
3841
4209
  this.skipNewlines();
3842
4210
  }
3843
4211
  this.expect("RPAREN");
@@ -3848,19 +4216,128 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3848
4216
  this.skipNewlines();
3849
4217
  const config = {};
3850
4218
  while (!this.check("RBRACE") && !this.isAtEnd()) {
3851
- this.skipNewlines();
4219
+ this.skipBlockMemberSeparators();
3852
4220
  if (this.check("RBRACE")) break;
3853
- const key = this.expectIdentifier();
3854
- this.expect("COLON");
3855
- config[key] = this.parseValue();
3856
- if (this.check("COMMA")) {
4221
+ if (this.isNamedOrTraitedPropertyBlockStart()) {
4222
+ const { key, value } = this.parseNamedOrTraitedPropertyBlock();
4223
+ config[key] = value;
4224
+ } else if (this.check("AT")) {
3857
4225
  this.advance();
4226
+ const traitName = this.parseTraitName();
4227
+ if (traitName) {
4228
+ config[`@${traitName}`] = this.parseOptionalTraitConfig();
4229
+ }
4230
+ } else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
4231
+ const nestedKey = this.parsePropertyKey();
4232
+ config[nestedKey] = this.parseBlockTraitConfig();
4233
+ } else {
4234
+ const key = this.parsePropertyKey();
4235
+ this.expect("COLON");
4236
+ config[key] = this.parseInlineExpressionTail(this.parseValue());
3858
4237
  }
4238
+ this.matchBlockMemberSeparator();
3859
4239
  this.skipNewlines();
3860
4240
  }
3861
4241
  this.expect("RBRACE");
3862
4242
  return config;
3863
4243
  }
4244
+ parseInlineExpressionTail(value) {
4245
+ if (value === null || typeof value === "object" && !Array.isArray(value) || !this.isInlineExpressionTailStart()) {
4246
+ return value;
4247
+ }
4248
+ let text = String(value);
4249
+ while (!this.check(["NEWLINE", "COMMA", "SEMICOLON", "RBRACE", "RPAREN", "RBRACKET", "EOF"])) {
4250
+ const token = this.current();
4251
+ const raw = token.type === "STRING" ? `"${token.value}"` : token.value;
4252
+ text += ` ${raw}`;
4253
+ this.advance();
4254
+ }
4255
+ return text;
4256
+ }
4257
+ isInlineExpressionTailStart() {
4258
+ return this.check([
4259
+ "EQUALS_EQUALS",
4260
+ "BANG_EQUALS",
4261
+ "LESS",
4262
+ "LESS_EQUALS",
4263
+ "GREATER",
4264
+ "GREATER_EQUALS",
4265
+ "AND",
4266
+ "OR",
4267
+ "PLUS",
4268
+ "MINUS",
4269
+ "STAR",
4270
+ "SLASH"
4271
+ ]);
4272
+ }
4273
+ isNamedOrTraitedPropertyBlockStart() {
4274
+ if (!this.isPropertyName()) return false;
4275
+ let index = this.pos + 1;
4276
+ const hasName = this.tokens[index]?.type === "STRING" || this.tokens[index]?.type === "IDENTIFIER";
4277
+ if (hasName) {
4278
+ index++;
4279
+ }
4280
+ while (this.tokens[index]?.type === "NEWLINE") index++;
4281
+ let hasTrait = false;
4282
+ while (this.tokens[index]?.type === "AT") {
4283
+ hasTrait = true;
4284
+ index++;
4285
+ if (this.tokens[index]?.type === "EOF") return false;
4286
+ index++;
4287
+ if (this.tokens[index]?.type === "LPAREN") {
4288
+ index = this.indexAfterBalancedTokens(index, "LPAREN", "RPAREN");
4289
+ }
4290
+ while (this.tokens[index]?.type === "NEWLINE") index++;
4291
+ }
4292
+ return (hasName || hasTrait) && this.tokens[index]?.type === "LBRACE";
4293
+ }
4294
+ indexAfterBalancedTokens(startIndex, openType, closeType) {
4295
+ let depth = 0;
4296
+ let index = startIndex;
4297
+ while (index < this.tokens.length) {
4298
+ if (this.tokens[index].type === openType) depth++;
4299
+ if (this.tokens[index].type === closeType) {
4300
+ depth--;
4301
+ index++;
4302
+ if (depth === 0) return index;
4303
+ continue;
4304
+ }
4305
+ index++;
4306
+ }
4307
+ return index;
4308
+ }
4309
+ parseNamedOrTraitedPropertyBlock() {
4310
+ const key = this.parsePropertyKey();
4311
+ const name = this.check("STRING") || this.check("IDENTIFIER") ? this.advance().value : void 0;
4312
+ const traits = this.parseInlineTraitNamesBeforeBlock();
4313
+ const body = this.check("LBRACE") ? this.parseBlockTraitConfig() : {};
4314
+ return {
4315
+ key,
4316
+ value: {
4317
+ ...name !== void 0 ? { name } : {},
4318
+ ...traits.length > 0 ? { traits } : {},
4319
+ ...body
4320
+ }
4321
+ };
4322
+ }
4323
+ parseInlineTraitNamesBeforeBlock() {
4324
+ const traits = [];
4325
+ while (this.check("AT")) {
4326
+ this.advance();
4327
+ const traitName = this.parseTraitName();
4328
+ if (traitName) traits.push(traitName);
4329
+ if (this.check("LPAREN")) {
4330
+ this.skipParens();
4331
+ }
4332
+ this.skipNewlines();
4333
+ }
4334
+ return traits;
4335
+ }
4336
+ parseSharePlayBlock() {
4337
+ this.advance();
4338
+ if (!this.check("LBRACE")) return {};
4339
+ return this.parseBlockTraitConfig();
4340
+ }
3864
4341
  // ===========================================================================
3865
4342
  // PLATFORM CONSTRAINT PARSING
3866
4343
  // ===========================================================================
@@ -3976,7 +4453,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3976
4453
  type: "NPC",
3977
4454
  name,
3978
4455
  properties: [],
3979
- behaviors: []
4456
+ behaviors: [],
4457
+ traits: [],
4458
+ directives: []
3980
4459
  };
3981
4460
  while (!this.check("RBRACE") && !this.isAtEnd()) {
3982
4461
  this.skipNewlines();
@@ -3985,29 +4464,86 @@ var _HoloCompositionParser = class _HoloCompositionParser {
3985
4464
  npc.behaviors.push(this.parseBehavior());
3986
4465
  } else if (this.check("STATE")) {
3987
4466
  npc.state = this.parseState();
3988
- } else {
3989
- const key = this.expectIdentifier();
3990
- this.expect("COLON");
3991
- const value = this.parseValue();
3992
- if (key === "type") npc.npcType = value;
3993
- else if (key === "model") npc.model = value;
3994
- else if (key === "dialogue_tree") npc.dialogueTree = value;
3995
- else npc.properties.push({ type: "NPCProperty", key, value });
3996
- }
3997
- this.skipNewlines();
3998
- }
3999
- this.expect("RBRACE");
4000
- this.popContext();
4001
- return npc;
4002
- }
4003
- parseBehavior() {
4004
- this.expect("BEHAVIOR");
4005
- const name = this.expectString();
4006
- this.expect("LBRACE");
4007
- this.skipNewlines();
4008
- const behavior = {
4009
- type: "Behavior",
4010
- name,
4467
+ } else if (this.check("ACTION") || this.check("ASYNC")) {
4468
+ const action = this.parseAction();
4469
+ (npc.directives ?? (npc.directives = [])).push({
4470
+ type: "method",
4471
+ name: action.name,
4472
+ parameters: action.parameters || [],
4473
+ body: action.body,
4474
+ async: action.async
4475
+ });
4476
+ } else if (this.check("IDENTIFIER") && this.current().value === "on" && this.peek(1).type === "IDENTIFIER") {
4477
+ const eventName = this.peek(1).value;
4478
+ this.advance();
4479
+ this.advance();
4480
+ while (this.check("DOT")) {
4481
+ this.advance();
4482
+ if (this.check("IDENTIFIER")) this.advance();
4483
+ }
4484
+ let parameters = [];
4485
+ if (this.check("LPAREN")) {
4486
+ parameters = this.parseParameterList();
4487
+ }
4488
+ this.skipBlock();
4489
+ (npc.directives ?? (npc.directives = [])).push({
4490
+ type: "lifecycle",
4491
+ hook: eventName,
4492
+ parameters,
4493
+ body: []
4494
+ });
4495
+ } else if (this.check("AT")) {
4496
+ this.advance();
4497
+ const traitName = this.parseTraitName();
4498
+ const config = this.parseOptionalTraitConfig(true);
4499
+ (npc.traits ?? (npc.traits = [])).push({ type: "ObjectTrait", name: traitName, config });
4500
+ } else {
4501
+ const key = this.expectIdentifier();
4502
+ this.expect("COLON");
4503
+ const value = this.parseValue();
4504
+ if (key === "type") npc.npcType = value;
4505
+ else if (key === "model") npc.model = value;
4506
+ else if (key === "dialogue_tree") npc.dialogueTree = value;
4507
+ else if (key === "position") {
4508
+ if (Array.isArray(value) && value.length >= 3) {
4509
+ npc.position = { x: value[0], y: value[1], z: value[2] };
4510
+ } else if (value && typeof value === "object" && "x" in value) {
4511
+ const v = value;
4512
+ npc.position = { x: v.x, y: v.y, z: v.z };
4513
+ }
4514
+ } else if (key === "brain_ref") {
4515
+ npc.brain = {
4516
+ ...npc.brain ?? { type: "AgentBrainAttachment", brainType: "llm" },
4517
+ type: "AgentBrainAttachment",
4518
+ brainType: npc.brain?.brainType ?? "llm",
4519
+ brainRef: value
4520
+ };
4521
+ } else if (key === "brain") {
4522
+ const cfg = value && typeof value === "object" ? value : {};
4523
+ npc.brain = {
4524
+ type: "AgentBrainAttachment",
4525
+ brainType: cfg.type ?? "llm",
4526
+ autonomy: cfg.autonomy,
4527
+ brainRef: typeof cfg.ref === "string" ? cfg.ref : typeof cfg.brainRef === "string" ? cfg.brainRef : void 0,
4528
+ toolPermissions: Array.isArray(cfg.tools) ? cfg.tools.map(String) : void 0,
4529
+ model: cfg.model && typeof cfg.model === "object" ? cfg.model : void 0
4530
+ };
4531
+ } else npc.properties.push({ type: "NPCProperty", key, value });
4532
+ }
4533
+ this.skipNewlines();
4534
+ }
4535
+ this.expect("RBRACE");
4536
+ this.popContext();
4537
+ return npc;
4538
+ }
4539
+ parseBehavior() {
4540
+ this.expect("BEHAVIOR");
4541
+ const name = this.expectString();
4542
+ this.expect("LBRACE");
4543
+ this.skipNewlines();
4544
+ const behavior = {
4545
+ type: "Behavior",
4546
+ name,
4011
4547
  trigger: "idle",
4012
4548
  actions: []
4013
4549
  };
@@ -4349,7 +4885,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4349
4885
  options: []
4350
4886
  };
4351
4887
  while (!this.check("RBRACE") && !this.isAtEnd()) {
4352
- this.skipNewlines();
4888
+ this.skipBlockMemberSeparators();
4353
4889
  if (this.check("RBRACE")) break;
4354
4890
  const key = this.expectIdentifier();
4355
4891
  this.expect("COLON");
@@ -4379,7 +4915,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4379
4915
  text: ""
4380
4916
  };
4381
4917
  while (!this.check("RBRACE") && !this.isAtEnd()) {
4382
- this.skipNewlines();
4918
+ this.skipBlockMemberSeparators();
4383
4919
  if (this.check("RBRACE")) break;
4384
4920
  const key = this.expectIdentifier();
4385
4921
  this.expect("COLON");
@@ -4402,9 +4938,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4402
4938
  // BRITTNEY AI FEATURES - STATE MACHINES
4403
4939
  // ===========================================================================
4404
4940
  parseStateMachine() {
4405
- this.currentLocation();
4941
+ const startLoc = this.currentLocation();
4406
4942
  this.expect("STATE_MACHINE");
4407
- const name = this.expectString();
4943
+ const name = this.parseOptionalStateMachineName("");
4944
+ if (!name) {
4945
+ this.error("Expected state_machine name");
4946
+ }
4408
4947
  this.pushContext(`StateMachine "${name}"`);
4409
4948
  this.expect("LBRACE");
4410
4949
  this.skipNewlines();
@@ -4412,11 +4951,19 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4412
4951
  type: "StateMachine",
4413
4952
  name,
4414
4953
  initialState: "",
4415
- states: {}
4954
+ inputs: [],
4955
+ listeners: [],
4956
+ states: {},
4957
+ transitions: []
4416
4958
  };
4417
4959
  while (!this.check("RBRACE") && !this.isAtEnd()) {
4418
4960
  this.skipNewlines();
4419
4961
  if (this.check("RBRACE")) break;
4962
+ if (this.isAnimationTransitionShorthandStart()) {
4963
+ sm.transitions.push(this.parseAnimationTransitionShorthand());
4964
+ this.skipNewlines();
4965
+ continue;
4966
+ }
4420
4967
  if (this.check("STATE")) {
4421
4968
  this.advance();
4422
4969
  const stateName = this.check("STRING") || this.check("IDENTIFIER") ? this.advance().value : "anonymous";
@@ -4433,6 +4980,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4433
4980
  while (!this.check("RBRACE") && !this.isAtEnd()) {
4434
4981
  this.skipNewlines();
4435
4982
  if (this.check("RBRACE")) break;
4983
+ if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
4984
+ if (this.check("LPAREN")) this.skipParens();
4985
+ else if (this.check("LBRACE")) this.skipBlock();
4986
+ else this.advance();
4987
+ continue;
4988
+ }
4436
4989
  const key2 = this.expectIdentifier();
4437
4990
  if (this.check("COLON")) {
4438
4991
  this.advance();
@@ -4448,7 +5001,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4448
5001
  this.expect("RBRACE");
4449
5002
  } else if (key2 === "actions") {
4450
5003
  state.actions = this.parseBehaviorActions();
4451
- } else if (key2 === "transitions") {
5004
+ } else if (this.parseAnimationStateMetadata(state, key2)) ; else if (key2 === "transitions") {
4452
5005
  state.transitions = this.parseStateTransitions();
4453
5006
  } else if (key2 === "onDamage") {
4454
5007
  state.onDamage = this.parseStatementBlock();
@@ -4457,7 +5010,11 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4457
5010
  } else if (key2 === "onTimeout") {
4458
5011
  state.onTimeout = this.parseStatementBlock();
4459
5012
  } else {
4460
- this.parseValue();
5013
+ if (!this.check("RBRACE") && !this.isAtEnd()) {
5014
+ this.parseValue();
5015
+ if (this.check("LPAREN")) this.skipParens();
5016
+ if (this.check("LBRACE")) this.skipBlock();
5017
+ }
4461
5018
  }
4462
5019
  } else if (this.check("LBRACE")) {
4463
5020
  if (key2 === "enter" || key2 === "entry") {
@@ -4473,6 +5030,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4473
5030
  } else {
4474
5031
  this.skipBlock();
4475
5032
  }
5033
+ } else if (this.check("LPAREN")) {
5034
+ this.skipParens();
5035
+ if (this.check("LBRACE")) this.skipBlock();
4476
5036
  }
4477
5037
  this.skipNewlines();
4478
5038
  }
@@ -4482,18 +5042,37 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4482
5042
  this.skipNewlines();
4483
5043
  continue;
4484
5044
  }
5045
+ if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
5046
+ if (this.check("LPAREN")) this.skipParens();
5047
+ else if (this.check("LBRACE")) this.skipBlock();
5048
+ else this.advance();
5049
+ this.skipNewlines();
5050
+ continue;
5051
+ }
4485
5052
  const key = this.expectIdentifier();
4486
5053
  if (key === "initial" || key === "initialState") {
4487
5054
  this.expect("COLON");
4488
5055
  sm.initialState = this.parseValue();
5056
+ } else if (key === "input") {
5057
+ sm.inputs.push(this.parseAnimationInputDeclaration(startLoc));
5058
+ } else if (key === "listen") {
5059
+ sm.listeners.push(this.parseAnimationListenerDeclaration(startLoc));
4489
5060
  } else if (key === "states" && this.check("COLON")) {
4490
5061
  this.advance();
4491
5062
  sm.states = this.parseStateMachineStates();
5063
+ } else if (key === "transitions" && this.check("COLON")) {
5064
+ this.advance();
5065
+ sm.transitions = this.parseStateTransitions();
4492
5066
  } else if (this.check("COLON")) {
4493
5067
  this.advance();
4494
5068
  this.parseValue();
5069
+ if (this.check("LPAREN")) this.skipParens();
5070
+ if (this.check("LBRACE")) this.skipBlock();
4495
5071
  } else if (this.check("LBRACE")) {
4496
5072
  this.skipBlock();
5073
+ } else if (this.check("LPAREN")) {
5074
+ this.skipParens();
5075
+ if (this.check("LBRACE")) this.skipBlock();
4497
5076
  }
4498
5077
  this.skipNewlines();
4499
5078
  }
@@ -4514,19 +5093,27 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4514
5093
  * Without this, @state_machine blocks were stored as opaque traits and
4515
5094
  * invisible to compile_to_a2a_agent_card and other compilers.
4516
5095
  */
4517
- parseStateMachineFromDecorator() {
5096
+ parseStateMachineFromDecorator(name = "implicit") {
4518
5097
  const startLoc = this.currentLocation();
4519
5098
  this.expect("LBRACE");
4520
5099
  this.skipNewlines();
4521
5100
  const sm = {
4522
5101
  type: "StateMachine",
4523
- name: "implicit",
5102
+ name,
4524
5103
  initialState: "",
4525
- states: {}
5104
+ inputs: [],
5105
+ listeners: [],
5106
+ states: {},
5107
+ transitions: []
4526
5108
  };
4527
5109
  while (!this.check("RBRACE") && !this.isAtEnd()) {
4528
5110
  this.skipNewlines();
4529
5111
  if (this.check("RBRACE")) break;
5112
+ if (this.isAnimationTransitionShorthandStart()) {
5113
+ sm.transitions.push(this.parseAnimationTransitionShorthand());
5114
+ this.skipNewlines();
5115
+ continue;
5116
+ }
4530
5117
  if (this.check("STATE")) {
4531
5118
  this.advance();
4532
5119
  const stateName = this.check("STRING") || this.check("IDENTIFIER") ? this.advance().value : "anonymous";
@@ -4543,6 +5130,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4543
5130
  while (!this.check("RBRACE") && !this.isAtEnd()) {
4544
5131
  this.skipNewlines();
4545
5132
  if (this.check("RBRACE")) break;
5133
+ if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
5134
+ if (this.check("LPAREN")) this.skipParens();
5135
+ else if (this.check("LBRACE")) this.skipBlock();
5136
+ else this.advance();
5137
+ continue;
5138
+ }
4546
5139
  const key2 = this.expectIdentifier();
4547
5140
  if (this.check("COLON")) {
4548
5141
  this.advance();
@@ -4558,12 +5151,16 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4558
5151
  this.expect("RBRACE");
4559
5152
  } else if (key2 === "actions") {
4560
5153
  state.actions = this.parseBehaviorActions();
4561
- } else if (key2 === "transitions") {
5154
+ } else if (this.parseAnimationStateMetadata(state, key2)) ; else if (key2 === "transitions") {
4562
5155
  state.transitions = this.parseStateTransitions();
4563
5156
  } else if (key2 === "timeout") {
4564
5157
  state.timeout = this.parseValue();
4565
5158
  } else {
4566
- this.parseValue();
5159
+ if (!this.check("RBRACE") && !this.isAtEnd()) {
5160
+ this.parseValue();
5161
+ if (this.check("LPAREN")) this.skipParens();
5162
+ if (this.check("LBRACE")) this.skipBlock();
5163
+ }
4567
5164
  }
4568
5165
  } else if (this.check("LBRACE")) {
4569
5166
  if (key2 === "enter" || key2 === "entry" || key2 === "on_entry") {
@@ -4581,6 +5178,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4581
5178
  } else {
4582
5179
  this.skipBlock();
4583
5180
  }
5181
+ } else if (this.check("LPAREN")) {
5182
+ this.skipParens();
5183
+ if (this.check("LBRACE")) this.skipBlock();
4584
5184
  }
4585
5185
  this.skipNewlines();
4586
5186
  }
@@ -4590,21 +5190,40 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4590
5190
  this.skipNewlines();
4591
5191
  continue;
4592
5192
  }
5193
+ if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
5194
+ if (this.check("LPAREN")) this.skipParens();
5195
+ else if (this.check("LBRACE")) this.skipBlock();
5196
+ else this.advance();
5197
+ this.skipNewlines();
5198
+ continue;
5199
+ }
4593
5200
  const key = this.expectIdentifier();
4594
5201
  if (key === "initial" || key === "initialState") {
4595
5202
  this.expect("COLON");
4596
5203
  sm.initialState = this.parseValue();
5204
+ } else if (key === "input") {
5205
+ sm.inputs.push(this.parseAnimationInputDeclaration(startLoc));
5206
+ } else if (key === "listen") {
5207
+ sm.listeners.push(this.parseAnimationListenerDeclaration(startLoc));
4597
5208
  } else if (key === "name") {
4598
5209
  this.expect("COLON");
4599
5210
  sm.name = this.parseValue();
4600
5211
  } else if (key === "states" && this.check("COLON")) {
4601
5212
  this.advance();
4602
5213
  sm.states = this.parseStateMachineStates();
5214
+ } else if (key === "transitions" && this.check("COLON")) {
5215
+ this.advance();
5216
+ sm.transitions = this.parseStateTransitions();
4603
5217
  } else if (this.check("COLON")) {
4604
5218
  this.advance();
4605
5219
  this.parseValue();
5220
+ if (this.check("LPAREN")) this.skipParens();
5221
+ if (this.check("LBRACE")) this.skipBlock();
4606
5222
  } else if (this.check("LBRACE")) {
4607
5223
  this.skipBlock();
5224
+ } else if (this.check("LPAREN")) {
5225
+ this.skipParens();
5226
+ if (this.check("LBRACE")) this.skipBlock();
4608
5227
  }
4609
5228
  this.skipNewlines();
4610
5229
  }
@@ -4637,7 +5256,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4637
5256
  if (key === "entry") state.entry = this.parseStatementBlock();
4638
5257
  else if (key === "exit") state.exit = this.parseStatementBlock();
4639
5258
  else if (key === "actions") state.actions = this.parseBehaviorActions();
4640
- else if (key === "onDamage") state.onDamage = this.parseStatementBlock();
5259
+ else if (this.parseAnimationStateMetadata(state, key)) ; else if (key === "onDamage") state.onDamage = this.parseStatementBlock();
4641
5260
  else if (key === "timeout") state.timeout = this.parseValue();
4642
5261
  else if (key === "onTimeout") state.onTimeout = this.parseStatementBlock();
4643
5262
  else if (key === "transitions") state.transitions = this.parseStateTransitions();
@@ -4651,13 +5270,385 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4651
5270
  this.expect("RBRACE");
4652
5271
  return states;
4653
5272
  }
5273
+ parseOptionalStateMachineName(defaultName) {
5274
+ if (this.check("STRING") || this.check("IDENTIFIER") || this.isKeywordAsIdentifier()) {
5275
+ return this.advance().value;
5276
+ }
5277
+ return defaultName;
5278
+ }
5279
+ parseAnimationStateMetadata(state, key) {
5280
+ if (key === "clip") {
5281
+ state.clip = String(this.parseValue() ?? "");
5282
+ return true;
5283
+ }
5284
+ if (key === "clips") {
5285
+ state.clips = this.coerceStringArray(this.parseValue());
5286
+ return true;
5287
+ }
5288
+ if (key === "parameter") {
5289
+ state.parameter = String(this.parseValue() ?? "");
5290
+ return true;
5291
+ }
5292
+ if (key === "parameters") {
5293
+ state.parameters = this.coerceStringArray(this.parseValue());
5294
+ return true;
5295
+ }
5296
+ if (key === "thresholds") {
5297
+ state.thresholds = this.coerceNumberArray(this.parseValue());
5298
+ return true;
5299
+ }
5300
+ if (key === "blendType" || key === "blend_type" || key === "blend") {
5301
+ const blendType = String(this.parseValue() ?? "").toLowerCase();
5302
+ if (blendType === "1d" || blendType === "direct") {
5303
+ state.blendType = blendType;
5304
+ } else {
5305
+ this.error(`Unknown animation blend type "${blendType}"`);
5306
+ }
5307
+ return true;
5308
+ }
5309
+ if (key === "blendMode" || key === "blend_mode") {
5310
+ const blendMode = String(this.parseValue() ?? "").toLowerCase();
5311
+ if (blendMode === "override" || blendMode === "additive") {
5312
+ state.blendMode = blendMode;
5313
+ } else {
5314
+ this.error(`Unknown animation blend mode "${blendMode}"`);
5315
+ }
5316
+ return true;
5317
+ }
5318
+ if (key === "mask") {
5319
+ state.mask = this.coerceStringArray(this.parseValue());
5320
+ return true;
5321
+ }
5322
+ if (key === "baseline") {
5323
+ state.baseline = this.coerceNumberRecord(this.parseValue());
5324
+ return true;
5325
+ }
5326
+ return false;
5327
+ }
5328
+ coerceStringArray(value) {
5329
+ if (!Array.isArray(value)) return value == null ? [] : [String(value)];
5330
+ return value.map((entry) => String(entry));
5331
+ }
5332
+ coerceNumberArray(value) {
5333
+ if (!Array.isArray(value)) {
5334
+ const single = Number(value);
5335
+ return Number.isFinite(single) ? [single] : [];
5336
+ }
5337
+ return value.map((entry) => Number(entry)).filter((entry) => Number.isFinite(entry));
5338
+ }
5339
+ coerceNumberRecord(value) {
5340
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
5341
+ const out = {};
5342
+ for (const [key, raw] of Object.entries(value)) {
5343
+ const numeric = Number(raw);
5344
+ if (Number.isFinite(numeric)) out[key] = numeric;
5345
+ }
5346
+ return out;
5347
+ }
5348
+ isStateNameToken(offset = 0) {
5349
+ const token = this.peek(offset);
5350
+ return token.type === "STRING" || token.type === "IDENTIFIER" || this.isKeywordAsIdentifierType(token.type);
5351
+ }
5352
+ isAnimationTransitionShorthandStart() {
5353
+ if (!this.isStateNameToken()) return false;
5354
+ return this.peek(1).type === "ARROW" || this.peek(1).type === "MINUS" && this.peek(2).type === "GREATER";
5355
+ }
5356
+ consumeStateTransitionArrow() {
5357
+ if (this.match("ARROW")) return true;
5358
+ if (this.check("MINUS") && this.peek(1).type === "GREATER") {
5359
+ this.advance();
5360
+ this.advance();
5361
+ return true;
5362
+ }
5363
+ return false;
5364
+ }
5365
+ parseAnimationInputDeclaration(startLoc) {
5366
+ const name = this.expectIdentifier();
5367
+ this.expect("COLON");
5368
+ const rawType = this.parseIdentifierOrStringValue();
5369
+ const inputType = this.normalizeAnimationInputType(rawType);
5370
+ let defaultValue;
5371
+ if (this.match("EQUALS")) {
5372
+ defaultValue = this.coerceAnimationInputDefault(inputType, this.parseValue());
5373
+ }
5374
+ return {
5375
+ type: "AnimationInput",
5376
+ name,
5377
+ inputType,
5378
+ rawType,
5379
+ default: defaultValue,
5380
+ loc: { start: startLoc, end: this.currentLocation() }
5381
+ };
5382
+ }
5383
+ parseAnimationListenerDeclaration(startLoc) {
5384
+ const event = this.parseDottedIdentifierValue("Expected listener event");
5385
+ if (!this.consumeStateTransitionArrow()) {
5386
+ this.error("Expected -> in animation listener");
5387
+ }
5388
+ if (this.isIdentifierValue("fire")) {
5389
+ this.advance();
5390
+ return {
5391
+ type: "AnimationListener",
5392
+ event,
5393
+ parameter: this.parseDottedIdentifierValue("Expected trigger input"),
5394
+ action: "fire",
5395
+ loc: { start: startLoc, end: this.currentLocation() }
5396
+ };
5397
+ }
5398
+ if (this.isIdentifierValue("reset")) {
5399
+ this.advance();
5400
+ return {
5401
+ type: "AnimationListener",
5402
+ event,
5403
+ parameter: this.parseDottedIdentifierValue("Expected trigger input"),
5404
+ action: "reset",
5405
+ loc: { start: startLoc, end: this.currentLocation() }
5406
+ };
5407
+ }
5408
+ const parameter = this.parseDottedIdentifierValue("Expected animation input");
5409
+ this.expect("EQUALS");
5410
+ const assignment = this.parseAnimationListenerValue();
5411
+ return {
5412
+ type: "AnimationListener",
5413
+ event,
5414
+ parameter,
5415
+ action: "set",
5416
+ ...assignment,
5417
+ loc: { start: startLoc, end: this.currentLocation() }
5418
+ };
5419
+ }
5420
+ parseAnimationListenerValue() {
5421
+ if (this.isIdentifierValue("event")) {
5422
+ return { source: this.parseDottedIdentifierValue("Expected event value source") };
5423
+ }
5424
+ const value = this.parseValue();
5425
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "string") {
5426
+ return { value };
5427
+ }
5428
+ return { value: String(value ?? "") };
5429
+ }
5430
+ normalizeAnimationInputType(rawType) {
5431
+ const normalized = rawType.toLowerCase();
5432
+ if (normalized === "number") return "float";
5433
+ if (normalized === "boolean") return "bool";
5434
+ if (normalized === "bool" || normalized === "float" || normalized === "int" || normalized === "trigger") {
5435
+ return normalized;
5436
+ }
5437
+ this.error(`Unknown animation input type "${rawType}", defaulting to float`);
5438
+ return "float";
5439
+ }
5440
+ coerceAnimationInputDefault(inputType, value) {
5441
+ if (inputType === "bool" || inputType === "trigger") return Boolean(value);
5442
+ if (typeof value === "number") return value;
5443
+ if (typeof value === "boolean") return value ? 1 : 0;
5444
+ return void 0;
5445
+ }
5446
+ parseAnimationTransitionShorthand() {
5447
+ const startLoc = this.currentLocation();
5448
+ const rawFrom = this.parseStateNameValue();
5449
+ const from = rawFrom.toLowerCase() === "any" ? "any" : rawFrom;
5450
+ if (!this.consumeStateTransitionArrow()) {
5451
+ this.error("Expected -> in animation transition");
5452
+ }
5453
+ const target = this.parseStateNameValue();
5454
+ const transition = {
5455
+ type: "StateTransition",
5456
+ from,
5457
+ target,
5458
+ conditions: [],
5459
+ loc: { start: startLoc, end: this.currentLocation() }
5460
+ };
5461
+ while (!this.check("NEWLINE") && !this.check("SEMICOLON") && !this.check("COMMA") && !this.check("RBRACE") && !this.isAtEnd()) {
5462
+ if (!this.isStateNameToken()) break;
5463
+ const clause = this.current().value.toLowerCase();
5464
+ this.advance();
5465
+ if (clause === "when") {
5466
+ transition.condition = this.parseExpression();
5467
+ transition.conditions = this.expressionToAnimationConditions(transition.condition);
5468
+ } else if (clause === "on") {
5469
+ const event = this.parseIdentifierOrStringValue();
5470
+ transition.event = event;
5471
+ transition.conditions = [
5472
+ {
5473
+ type: "AnimationTransitionCondition",
5474
+ parameter: event,
5475
+ operator: "==",
5476
+ value: true,
5477
+ loc: { start: startLoc, end: this.currentLocation() }
5478
+ }
5479
+ ];
5480
+ } else if (clause === "over" || clause === "duration") {
5481
+ transition.duration = this.parseNumberClauseValue();
5482
+ } else if (clause === "easing") {
5483
+ transition.easing = this.parseIdentifierOrStringValue();
5484
+ } else if (clause === "exittime" || clause === "exit_time") {
5485
+ transition.exitTime = this.parseNumberClauseValue();
5486
+ transition.hasExitTime = true;
5487
+ } else if (clause === "pausewhenexiting" || clause === "pause_when_exiting") {
5488
+ transition.pauseWhenExiting = this.parseOptionalBooleanFlag();
5489
+ } else if (clause === "priority") {
5490
+ transition.priority = this.parseNumberClauseValue();
5491
+ } else if (clause === "cantransitiontoself" || clause === "can_transition_to_self") {
5492
+ transition.canTransitionToSelf = this.parseOptionalBooleanFlag();
5493
+ } else {
5494
+ this.error(`Unknown animation transition clause "${clause}"`);
5495
+ break;
5496
+ }
5497
+ }
5498
+ transition.loc = { start: startLoc, end: this.currentLocation() };
5499
+ if (this.check("COMMA") || this.check("SEMICOLON")) this.advance();
5500
+ return transition;
5501
+ }
5502
+ parseStateNameValue() {
5503
+ if (this.check("STRING") || this.check("IDENTIFIER") || this.isKeywordAsIdentifier()) {
5504
+ return this.advance().value;
5505
+ }
5506
+ this.error(`Expected state name, got ${this.current().type}`);
5507
+ return this.isAtEnd() ? "" : this.advance().value;
5508
+ }
5509
+ parseNumberClauseValue() {
5510
+ if (this.check("COLON")) this.advance();
5511
+ const value = this.parseValue();
5512
+ return typeof value === "number" ? value : Number(value) || 0;
5513
+ }
5514
+ parseIdentifierOrStringValue() {
5515
+ if (this.check("COLON")) this.advance();
5516
+ if (this.check("STRING") || this.check("IDENTIFIER") || this.isKeywordAsIdentifier()) {
5517
+ return this.advance().value;
5518
+ }
5519
+ const value = this.parseValue();
5520
+ return value == null ? "" : String(value);
5521
+ }
5522
+ parseDottedIdentifierValue(message) {
5523
+ let value = this.parseIdentifierOrStringValue();
5524
+ if (!value) {
5525
+ this.error(message);
5526
+ }
5527
+ while (this.check("DOT")) {
5528
+ this.advance();
5529
+ const part = this.parseIdentifierOrStringValue();
5530
+ if (!part) {
5531
+ this.error("Expected property name after dot");
5532
+ break;
5533
+ }
5534
+ value += `.${part}`;
5535
+ }
5536
+ return value;
5537
+ }
5538
+ isIdentifierValue(value) {
5539
+ return (this.current().type === "IDENTIFIER" || this.isKeywordAsIdentifierType(this.current().type)) && this.current().value === value;
5540
+ }
5541
+ parseOptionalBooleanFlag() {
5542
+ if (this.check("COLON")) this.advance();
5543
+ if (this.check("BOOLEAN")) return this.advance().value === "true";
5544
+ if (this.check("IDENTIFIER")) {
5545
+ const value = this.current().value.toLowerCase();
5546
+ if (value === "true" || value === "false") {
5547
+ this.advance();
5548
+ return value === "true";
5549
+ }
5550
+ }
5551
+ return true;
5552
+ }
5553
+ expressionToAnimationConditions(expression) {
5554
+ if (expression.type === "BinaryExpression" && (expression.operator === "&&" || expression.operator === "||")) {
5555
+ const left = this.expressionToAnimationConditions(expression.left);
5556
+ const right = this.expressionToAnimationConditions(expression.right);
5557
+ if (left.length > 0 && right.length > 0) {
5558
+ left[left.length - 1].chain = expression.operator === "||" ? "or" : "and";
5559
+ }
5560
+ return [...left, ...right];
5561
+ }
5562
+ const comparison = this.expressionToAnimationCondition(expression);
5563
+ return comparison ? [comparison] : [];
5564
+ }
5565
+ expressionToAnimationCondition(expression) {
5566
+ const startLoc = expression.loc?.start ?? this.currentLocation();
5567
+ const endLoc = expression.loc?.end ?? this.currentLocation();
5568
+ if (expression.type === "BinaryExpression") {
5569
+ const normalizedOperator = this.normalizeAnimationConditionOperator(expression.operator);
5570
+ if (normalizedOperator) {
5571
+ const parameter = this.expressionToString(expression.left);
5572
+ if (parameter) {
5573
+ return {
5574
+ type: "AnimationTransitionCondition",
5575
+ parameter,
5576
+ operator: normalizedOperator,
5577
+ value: this.expressionLiteralValue(expression.right),
5578
+ loc: { start: startLoc, end: endLoc }
5579
+ };
5580
+ }
5581
+ }
5582
+ }
5583
+ if (expression.type === "Identifier" || expression.type === "MemberExpression") {
5584
+ return {
5585
+ type: "AnimationTransitionCondition",
5586
+ parameter: this.expressionToString(expression),
5587
+ operator: "==",
5588
+ value: true,
5589
+ loc: { start: startLoc, end: endLoc }
5590
+ };
5591
+ }
5592
+ if (expression.type === "UnaryExpression" && expression.operator === "!") {
5593
+ const parameter = this.expressionToString(expression.argument);
5594
+ if (parameter) {
5595
+ return {
5596
+ type: "AnimationTransitionCondition",
5597
+ parameter,
5598
+ operator: "==",
5599
+ value: false,
5600
+ loc: { start: startLoc, end: endLoc }
5601
+ };
5602
+ }
5603
+ }
5604
+ return null;
5605
+ }
5606
+ normalizeAnimationConditionOperator(operator) {
5607
+ if (operator === "===") return "==";
5608
+ if (operator === "!==") return "!=";
5609
+ if (operator === "==" || operator === "!=" || operator === ">" || operator === "<" || operator === ">=" || operator === "<=") {
5610
+ return operator;
5611
+ }
5612
+ return null;
5613
+ }
5614
+ expressionLiteralValue(expression) {
5615
+ if (expression.type === "Literal") {
5616
+ if (expression.value === null) return "null";
5617
+ return expression.value;
5618
+ }
5619
+ const value = this.expressionToString(expression);
5620
+ return value || "";
5621
+ }
4654
5622
  parseStateTransitions() {
5623
+ if (this.check("LBRACE")) {
5624
+ this.expect("LBRACE");
5625
+ this.skipNewlines();
5626
+ const transitions2 = [];
5627
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
5628
+ this.skipNewlines();
5629
+ if (this.check("RBRACE")) break;
5630
+ if (this.isAnimationTransitionShorthandStart()) {
5631
+ transitions2.push(this.parseAnimationTransitionShorthand());
5632
+ } else {
5633
+ this.error(`Expected animation transition, got ${this.current().type}`);
5634
+ this.advance();
5635
+ }
5636
+ this.skipNewlines();
5637
+ }
5638
+ this.expect("RBRACE");
5639
+ return transitions2;
5640
+ }
4655
5641
  this.expect("LBRACKET");
4656
5642
  this.skipNewlines();
4657
5643
  const transitions = [];
4658
5644
  while (!this.check("RBRACKET") && !this.isAtEnd()) {
4659
5645
  this.skipNewlines();
4660
5646
  if (this.check("RBRACKET")) break;
5647
+ if (this.isAnimationTransitionShorthandStart()) {
5648
+ transitions.push(this.parseAnimationTransitionShorthand());
5649
+ this.skipNewlines();
5650
+ continue;
5651
+ }
4661
5652
  this.expect("LBRACE");
4662
5653
  this.skipNewlines();
4663
5654
  const transition = {
@@ -4669,9 +5660,46 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4669
5660
  if (this.check("RBRACE")) break;
4670
5661
  const key = this.expectIdentifier();
4671
5662
  this.expect("COLON");
4672
- if (key === "target") transition.target = this.parseValue();
4673
- else if (key === "condition") transition.condition = this.parseExpression();
4674
- else if (key === "event") transition.event = this.parseValue();
5663
+ if (key === "from") {
5664
+ const from = this.parseValue();
5665
+ transition.from = from.toLowerCase() === "any" ? "any" : from;
5666
+ } else if (key === "target" || key === "to") {
5667
+ transition.target = this.parseValue();
5668
+ } else if (key === "condition" || key === "when") {
5669
+ transition.condition = this.parseExpression();
5670
+ transition.conditions = this.expressionToAnimationConditions(transition.condition);
5671
+ } else if (key === "event" || key === "on") {
5672
+ transition.event = this.parseValue();
5673
+ transition.conditions = [
5674
+ {
5675
+ type: "AnimationTransitionCondition",
5676
+ parameter: transition.event,
5677
+ operator: "==",
5678
+ value: true,
5679
+ loc: transition.loc
5680
+ }
5681
+ ];
5682
+ } else if (key === "duration" || key === "over") {
5683
+ const duration = this.parseValue();
5684
+ transition.duration = typeof duration === "number" ? duration : Number(duration) || 0;
5685
+ } else if (key === "easing") {
5686
+ transition.easing = this.parseValue();
5687
+ } else if (key === "exitTime" || key === "exit_time") {
5688
+ const exitTime = this.parseValue();
5689
+ transition.exitTime = typeof exitTime === "number" ? exitTime : Number(exitTime) || 0;
5690
+ transition.hasExitTime = true;
5691
+ } else if (key === "hasExitTime" || key === "has_exit_time") {
5692
+ transition.hasExitTime = Boolean(this.parseValue());
5693
+ } else if (key === "pauseWhenExiting" || key === "pause_when_exiting") {
5694
+ transition.pauseWhenExiting = Boolean(this.parseValue());
5695
+ } else if (key === "priority") {
5696
+ const priority = this.parseValue();
5697
+ transition.priority = typeof priority === "number" ? priority : Number(priority) || 0;
5698
+ } else if (key === "canTransitionToSelf" || key === "can_transition_to_self") {
5699
+ transition.canTransitionToSelf = Boolean(this.parseValue());
5700
+ } else {
5701
+ this.parseValue();
5702
+ }
4675
5703
  this.skipNewlines();
4676
5704
  }
4677
5705
  this.expect("RBRACE");
@@ -4961,32 +5989,714 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4961
5989
  isDomainBlockToken() {
4962
5990
  return _HoloCompositionParser.DOMAIN_TOKENS.has(this.current().type);
4963
5991
  }
4964
- // ===========================================================================
4965
- // NORM LIFECYCLE BLOCKS (v4.5 March 2026, CRSEC Model)
4966
- // ===========================================================================
4967
- /**
4968
- * Parse a norm block with full CRSEC lifecycle sub-blocks.
4969
- *
4970
- * Pattern:
4971
- * ```
4972
- * norm "NormName" @trait1 @trait2 {
4973
- * description: "..."
4974
- * category: "..."
4975
- * priority: 8
4976
- *
4977
- * creation { ... }
4978
- * representation { ... }
4979
- * spreading { ... }
4980
- * evaluation { ... }
4981
- * compliance { ... }
4982
- *
4983
- * on norm_violated(agent, context) { ... }
4984
- * }
4985
- * ```
4986
- */
4987
- parseNormBlock() {
4988
- const startLoc = this.currentLocation();
4989
- this.pushContext("norm");
5992
+ isLooseOnHandlerStart() {
5993
+ return this.check("IDENTIFIER") && this.current().value === "on";
5994
+ }
5995
+ skipLooseOnHandler() {
5996
+ if (!this.isLooseOnHandlerStart()) return;
5997
+ this.advance();
5998
+ while (!this.check("LBRACE") && !this.isAtEnd()) {
5999
+ if (this.check("LPAREN")) {
6000
+ this.skipParens();
6001
+ } else {
6002
+ this.advance();
6003
+ }
6004
+ }
6005
+ if (this.check("LBRACE")) {
6006
+ this.skipBlock();
6007
+ }
6008
+ }
6009
+ isLooseDomainBlockStart() {
6010
+ if (!this.check("IDENTIFIER")) return false;
6011
+ const keyword = this.current().value;
6012
+ if (!/_material$/i.test(keyword)) return false;
6013
+ let index = this.pos + 1;
6014
+ if (this.tokens[index]?.type === "STRING" || this.tokens[index]?.type === "IDENTIFIER") {
6015
+ index++;
6016
+ }
6017
+ while (this.tokens[index]?.type === "AT") {
6018
+ index += 2;
6019
+ if (this.tokens[index]?.type === "LPAREN") {
6020
+ let depth = 1;
6021
+ index++;
6022
+ while (depth > 0 && index < this.tokens.length) {
6023
+ if (this.tokens[index].type === "LPAREN") depth++;
6024
+ else if (this.tokens[index].type === "RPAREN") depth--;
6025
+ index++;
6026
+ }
6027
+ }
6028
+ }
6029
+ while (this.tokens[index]?.type === "NEWLINE") index++;
6030
+ return this.tokens[index]?.type === "LBRACE";
6031
+ }
6032
+ isLooseNamedDomainBlockStart() {
6033
+ if (!this.check("IDENTIFIER")) return false;
6034
+ const keyword = this.current().value.toLowerCase();
6035
+ if (this.isPrimitiveShape(keyword) || this.isLightPrimitive(keyword) || keyword === "on") {
6036
+ return false;
6037
+ }
6038
+ let index = this.pos + 1;
6039
+ if (this.tokens[index]?.type !== "STRING" && this.tokens[index]?.type !== "IDENTIFIER") {
6040
+ return false;
6041
+ }
6042
+ index++;
6043
+ while (this.tokens[index]?.type === "AT") {
6044
+ index += 2;
6045
+ if (this.tokens[index]?.type === "LPAREN") {
6046
+ let depth = 1;
6047
+ index++;
6048
+ while (depth > 0 && index < this.tokens.length) {
6049
+ if (this.tokens[index].type === "LPAREN") depth++;
6050
+ else if (this.tokens[index].type === "RPAREN") depth--;
6051
+ index++;
6052
+ }
6053
+ }
6054
+ }
6055
+ while (this.tokens[index]?.type === "NEWLINE") index++;
6056
+ return this.tokens[index]?.type === "LBRACE";
6057
+ }
6058
+ // ===========================================================================
6059
+ // MMO/AAA GAME CONSTRUCTS (v6.2 — June 2026)
6060
+ // ===========================================================================
6061
+ /**
6062
+ * Parse a loot_table block with weighted entry sub-blocks and optional
6063
+ * guaranteed drop section.
6064
+ *
6065
+ * Syntax:
6066
+ * loot_table goblin_drops {
6067
+ * entry common_coin { item: "gold_coin" qty: "1..5" weight: 60 }
6068
+ * entry nothing { weight: 10 }
6069
+ * guaranteed { item: "goblin_ear" qty: 1 }
6070
+ * multiplier_on_faction_hostile: "ironveil * 1.5"
6071
+ * }
6072
+ */
6073
+ parseLootTable() {
6074
+ const startLoc = this.currentLocation();
6075
+ this.pushContext("loot-table");
6076
+ this.advance();
6077
+ const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
6078
+ this.expect("LBRACE");
6079
+ this.skipNewlines();
6080
+ const entries = [];
6081
+ let guaranteed;
6082
+ const properties = {};
6083
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6084
+ this.skipNewlines();
6085
+ if (this.check("RBRACE")) break;
6086
+ if (this.check("IDENTIFIER") && this.current().value === "entry") {
6087
+ this.advance();
6088
+ const entryId = this.check("STRING") ? this.expectString() : this.expectIdentifier();
6089
+ const entryProps = {};
6090
+ let weight = 0;
6091
+ let itemId;
6092
+ let qty;
6093
+ let rarity;
6094
+ let condition;
6095
+ if (this.check("LBRACE")) {
6096
+ this.advance();
6097
+ this.skipNewlines();
6098
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6099
+ this.skipNewlines();
6100
+ if (this.check("RBRACE")) break;
6101
+ const key = this.expectIdentifier();
6102
+ this.expect("COLON");
6103
+ const val = this.parseValue();
6104
+ if (key === "item") itemId = val;
6105
+ else if (key === "weight") weight = val;
6106
+ else if (key === "qty") qty = val;
6107
+ else if (key === "rarity") rarity = val;
6108
+ else if (key === "condition") condition = val;
6109
+ else entryProps[key] = val;
6110
+ if (this.check("COMMA")) this.advance();
6111
+ this.skipNewlines();
6112
+ }
6113
+ this.expect("RBRACE");
6114
+ }
6115
+ entries.push({
6116
+ type: "LootEntry",
6117
+ id: entryId,
6118
+ itemId,
6119
+ weight,
6120
+ qty,
6121
+ rarity,
6122
+ condition,
6123
+ properties: entryProps
6124
+ });
6125
+ } else if (this.check("IDENTIFIER") && this.current().value === "guaranteed") {
6126
+ this.advance();
6127
+ if (this.check("LBRACE")) {
6128
+ this.advance();
6129
+ this.skipNewlines();
6130
+ guaranteed = {};
6131
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6132
+ this.skipNewlines();
6133
+ if (this.check("RBRACE")) break;
6134
+ const key = this.expectIdentifier();
6135
+ this.expect("COLON");
6136
+ guaranteed[key] = this.parseValue();
6137
+ if (this.check("COMMA")) this.advance();
6138
+ this.skipNewlines();
6139
+ }
6140
+ this.expect("RBRACE");
6141
+ }
6142
+ } else {
6143
+ const key = this.expectIdentifier();
6144
+ this.expect("COLON");
6145
+ properties[key] = this.parseValue();
6146
+ }
6147
+ if (this.check("COMMA")) this.advance();
6148
+ this.skipNewlines();
6149
+ }
6150
+ this.expect("RBRACE");
6151
+ this.popContext();
6152
+ return {
6153
+ loc: { start: startLoc, end: this.currentLocation() },
6154
+ type: "LootTable",
6155
+ name,
6156
+ entries,
6157
+ guaranteed,
6158
+ properties
6159
+ };
6160
+ }
6161
+ /**
6162
+ * Parse a world_chunk block for open-world streaming.
6163
+ *
6164
+ * Syntax:
6165
+ * world_chunk dockside {
6166
+ * bounds: ((-200, 0, -200), (200, 100, 200))
6167
+ * priority: "high"
6168
+ * lod_distances: [50, 150, 400]
6169
+ * biome: "coastal_urban"
6170
+ * npc_roster: ["merchant_alva", "harbor_guard_01"]
6171
+ * streaming { load_radius: 300 unload_radius: 500 budget_kb: 32768 }
6172
+ * }
6173
+ */
6174
+ parseWorldChunk() {
6175
+ const startLoc = this.currentLocation();
6176
+ this.pushContext("world-chunk");
6177
+ this.advance();
6178
+ const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
6179
+ this.expect("LBRACE");
6180
+ this.skipNewlines();
6181
+ const properties = {};
6182
+ let priority;
6183
+ let biome;
6184
+ let lodDistances;
6185
+ let assetManifest;
6186
+ let npcRoster;
6187
+ let spawnPoints;
6188
+ let streaming;
6189
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6190
+ this.skipNewlines();
6191
+ if (this.check("RBRACE")) break;
6192
+ if (this.check("IDENTIFIER") && this.current().value === "streaming") {
6193
+ this.advance();
6194
+ if (this.check("LBRACE")) {
6195
+ this.advance();
6196
+ this.skipNewlines();
6197
+ streaming = {};
6198
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6199
+ this.skipNewlines();
6200
+ if (this.check("RBRACE")) break;
6201
+ const key = this.expectIdentifier();
6202
+ this.expect("COLON");
6203
+ streaming[key] = this.parseValue();
6204
+ if (this.check("COMMA")) this.advance();
6205
+ this.skipNewlines();
6206
+ }
6207
+ this.expect("RBRACE");
6208
+ }
6209
+ } else if (this.check("IDENTIFIER") && this.current().value === "asset_manifest") {
6210
+ this.advance();
6211
+ const val = this.parseValue();
6212
+ assetManifest = Array.isArray(val) ? val : [val];
6213
+ } else {
6214
+ const key = this.expectIdentifier();
6215
+ this.expect("COLON");
6216
+ const val = this.parseValue();
6217
+ if (key === "priority") priority = val;
6218
+ else if (key === "biome") biome = val;
6219
+ else if (key === "lod_distances")
6220
+ lodDistances = Array.isArray(val) ? val : [val];
6221
+ else if (key === "npc_roster") npcRoster = Array.isArray(val) ? val : [val];
6222
+ else if (key === "spawn_points") spawnPoints = val;
6223
+ else properties[key] = val;
6224
+ }
6225
+ if (this.check("COMMA")) this.advance();
6226
+ this.skipNewlines();
6227
+ }
6228
+ this.expect("RBRACE");
6229
+ this.popContext();
6230
+ return {
6231
+ loc: { start: startLoc, end: this.currentLocation() },
6232
+ type: "WorldChunk",
6233
+ name,
6234
+ priority,
6235
+ biome,
6236
+ lodDistances,
6237
+ assetManifest,
6238
+ npcRoster,
6239
+ spawnPoints,
6240
+ streaming,
6241
+ properties
6242
+ };
6243
+ }
6244
+ /**
6245
+ * Parse a world_layer block (P2.4 — phasing).
6246
+ *
6247
+ * Syntax:
6248
+ * world_layer post_awakening {
6249
+ * requires_quest: "main_chapter_1" // visible AFTER the quest is done
6250
+ * npcs: ["restored_keeper"] // forbids_quest = visible BEFORE
6251
+ * objects: ["healed_shrine"]
6252
+ * }
6253
+ */
6254
+ parseWorldLayer() {
6255
+ const startLoc = this.currentLocation();
6256
+ this.pushContext("world-layer");
6257
+ this.advance();
6258
+ const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
6259
+ this.expect("LBRACE");
6260
+ this.skipNewlines();
6261
+ const properties = {};
6262
+ let questId = "";
6263
+ let mustBeCompleted = true;
6264
+ let npcs = [];
6265
+ let objects = [];
6266
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6267
+ this.skipNewlines();
6268
+ if (this.check("RBRACE")) break;
6269
+ const key = this.expectIdentifier();
6270
+ this.expect("COLON");
6271
+ const val = this.parseValue();
6272
+ if (key === "requires_quest") {
6273
+ questId = String(val);
6274
+ mustBeCompleted = true;
6275
+ } else if (key === "forbids_quest") {
6276
+ questId = String(val);
6277
+ mustBeCompleted = false;
6278
+ } else if (key === "npcs") {
6279
+ npcs = (Array.isArray(val) ? val : [val]).map((v) => String(v));
6280
+ } else if (key === "objects") {
6281
+ objects = (Array.isArray(val) ? val : [val]).map((v) => String(v));
6282
+ } else {
6283
+ properties[key] = val;
6284
+ }
6285
+ if (this.check("COMMA")) this.advance();
6286
+ this.skipNewlines();
6287
+ }
6288
+ this.expect("RBRACE");
6289
+ this.popContext();
6290
+ return {
6291
+ loc: { start: startLoc, end: this.currentLocation() },
6292
+ type: "WorldLayer",
6293
+ name,
6294
+ predicate: { type: "PhasePredicate", kind: "quest_flag", questId, mustBeCompleted },
6295
+ npcs,
6296
+ objects,
6297
+ properties
6298
+ };
6299
+ }
6300
+ /**
6301
+ * Parse a dungeon_instance block (P2.6 — instanced content).
6302
+ *
6303
+ * Syntax:
6304
+ * dungeon_instance shadowfen_keep {
6305
+ * max_instances: 10
6306
+ * party_size: 5
6307
+ * reset_timer: 3600
6308
+ * completion_quest: "shadowfen_cleared"
6309
+ * npcs: ["dungeon_boss"]
6310
+ * }
6311
+ */
6312
+ parseDungeonInstance() {
6313
+ const startLoc = this.currentLocation();
6314
+ this.pushContext("dungeon-instance");
6315
+ this.advance();
6316
+ const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
6317
+ this.expect("LBRACE");
6318
+ this.skipNewlines();
6319
+ const properties = {};
6320
+ let maxInstances = 1;
6321
+ let partySize = 1;
6322
+ let resetTimer = 0;
6323
+ let completionQuest = "";
6324
+ let npcs = [];
6325
+ let objects = [];
6326
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6327
+ this.skipNewlines();
6328
+ if (this.check("RBRACE")) break;
6329
+ const key = this.expectIdentifier();
6330
+ this.expect("COLON");
6331
+ const val = this.parseValue();
6332
+ if (key === "max_instances") maxInstances = Number(val) || 1;
6333
+ else if (key === "party_size") partySize = Number(val) || 1;
6334
+ else if (key === "reset_timer") resetTimer = Number(val) || 0;
6335
+ else if (key === "completion_quest") completionQuest = String(val);
6336
+ else if (key === "npcs") npcs = (Array.isArray(val) ? val : [val]).map((v) => String(v));
6337
+ else if (key === "objects")
6338
+ objects = (Array.isArray(val) ? val : [val]).map((v) => String(v));
6339
+ else properties[key] = val;
6340
+ if (this.check("COMMA")) this.advance();
6341
+ this.skipNewlines();
6342
+ }
6343
+ this.expect("RBRACE");
6344
+ this.popContext();
6345
+ return {
6346
+ loc: { start: startLoc, end: this.currentLocation() },
6347
+ type: "DungeonInstance",
6348
+ name,
6349
+ maxInstances,
6350
+ partySize,
6351
+ resetTimer,
6352
+ completionQuest,
6353
+ npcs,
6354
+ objects,
6355
+ properties
6356
+ };
6357
+ }
6358
+ /**
6359
+ * Parse a world_shard block (P2.5 — world sharding).
6360
+ *
6361
+ * Syntax:
6362
+ * world_shard north_province {
6363
+ * min: [-1000, 0, -1000]
6364
+ * max: [0, 256, 1000]
6365
+ * neighbors: ["south_province"]
6366
+ * max_players: 200
6367
+ * handoff: "seamless"
6368
+ * }
6369
+ */
6370
+ parseWorldShard() {
6371
+ const startLoc = this.currentLocation();
6372
+ this.pushContext("world-shard");
6373
+ this.advance();
6374
+ const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
6375
+ this.expect("LBRACE");
6376
+ this.skipNewlines();
6377
+ const properties = {};
6378
+ let min = [0, 0, 0];
6379
+ let max = [0, 0, 0];
6380
+ let neighbors = [];
6381
+ let maxPlayers = 100;
6382
+ let handoff = "seamless";
6383
+ const toVec3 = (val) => {
6384
+ const a = (Array.isArray(val) ? val : [val]).map((v) => Number(v) || 0);
6385
+ return [a[0] ?? 0, a[1] ?? 0, a[2] ?? 0];
6386
+ };
6387
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6388
+ this.skipNewlines();
6389
+ if (this.check("RBRACE")) break;
6390
+ const key = this.expectIdentifier();
6391
+ this.expect("COLON");
6392
+ const val = this.parseValue();
6393
+ if (key === "min") min = toVec3(val);
6394
+ else if (key === "max") max = toVec3(val);
6395
+ else if (key === "neighbors")
6396
+ neighbors = (Array.isArray(val) ? val : [val]).map((v) => String(v));
6397
+ else if (key === "max_players") maxPlayers = Number(val) || 100;
6398
+ else if (key === "handoff") handoff = String(val);
6399
+ else properties[key] = val;
6400
+ if (this.check("COMMA")) this.advance();
6401
+ this.skipNewlines();
6402
+ }
6403
+ this.expect("RBRACE");
6404
+ this.popContext();
6405
+ return {
6406
+ loc: { start: startLoc, end: this.currentLocation() },
6407
+ type: "WorldShard",
6408
+ name,
6409
+ min,
6410
+ max,
6411
+ neighbors,
6412
+ maxPlayers,
6413
+ handoff,
6414
+ properties
6415
+ };
6416
+ }
6417
+ /**
6418
+ * Parse a spawn_point block.
6419
+ *
6420
+ * Syntax:
6421
+ * spawn_point village_entry {
6422
+ * faction: "neutral"
6423
+ * max_count: 10
6424
+ * respawn_radius: 5
6425
+ * position: (10, 0, 10)
6426
+ * }
6427
+ */
6428
+ parseSpawnPoint() {
6429
+ const startLoc = this.currentLocation();
6430
+ this.pushContext("spawn-point");
6431
+ this.advance();
6432
+ const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
6433
+ this.expect("LBRACE");
6434
+ this.skipNewlines();
6435
+ const properties = {};
6436
+ let faction;
6437
+ let maxCount;
6438
+ let respawnRadius;
6439
+ let position;
6440
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6441
+ this.skipNewlines();
6442
+ if (this.check("RBRACE")) break;
6443
+ const key = this.expectIdentifier();
6444
+ this.expect("COLON");
6445
+ const val = this.parseValue();
6446
+ if (key === "faction") faction = val;
6447
+ else if (key === "max_count") maxCount = val;
6448
+ else if (key === "respawn_radius") respawnRadius = val;
6449
+ else if (key === "position") {
6450
+ if (Array.isArray(val) && val.length >= 3) {
6451
+ position = { x: val[0], y: val[1], z: val[2] };
6452
+ }
6453
+ } else {
6454
+ properties[key] = val;
6455
+ }
6456
+ if (this.check("COMMA")) this.advance();
6457
+ this.skipNewlines();
6458
+ }
6459
+ this.expect("RBRACE");
6460
+ this.popContext();
6461
+ return {
6462
+ loc: { start: startLoc, end: this.currentLocation() },
6463
+ type: "SpawnPoint",
6464
+ name,
6465
+ faction,
6466
+ maxCount,
6467
+ respawnRadius,
6468
+ position,
6469
+ properties
6470
+ };
6471
+ }
6472
+ /**
6473
+ * Parse a trigger block for MMO interaction volumes.
6474
+ *
6475
+ * Syntax:
6476
+ * trigger dungeon_entrance {
6477
+ * radius: 3
6478
+ * faction_filter: ["alliance", "neutral"]
6479
+ * on_enter { emit("dungeon_enter") }
6480
+ * on_exit { emit("dungeon_exit") }
6481
+ * }
6482
+ */
6483
+ parseGameTrigger() {
6484
+ const startLoc = this.currentLocation();
6485
+ this.pushContext("game-trigger");
6486
+ this.advance();
6487
+ const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
6488
+ this.expect("LBRACE");
6489
+ this.skipNewlines();
6490
+ const properties = {};
6491
+ let radius = 1;
6492
+ let factionFilter;
6493
+ let position;
6494
+ const onEnter = [];
6495
+ const onExit = [];
6496
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6497
+ this.skipNewlines();
6498
+ if (this.check("RBRACE")) break;
6499
+ if (this.check("IDENTIFIER") && this.current().value === "on_enter") {
6500
+ this.advance();
6501
+ const params = this.check("LPAREN") ? this.parseParameterList() : [];
6502
+ const body = this.check("LBRACE") ? (() => {
6503
+ this.advance();
6504
+ this.skipNewlines();
6505
+ const stmts = this.parseStatementBlock();
6506
+ this.expect("RBRACE");
6507
+ return stmts;
6508
+ })() : [];
6509
+ onEnter.push({ type: "EventHandler", event: "on_enter", parameters: params, body });
6510
+ } else if (this.check("IDENTIFIER") && this.current().value === "on_exit") {
6511
+ this.advance();
6512
+ const params = this.check("LPAREN") ? this.parseParameterList() : [];
6513
+ const body = this.check("LBRACE") ? (() => {
6514
+ this.advance();
6515
+ this.skipNewlines();
6516
+ const stmts = this.parseStatementBlock();
6517
+ this.expect("RBRACE");
6518
+ return stmts;
6519
+ })() : [];
6520
+ onExit.push({ type: "EventHandler", event: "on_exit", parameters: params, body });
6521
+ } else {
6522
+ const key = this.expectIdentifier();
6523
+ this.expect("COLON");
6524
+ const val = this.parseValue();
6525
+ if (key === "radius") radius = val;
6526
+ else if (key === "faction_filter")
6527
+ factionFilter = Array.isArray(val) ? val : [val];
6528
+ else if (key === "position") {
6529
+ if (Array.isArray(val) && val.length >= 3) {
6530
+ position = { x: val[0], y: val[1], z: val[2] };
6531
+ }
6532
+ } else {
6533
+ properties[key] = val;
6534
+ }
6535
+ }
6536
+ if (this.check("COMMA")) this.advance();
6537
+ this.skipNewlines();
6538
+ }
6539
+ this.expect("RBRACE");
6540
+ this.popContext();
6541
+ return {
6542
+ loc: { start: startLoc, end: this.currentLocation() },
6543
+ type: "GameTrigger",
6544
+ name,
6545
+ radius,
6546
+ factionFilter,
6547
+ onEnter: onEnter.length > 0 ? onEnter : void 0,
6548
+ onExit: onExit.length > 0 ? onExit : void 0,
6549
+ position,
6550
+ properties
6551
+ };
6552
+ }
6553
+ /**
6554
+ * Parse a scene-level movement path:
6555
+ * movement_path patrol_route { mode: "patrol" loop: true speed: 2.5
6556
+ * waypoints: [[0,0,0],[10,0,0]] easing: "linear" }
6557
+ */
6558
+ parseMovementPath() {
6559
+ const startLoc = this.currentLocation();
6560
+ this.pushContext("movement-path");
6561
+ this.advance();
6562
+ const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
6563
+ this.expect("LBRACE");
6564
+ this.skipNewlines();
6565
+ const properties = {};
6566
+ let mode;
6567
+ let loop;
6568
+ let speed;
6569
+ let waypoints;
6570
+ let easing;
6571
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6572
+ this.skipNewlines();
6573
+ if (this.check("RBRACE")) break;
6574
+ const key = this.expectIdentifier();
6575
+ this.expect("COLON");
6576
+ const val = this.parseValue();
6577
+ if (key === "mode") mode = val;
6578
+ else if (key === "loop") loop = val;
6579
+ else if (key === "speed") speed = val;
6580
+ else if (key === "waypoints") waypoints = val;
6581
+ else if (key === "easing") easing = val;
6582
+ else properties[key] = val;
6583
+ if (this.check("COMMA")) this.advance();
6584
+ this.skipNewlines();
6585
+ }
6586
+ this.expect("RBRACE");
6587
+ this.popContext();
6588
+ return {
6589
+ loc: { start: startLoc, end: this.currentLocation() },
6590
+ type: "MovementPath",
6591
+ name,
6592
+ mode,
6593
+ loop,
6594
+ speed,
6595
+ waypoints,
6596
+ easing,
6597
+ properties
6598
+ };
6599
+ }
6600
+ /**
6601
+ * Parse a scene-level reaction trigger:
6602
+ * reaction_trigger on_player_enter { target: "player" condition: "..."
6603
+ * on_activate { emit("zone_entered") } on_deactivate { ... } cooldown: 2 }
6604
+ */
6605
+ parseReactionTrigger() {
6606
+ const startLoc = this.currentLocation();
6607
+ this.pushContext("reaction-trigger");
6608
+ this.advance();
6609
+ const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
6610
+ this.expect("LBRACE");
6611
+ this.skipNewlines();
6612
+ const properties = {};
6613
+ let target;
6614
+ let condition;
6615
+ let cooldown;
6616
+ const onActivate = [];
6617
+ const onDeactivate = [];
6618
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6619
+ this.skipNewlines();
6620
+ if (this.check("RBRACE")) break;
6621
+ if (this.check("IDENTIFIER") && this.current().value === "on_activate") {
6622
+ this.advance();
6623
+ const params = this.check("LPAREN") ? this.parseParameterList() : [];
6624
+ const body = this.check("LBRACE") ? (() => {
6625
+ this.advance();
6626
+ this.skipNewlines();
6627
+ const stmts = this.parseStatementBlock();
6628
+ this.expect("RBRACE");
6629
+ return stmts;
6630
+ })() : [];
6631
+ onActivate.push({ type: "EventHandler", event: "on_activate", parameters: params, body });
6632
+ } else if (this.check("IDENTIFIER") && this.current().value === "on_deactivate") {
6633
+ this.advance();
6634
+ const params = this.check("LPAREN") ? this.parseParameterList() : [];
6635
+ const body = this.check("LBRACE") ? (() => {
6636
+ this.advance();
6637
+ this.skipNewlines();
6638
+ const stmts = this.parseStatementBlock();
6639
+ this.expect("RBRACE");
6640
+ return stmts;
6641
+ })() : [];
6642
+ onDeactivate.push({
6643
+ type: "EventHandler",
6644
+ event: "on_deactivate",
6645
+ parameters: params,
6646
+ body
6647
+ });
6648
+ } else {
6649
+ const key = this.expectIdentifier();
6650
+ this.expect("COLON");
6651
+ const val = this.parseValue();
6652
+ if (key === "target") target = val;
6653
+ else if (key === "condition") condition = val;
6654
+ else if (key === "cooldown") cooldown = val;
6655
+ else properties[key] = val;
6656
+ }
6657
+ if (this.check("COMMA")) this.advance();
6658
+ this.skipNewlines();
6659
+ }
6660
+ this.expect("RBRACE");
6661
+ this.popContext();
6662
+ return {
6663
+ loc: { start: startLoc, end: this.currentLocation() },
6664
+ type: "ReactionTrigger",
6665
+ name,
6666
+ target,
6667
+ condition,
6668
+ cooldown,
6669
+ onActivate: onActivate.length > 0 ? onActivate : void 0,
6670
+ onDeactivate: onDeactivate.length > 0 ? onDeactivate : void 0,
6671
+ properties
6672
+ };
6673
+ }
6674
+ // ===========================================================================
6675
+ // NORM LIFECYCLE BLOCKS (v4.5 — March 2026, CRSEC Model)
6676
+ // ===========================================================================
6677
+ /**
6678
+ * Parse a norm block with full CRSEC lifecycle sub-blocks.
6679
+ *
6680
+ * Pattern:
6681
+ * ```
6682
+ * norm "NormName" @trait1 @trait2 {
6683
+ * description: "..."
6684
+ * category: "..."
6685
+ * priority: 8
6686
+ *
6687
+ * creation { ... }
6688
+ * representation { ... }
6689
+ * spreading { ... }
6690
+ * evaluation { ... }
6691
+ * compliance { ... }
6692
+ *
6693
+ * on norm_violated(agent, context) { ... }
6694
+ * }
6695
+ * ```
6696
+ */
6697
+ parseNormBlock() {
6698
+ const startLoc = this.currentLocation();
6699
+ this.pushContext("norm");
4990
6700
  this.advance();
4991
6701
  let name = "unnamed";
4992
6702
  if (this.check("STRING")) {
@@ -4994,15 +6704,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
4994
6704
  } else if (this.check("IDENTIFIER")) {
4995
6705
  name = this.expectIdentifier();
4996
6706
  }
4997
- const traits = [];
4998
- while (this.check("AT") && this.peek(1)?.type === "IDENTIFIER") {
4999
- this.advance();
5000
- traits.push(this.current().value);
5001
- this.advance();
5002
- if (this.check("LPAREN")) {
5003
- this.skipParens();
5004
- }
5005
- }
6707
+ const traits = this.parseInlineTraitNamesBeforeBlock();
5006
6708
  this.expect("LBRACE");
5007
6709
  this.skipNewlines();
5008
6710
  const properties = {};
@@ -5056,6 +6758,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
5056
6758
  body
5057
6759
  });
5058
6760
  }
6761
+ } else if (this.isPropertyName() && this.peek(1)?.type === "LBRACE") {
6762
+ const key = this.parsePropertyKey();
6763
+ properties[key] = this.parseBlockTraitConfig();
5059
6764
  } else if (this.check("IDENTIFIER") || this.check("STRING")) {
5060
6765
  const key = this.check("STRING") ? this.expectString() : this.expectIdentifier();
5061
6766
  this.expect("COLON");
@@ -5135,15 +6840,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
5135
6840
  } else if (this.check("IDENTIFIER")) {
5136
6841
  name = this.expectIdentifier();
5137
6842
  }
5138
- const traits = [];
5139
- while (this.check("AT") && this.peek(1)?.type === "IDENTIFIER") {
5140
- this.advance();
5141
- traits.push(this.current().value);
5142
- this.advance();
5143
- if (this.check("LPAREN")) {
5144
- this.skipParens();
5145
- }
5146
- }
6843
+ const traits = this.parseInlineTraitNamesBeforeBlock();
5147
6844
  this.expect("LBRACE");
5148
6845
  this.skipNewlines();
5149
6846
  const properties = {};
@@ -5185,6 +6882,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
5185
6882
  body
5186
6883
  });
5187
6884
  }
6885
+ } else if (this.isPropertyName() && this.peek(1)?.type === "LBRACE") {
6886
+ const key = this.parsePropertyKey();
6887
+ properties[key] = this.parseBlockTraitConfig();
5188
6888
  } else if (this.check("IDENTIFIER") || this.check("STRING")) {
5189
6889
  const key = this.check("STRING") ? this.expectString() : this.expectIdentifier();
5190
6890
  this.expect("COLON");
@@ -5209,6 +6909,303 @@ var _HoloCompositionParser = class _HoloCompositionParser {
5209
6909
  eventHandlers: eventHandlers.length > 0 ? eventHandlers : void 0
5210
6910
  };
5211
6911
  }
6912
+ // ===========================================================================
6913
+ // SIMULATION CONTRACT BLOCK (v6.3)
6914
+ // ===========================================================================
6915
+ /**
6916
+ * Parse a `sim_contract { ... }` block.
6917
+ *
6918
+ * Syntax:
6919
+ * ```
6920
+ * sim_contract {
6921
+ * precondition "name" { expr }
6922
+ * precondition "name" "description" { expr }
6923
+ * invariant "name" { expr }
6924
+ * receipt { field: type, ... }
6925
+ * }
6926
+ * ```
6927
+ */
6928
+ parseContractBlock() {
6929
+ const startLoc = this.currentLocation();
6930
+ this.pushContext("sim_contract");
6931
+ this.advance();
6932
+ this.expect("LBRACE");
6933
+ this.skipNewlines();
6934
+ const preconditions = [];
6935
+ const invariants = [];
6936
+ const receipt = {};
6937
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6938
+ this.skipNewlines();
6939
+ if (this.check("RBRACE")) break;
6940
+ const tokenLower = this.current().value.toLowerCase();
6941
+ if ((tokenLower === "precondition" || tokenLower === "invariant") && this.check("IDENTIFIER")) {
6942
+ const clauseKind = tokenLower;
6943
+ this.advance();
6944
+ let clauseName = "unnamed";
6945
+ if (this.check("STRING")) {
6946
+ clauseName = this.expectString();
6947
+ } else if (this.check("IDENTIFIER")) {
6948
+ clauseName = this.expectIdentifier();
6949
+ }
6950
+ let description;
6951
+ if (this.check("STRING")) {
6952
+ description = this.expectString();
6953
+ }
6954
+ let expr = "";
6955
+ if (this.check("LBRACE")) {
6956
+ this.advance();
6957
+ const parts = [];
6958
+ let depth = 1;
6959
+ while (depth > 0 && !this.isAtEnd()) {
6960
+ if (this.check("LBRACE")) depth++;
6961
+ if (this.check("RBRACE")) {
6962
+ depth--;
6963
+ if (depth === 0) break;
6964
+ }
6965
+ parts.push(this.current().value);
6966
+ this.advance();
6967
+ }
6968
+ this.expect("RBRACE");
6969
+ expr = parts.join(" ").trim();
6970
+ }
6971
+ const clause = { name: clauseName, expr };
6972
+ if (description !== void 0) clause.description = description;
6973
+ if (clauseKind === "precondition") {
6974
+ preconditions.push(clause);
6975
+ } else {
6976
+ invariants.push(clause);
6977
+ }
6978
+ } else if (tokenLower === "receipt" && this.check("IDENTIFIER")) {
6979
+ this.advance();
6980
+ if (this.check("LBRACE")) {
6981
+ this.advance();
6982
+ this.skipNewlines();
6983
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
6984
+ this.skipNewlines();
6985
+ if (this.check("RBRACE")) break;
6986
+ let fieldName = "";
6987
+ if (this.check("IDENTIFIER")) {
6988
+ fieldName = this.expectIdentifier();
6989
+ } else if (this.check("STRING")) {
6990
+ fieldName = this.expectString();
6991
+ } else {
6992
+ this.advance();
6993
+ continue;
6994
+ }
6995
+ let typeName = "unknown";
6996
+ if (this.check("COLON")) {
6997
+ this.advance();
6998
+ if (this.check("IDENTIFIER")) {
6999
+ typeName = this.expectIdentifier();
7000
+ } else if (this.check("STRING")) {
7001
+ typeName = this.expectString();
7002
+ }
7003
+ }
7004
+ if (fieldName) receipt[fieldName] = typeName;
7005
+ if (this.check("COMMA")) this.advance();
7006
+ this.skipNewlines();
7007
+ }
7008
+ this.expect("RBRACE");
7009
+ }
7010
+ } else {
7011
+ this.advance();
7012
+ }
7013
+ this.skipNewlines();
7014
+ }
7015
+ this.expect("RBRACE");
7016
+ this.popContext();
7017
+ return {
7018
+ loc: { start: startLoc, end: this.currentLocation() },
7019
+ type: "contract",
7020
+ preconditions,
7021
+ invariants,
7022
+ receipt
7023
+ };
7024
+ }
7025
+ // ── Pub/sub messaging primitives (v6.4) ───────────────────────────────────
7026
+ /**
7027
+ * Parse policy_pack Name { ... } as a first-class regulated-AI governance
7028
+ * primitive. Validation lives in policy/PolicyPack.ts so compilers and deploy
7029
+ * gates consume the same schema the parser emits.
7030
+ */
7031
+ parsePolicyPackBlock() {
7032
+ const startLoc = this.currentLocation();
7033
+ this.pushContext("policy-pack");
7034
+ this.advance();
7035
+ const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
7036
+ this.expect("LBRACE");
7037
+ this.skipNewlines();
7038
+ const properties = {};
7039
+ let version = "1.0.0";
7040
+ let frameworkId = "";
7041
+ let requiredTests = [];
7042
+ let requiredCompileTargets = [];
7043
+ let auditRetention = {};
7044
+ let monitoringCadence = {};
7045
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
7046
+ this.skipNewlines();
7047
+ if (this.check("RBRACE")) break;
7048
+ const key = this.expectIdentifier();
7049
+ if ((key === "audit_retention" || key === "auditRetention") && this.check("LBRACE")) {
7050
+ auditRetention = this.parseBlockTraitConfig();
7051
+ } else if ((key === "monitoring" || key === "monitoring_cadence" || key === "monitoringCadence") && this.check("LBRACE")) {
7052
+ monitoringCadence = this.parseBlockTraitConfig();
7053
+ } else {
7054
+ this.expect("COLON");
7055
+ const value = this.parseValue();
7056
+ if (key === "version") version = typeof value === "string" ? value : String(value);
7057
+ else if (key === "framework_id" || key === "frameworkId") {
7058
+ frameworkId = typeof value === "string" ? value : String(value);
7059
+ } else if (key === "required_tests" || key === "requiredTests") {
7060
+ requiredTests = Array.isArray(value) ? value : [value];
7061
+ } else if (key === "required_compile_targets" || key === "requiredCompileTargets") {
7062
+ requiredCompileTargets = (Array.isArray(value) ? value : [value]).map(
7063
+ (target) => String(target)
7064
+ );
7065
+ } else if (key === "audit_retention" || key === "auditRetention") {
7066
+ auditRetention = this.asRecord(value);
7067
+ } else if (key === "monitoring" || key === "monitoring_cadence" || key === "monitoringCadence") {
7068
+ monitoringCadence = this.asRecord(value);
7069
+ } else {
7070
+ properties[key] = value;
7071
+ }
7072
+ }
7073
+ if (this.check("COMMA")) this.advance();
7074
+ this.skipNewlines();
7075
+ }
7076
+ this.expect("RBRACE");
7077
+ this.popContext();
7078
+ return {
7079
+ loc: { start: startLoc, end: this.currentLocation() },
7080
+ type: "PolicyPack",
7081
+ name,
7082
+ version,
7083
+ frameworkId,
7084
+ requiredTests,
7085
+ requiredCompileTargets,
7086
+ auditRetention,
7087
+ monitoringCadence,
7088
+ properties
7089
+ };
7090
+ }
7091
+ asRecord(value) {
7092
+ if (!value || typeof value !== "object" || Array.isArray(value) || "__bind" in value) {
7093
+ return {};
7094
+ }
7095
+ return value;
7096
+ }
7097
+ /** Parse `topic Name { type: "T" broadcast: true }` */
7098
+ parseTopicBlock() {
7099
+ const startLoc = this.currentLocation();
7100
+ this.advance();
7101
+ const name = this.check("IDENTIFIER") ? this.expectIdentifier() : "unnamed";
7102
+ const metadata = {};
7103
+ let dataType;
7104
+ let broadcast;
7105
+ if (this.check("LBRACE")) {
7106
+ this.advance();
7107
+ this.skipNewlines();
7108
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
7109
+ this.skipNewlines();
7110
+ if (this.check("RBRACE") || this.check("NEWLINE")) {
7111
+ if (!this.check("RBRACE")) this.advance();
7112
+ continue;
7113
+ }
7114
+ const key = this.current().value;
7115
+ this.advance();
7116
+ if (this.check("COLON")) this.advance();
7117
+ if (key === "type" || key === "dataType") {
7118
+ dataType = this.check("STRING") ? this.expectString() : this.check("IDENTIFIER") ? this.expectIdentifier() : (this.advance(), void 0);
7119
+ } else if (key === "broadcast") {
7120
+ broadcast = this.current().value === "true";
7121
+ this.advance();
7122
+ } else if (this.check("LBRACE") || this.check("STRING") || this.check("NUMBER") || this.check("IDENTIFIER") || this.check("LBRACKET")) {
7123
+ metadata[key] = this.parseValue();
7124
+ }
7125
+ if (this.check("COMMA")) this.advance();
7126
+ this.skipNewlines();
7127
+ }
7128
+ this.expect("RBRACE");
7129
+ }
7130
+ const topic = {
7131
+ loc: { start: startLoc, end: this.currentLocation() },
7132
+ type: "Topic",
7133
+ name
7134
+ };
7135
+ if (dataType !== void 0) topic.dataType = dataType;
7136
+ if (broadcast !== void 0) topic.broadcast = broadcast;
7137
+ if (Object.keys(metadata).length > 0) topic.metadata = metadata;
7138
+ return topic;
7139
+ }
7140
+ /** Parse `channel Name { from: A to: B capacity: N }` */
7141
+ parseChannelBlock() {
7142
+ const startLoc = this.currentLocation();
7143
+ this.advance();
7144
+ const name = this.check("IDENTIFIER") ? this.expectIdentifier() : "unnamed";
7145
+ const metadata = {};
7146
+ let from;
7147
+ let to;
7148
+ let capacity;
7149
+ if (this.check("LBRACE")) {
7150
+ this.advance();
7151
+ this.skipNewlines();
7152
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
7153
+ this.skipNewlines();
7154
+ if (this.check("RBRACE") || this.check("NEWLINE")) {
7155
+ if (!this.check("RBRACE")) this.advance();
7156
+ continue;
7157
+ }
7158
+ const key = this.current().value;
7159
+ this.advance();
7160
+ if (this.check("COLON")) this.advance();
7161
+ if (key === "from") {
7162
+ from = this.check("STRING") ? this.expectString() : this.check("IDENTIFIER") ? this.expectIdentifier() : void 0;
7163
+ } else if (key === "to") {
7164
+ to = this.check("STRING") ? this.expectString() : this.check("IDENTIFIER") ? this.expectIdentifier() : void 0;
7165
+ } else if (key === "capacity") {
7166
+ capacity = this.check("NUMBER") ? Number(this.current().value) : void 0;
7167
+ if (capacity !== void 0) this.advance();
7168
+ } else if (this.check("LBRACE") || this.check("STRING") || this.check("NUMBER") || this.check("IDENTIFIER") || this.check("LBRACKET")) {
7169
+ metadata[key] = this.parseValue();
7170
+ }
7171
+ if (this.check("COMMA")) this.advance();
7172
+ this.skipNewlines();
7173
+ }
7174
+ this.expect("RBRACE");
7175
+ }
7176
+ const ch = {
7177
+ loc: { start: startLoc, end: this.currentLocation() },
7178
+ type: "Channel",
7179
+ name
7180
+ };
7181
+ if (from !== void 0) ch.from = from;
7182
+ if (to !== void 0) ch.to = to;
7183
+ if (capacity !== void 0) ch.capacity = capacity;
7184
+ if (Object.keys(metadata).length > 0) ch.metadata = metadata;
7185
+ return ch;
7186
+ }
7187
+ /** Parse `connect Identifier to Identifier [as "edgeType"]` */
7188
+ parseConnectionStmt() {
7189
+ const startLoc = this.currentLocation();
7190
+ this.advance();
7191
+ const from = this.check("IDENTIFIER") ? this.expectIdentifier() : "";
7192
+ if (this.check("IDENTIFIER") && this.current().value === "to") this.advance();
7193
+ const to = this.check("IDENTIFIER") ? this.expectIdentifier() : "";
7194
+ let edgeType;
7195
+ if (this.check("IDENTIFIER") && this.current().value === "as") {
7196
+ this.advance();
7197
+ if (this.check("STRING")) edgeType = this.expectString();
7198
+ else if (this.check("IDENTIFIER")) edgeType = this.expectIdentifier();
7199
+ }
7200
+ const conn = {
7201
+ loc: { start: startLoc, end: this.currentLocation() },
7202
+ type: "Connection",
7203
+ from,
7204
+ to
7205
+ };
7206
+ if (edgeType !== void 0) conn.edgeType = edgeType;
7207
+ return conn;
7208
+ }
5212
7209
  /**
5213
7210
  * Unified parser for all domain-specific blocks.
5214
7211
  * Pattern: KEYWORD NAME @trait1 @trait2 { properties... }
@@ -5255,27 +7252,27 @@ var _HoloCompositionParser = class _HoloCompositionParser {
5255
7252
  if (domain === "pipeline" && keyword === "pipeline") {
5256
7253
  return this.parsePipelineDomainBlock(name, traits);
5257
7254
  }
7255
+ if (token.type === "PCG_GRAPH") {
7256
+ return this.parsePCGGraphDomainBlock(startLoc, name, traits, keyword, domain);
7257
+ }
5258
7258
  this.expect("LBRACE");
5259
7259
  this.skipNewlines();
5260
7260
  const properties = {};
5261
7261
  const children = [];
5262
7262
  const eventHandlers = [];
5263
7263
  while (!this.check("RBRACE") && !this.isAtEnd()) {
5264
- this.skipNewlines();
7264
+ this.skipBlockMemberSeparators();
5265
7265
  if (this.check("RBRACE")) break;
5266
- if (this.check("OBJECT") || this.check("IDENTIFIER") && PRIMITIVE_SHAPES.has(this.current().value)) {
7266
+ if (this.check("OBJECT")) {
5267
7267
  children.push(this.parseObject());
7268
+ } else if (this.check("IDENTIFIER") && this.isPrimitiveShape(this.current().value) && this.peek(1).type !== "COLON") {
7269
+ children.push(this.parsePrimitiveObject());
5268
7270
  } else if (this.check("IDENTIFIER") && this.current().value.startsWith("on")) {
5269
7271
  const evtName = this.current().value;
5270
7272
  if (this.tokens[this.pos + 1]?.type === "LPAREN" || this.tokens[this.pos + 1]?.type === "LBRACE") {
5271
7273
  this.advance();
5272
7274
  if (this.check("LPAREN")) {
5273
- this.advance();
5274
- while (!this.check("RPAREN") && !this.isAtEnd()) {
5275
- this.expectIdentifier();
5276
- if (this.check("COMMA")) this.advance();
5277
- }
5278
- this.expect("RPAREN");
7275
+ this.skipParens();
5279
7276
  }
5280
7277
  if (this.check("LBRACE")) {
5281
7278
  this.skipBlock();
@@ -5287,13 +7284,51 @@ var _HoloCompositionParser = class _HoloCompositionParser {
5287
7284
  body: []
5288
7285
  });
5289
7286
  } else {
5290
- const key = this.expectIdentifier();
7287
+ const key = this.parsePropertyKey();
5291
7288
  this.expect("COLON");
5292
7289
  const value = this.parseValue();
5293
7290
  properties[key] = value;
5294
7291
  }
7292
+ } else if (this.check("AT")) {
7293
+ this.advance();
7294
+ const traitName = this.parseTraitName();
7295
+ if (traitName) traits.push(traitName);
7296
+ if (this.check("LPAREN") || this.check("LBRACE") || this.check("COLON")) {
7297
+ properties[`@${traitName}`] = this.parseOptionalTraitConfig();
7298
+ }
7299
+ } else if (this.isNamedOrTraitedPropertyBlockStart()) {
7300
+ const { key, value } = this.parseNamedOrTraitedPropertyBlock();
7301
+ properties[key] = value;
7302
+ } else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
7303
+ const key = this.parsePropertyKey();
7304
+ properties[key] = this.parseBlockTraitConfig();
7305
+ } else if (this.isPropertyName() && (this.peek(1).type === "STRING" || this.peek(1).type === "IDENTIFIER") && this.peek(2).type === "LBRACE") {
7306
+ const key = this.parsePropertyKey();
7307
+ const blockName = this.advance().value;
7308
+ properties[key] = {
7309
+ name: blockName,
7310
+ ...this.parseBlockTraitConfig()
7311
+ };
7312
+ } else if (this.isPropertyName() && (this.peek(1).type === "ARROW" || this.peek(1).type === "MINUS" && this.peek(2).type === "GREATER")) {
7313
+ const from = this.parsePropertyKey();
7314
+ if (this.check("ARROW")) {
7315
+ this.advance();
7316
+ } else {
7317
+ this.advance();
7318
+ this.advance();
7319
+ }
7320
+ if (domain === "input") {
7321
+ properties[from] = this.parseValue();
7322
+ if (this.check("COMMA")) this.advance();
7323
+ this.skipNewlines();
7324
+ continue;
7325
+ }
7326
+ const to = this.isBarewordPathToken() ? this.parseBarewordPathValue() : "";
7327
+ const existing = properties.connections;
7328
+ const connection = { from, to };
7329
+ properties.connections = Array.isArray(existing) ? [...existing, connection] : [connection];
5295
7330
  } else {
5296
- const key = this.expectIdentifier();
7331
+ const key = this.parsePropertyKey();
5297
7332
  this.expect("COLON");
5298
7333
  const value = this.parseValue();
5299
7334
  properties[key] = value;
@@ -5315,6 +7350,90 @@ var _HoloCompositionParser = class _HoloCompositionParser {
5315
7350
  eventHandlers: eventHandlers.length > 0 ? eventHandlers : void 0
5316
7351
  };
5317
7352
  }
7353
+ parsePCGGraphDomainBlock(startLoc, name, traits, keyword, domain) {
7354
+ this.expect("LBRACE");
7355
+ this.skipNewlines();
7356
+ const nodes = [];
7357
+ const properties = {
7358
+ nodes
7359
+ };
7360
+ while (!this.check("RBRACE") && !this.isAtEnd()) {
7361
+ this.skipNewlines();
7362
+ if (this.check("RBRACE")) break;
7363
+ const token = this.current();
7364
+ const next = this.peek(1);
7365
+ if (next?.type === "COLON" && (token.type === "IDENTIFIER" || token.type === "PCG_GRAPH")) {
7366
+ const key = token.value;
7367
+ this.advance();
7368
+ this.expect("COLON");
7369
+ properties[key] = this.parseValue();
7370
+ } else {
7371
+ const kind = token.value;
7372
+ this.advance();
7373
+ const nodeProperties = {};
7374
+ if (this.check("LPAREN")) {
7375
+ this.parsePCGNodeArgs(kind, nodeProperties);
7376
+ }
7377
+ nodes.push({
7378
+ kind,
7379
+ properties: nodeProperties
7380
+ });
7381
+ }
7382
+ this.skipNewlines();
7383
+ if (this.check("ARROW")) {
7384
+ this.advance();
7385
+ } else if (this.check("MINUS") && this.peek(1).type === "GREATER") {
7386
+ this.advance();
7387
+ this.advance();
7388
+ }
7389
+ if (this.check("COMMA")) this.advance();
7390
+ this.skipNewlines();
7391
+ }
7392
+ this.expect("RBRACE");
7393
+ this.popContext();
7394
+ return {
7395
+ loc: { start: startLoc, end: this.currentLocation() },
7396
+ type: "DomainBlock",
7397
+ domain,
7398
+ keyword,
7399
+ name,
7400
+ traits,
7401
+ properties
7402
+ };
7403
+ }
7404
+ parsePCGNodeArgs(kind, properties) {
7405
+ this.expect("LPAREN");
7406
+ const args = [];
7407
+ while (!this.check("RPAREN") && !this.isAtEnd()) {
7408
+ if (this.check("COMMA")) {
7409
+ this.advance();
7410
+ continue;
7411
+ }
7412
+ if (this.check("IDENTIFIER") && this.peek(1).type === "COLON") {
7413
+ const key = this.expectIdentifier();
7414
+ this.expect("COLON");
7415
+ properties[key] = this.parseValue();
7416
+ } else {
7417
+ args.push(this.parsePCGArgumentValue());
7418
+ }
7419
+ if (this.check("COMMA")) this.advance();
7420
+ }
7421
+ this.expect("RPAREN");
7422
+ if (kind === "scatter") {
7423
+ if (args[0] !== void 0) properties["source_mesh"] = args[0];
7424
+ if (args[1] !== void 0) properties["count"] = args[1];
7425
+ } else if (args.length > 0) {
7426
+ properties["args"] = args;
7427
+ }
7428
+ }
7429
+ parsePCGArgumentValue() {
7430
+ if (this.check("STRING") || this.check("NUMBER") || this.check("BOOLEAN") || this.check("NULL") || this.check("LBRACKET")) {
7431
+ return this.parseValue();
7432
+ }
7433
+ const value = this.current().value;
7434
+ this.advance();
7435
+ return value;
7436
+ }
5318
7437
  /**
5319
7438
  * Parse a pipeline domain block by extracting the raw body text
5320
7439
  * and delegating to PipelineParser for structured AST.
@@ -5453,6 +7572,10 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
5453
7572
  "SIMULATION",
5454
7573
  // Perception & simulation layer
5455
7574
  "MATERIAL",
7575
+ "MATERIAL_GRAPH",
7576
+ "LIGHT_FIELD",
7577
+ "NAV_FIELD",
7578
+ "PHYSICS_CONTRACT",
5456
7579
  "PBR_MATERIAL",
5457
7580
  "UNLIT_MATERIAL",
5458
7581
  "SHADER",
@@ -5463,6 +7586,7 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
5463
7586
  "PARTICLES",
5464
7587
  "EMITTER",
5465
7588
  "VFX",
7589
+ "PARTICLE_FIELD",
5466
7590
  "POST_PROCESSING",
5467
7591
  "POST_FX",
5468
7592
  "AUDIO_SOURCE",
@@ -5471,6 +7595,7 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
5471
7595
  "WEATHER",
5472
7596
  "ATMOSPHERE",
5473
7597
  "PROCEDURAL",
7598
+ "PCG_GRAPH",
5474
7599
  "SCATTER",
5475
7600
  "LOD_BLOCK",
5476
7601
  "RENDER",
@@ -5540,7 +7665,9 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
5540
7665
  "RETRY_BLOCK",
5541
7666
  "TIMEOUT_BLOCK",
5542
7667
  "FALLBACK_BLOCK",
5543
- "BULKHEAD_BLOCK"
7668
+ "BULKHEAD_BLOCK",
7669
+ // MMO/AAA game constructs (v6.2) — real_estate only; others handled by dedicated parsers
7670
+ "REAL_ESTATE"
5544
7671
  ]);
5545
7672
  /** Token → domain type mapping */
5546
7673
  _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
@@ -5582,6 +7709,10 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
5582
7709
  SIMULATION: "simulation",
5583
7710
  // Perception & simulation layer
5584
7711
  MATERIAL: "material",
7712
+ MATERIAL_GRAPH: "material_graph",
7713
+ LIGHT_FIELD: "light_field",
7714
+ NAV_FIELD: "nav_field",
7715
+ PHYSICS_CONTRACT: "physics_contract",
5585
7716
  PBR_MATERIAL: "material",
5586
7717
  UNLIT_MATERIAL: "material",
5587
7718
  SHADER: "material",
@@ -5592,6 +7723,7 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
5592
7723
  PARTICLES: "vfx",
5593
7724
  EMITTER: "vfx",
5594
7725
  VFX: "vfx",
7726
+ PARTICLE_FIELD: "particle_field",
5595
7727
  POST_PROCESSING: "postfx",
5596
7728
  POST_FX: "postfx",
5597
7729
  AUDIO_SOURCE: "audio",
@@ -5600,6 +7732,7 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
5600
7732
  WEATHER: "weather",
5601
7733
  ATMOSPHERE: "weather",
5602
7734
  PROCEDURAL: "procedural",
7735
+ PCG_GRAPH: "procedural",
5603
7736
  SCATTER: "procedural",
5604
7737
  LOD_BLOCK: "rendering",
5605
7738
  RENDER: "rendering",
@@ -5669,7 +7802,9 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
5669
7802
  RETRY_BLOCK: "resilience",
5670
7803
  TIMEOUT_BLOCK: "resilience",
5671
7804
  FALLBACK_BLOCK: "resilience",
5672
- BULKHEAD_BLOCK: "resilience"
7805
+ BULKHEAD_BLOCK: "resilience",
7806
+ // MMO/AAA game constructs (v6.2)
7807
+ REAL_ESTATE: "custom"
5673
7808
  };
5674
7809
  var HoloCompositionParser = _HoloCompositionParser;
5675
7810
  function parseHolo(source, options) {
@@ -5739,6 +7874,6 @@ function parseHoloPartial(source, options) {
5739
7874
  };
5740
7875
  }
5741
7876
 
5742
- export { HoloCompositionParser, parseHolo, parseHoloPartial, parseHoloStrict };
5743
- //# sourceMappingURL=chunk-OABEO6HH.js.map
5744
- //# sourceMappingURL=chunk-OABEO6HH.js.map
7877
+ export { HoloCompositionParser, KEYWORDS, LIGHT_PRIMITIVES, PRIMITIVE_SHAPES, parseHolo, parseHoloPartial, parseHoloStrict };
7878
+ //# sourceMappingURL=chunk-SZOLTWWD.js.map
7879
+ //# sourceMappingURL=chunk-SZOLTWWD.js.map