unspaghettit 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (766) hide show
  1. package/README.md +56 -18
  2. package/build/client/_app/immutable/assets/0.DCOD5ne_.css +1 -0
  3. package/build/client/_app/immutable/assets/0.DCOD5ne_.css.br +0 -0
  4. package/build/client/_app/immutable/assets/0.DCOD5ne_.css.gz +0 -0
  5. package/build/client/_app/immutable/assets/12.nv0I59TU.css.gz +0 -0
  6. package/build/client/_app/immutable/assets/3.B3akUL9A.css.gz +0 -0
  7. package/build/client/_app/immutable/assets/BehaviorGraph.Bk0xQRZk.css.gz +0 -0
  8. package/build/client/_app/immutable/chunks/B3vnQs252.js +1 -0
  9. package/build/client/_app/immutable/chunks/B3vnQs252.js.br +0 -0
  10. package/build/client/_app/immutable/chunks/B3vnQs252.js.gz +0 -0
  11. package/build/client/_app/immutable/chunks/{CxyLMlpt2.js → BANF9BhQ2.js} +1 -1
  12. package/build/client/_app/immutable/chunks/BANF9BhQ2.js.br +0 -0
  13. package/build/client/_app/immutable/chunks/BANF9BhQ2.js.gz +0 -0
  14. package/build/client/_app/immutable/chunks/BJdTO_n6.js +1 -0
  15. package/build/client/_app/immutable/chunks/BJdTO_n6.js.br +0 -0
  16. package/build/client/_app/immutable/chunks/BJdTO_n6.js.gz +0 -0
  17. package/build/client/_app/immutable/chunks/BPl9BITm.js.gz +0 -0
  18. package/build/client/_app/immutable/chunks/BQ9GodWX2.js.gz +0 -0
  19. package/build/client/_app/immutable/chunks/Bcyn5YUg.js +4 -0
  20. package/build/client/_app/immutable/chunks/Bcyn5YUg.js.br +0 -0
  21. package/build/client/_app/immutable/chunks/Bcyn5YUg.js.gz +0 -0
  22. package/build/client/_app/immutable/chunks/Bfc9rQXP.js +1 -0
  23. package/build/client/_app/immutable/chunks/Bfc9rQXP.js.br +0 -0
  24. package/build/client/_app/immutable/chunks/Bfc9rQXP.js.gz +0 -0
  25. package/build/client/_app/immutable/chunks/{BfMYiIUi.js → BjxqhpPG.js} +1 -1
  26. package/build/client/_app/immutable/chunks/BjxqhpPG.js.br +0 -0
  27. package/build/client/_app/immutable/chunks/BjxqhpPG.js.gz +0 -0
  28. package/build/client/_app/immutable/chunks/ByaoVvNB.js +1 -0
  29. package/build/client/_app/immutable/chunks/ByaoVvNB.js.br +0 -0
  30. package/build/client/_app/immutable/chunks/ByaoVvNB.js.gz +0 -0
  31. package/build/client/_app/immutable/chunks/BzLd0mTH.js.gz +0 -0
  32. package/build/client/_app/immutable/chunks/C8b3IMj8.js +1 -0
  33. package/build/client/_app/immutable/chunks/C8b3IMj8.js.br +0 -0
  34. package/build/client/_app/immutable/chunks/C8b3IMj8.js.gz +0 -0
  35. package/build/client/_app/immutable/chunks/CXvvf4uQ.js +1 -0
  36. package/build/client/_app/immutable/chunks/CXvvf4uQ.js.br +0 -0
  37. package/build/client/_app/immutable/chunks/CXvvf4uQ.js.gz +0 -0
  38. package/build/client/_app/immutable/chunks/Cl7Z3e6-.js.gz +0 -0
  39. package/build/client/_app/immutable/chunks/ClC4qR7W2.js +2 -0
  40. package/build/client/_app/immutable/chunks/ClC4qR7W2.js.br +0 -0
  41. package/build/client/_app/immutable/chunks/ClC4qR7W2.js.gz +0 -0
  42. package/build/client/_app/immutable/chunks/CuGlh1c2.js +1 -0
  43. package/build/client/_app/immutable/chunks/CuGlh1c2.js.br +0 -0
  44. package/build/client/_app/immutable/chunks/CuGlh1c2.js.gz +0 -0
  45. package/build/client/_app/immutable/chunks/CwzIdrQR.js +1 -0
  46. package/build/client/_app/immutable/chunks/CwzIdrQR.js.br +0 -0
  47. package/build/client/_app/immutable/chunks/CwzIdrQR.js.gz +0 -0
  48. package/build/client/_app/immutable/chunks/D5speDV82.js.gz +0 -0
  49. package/build/client/_app/immutable/chunks/D64sGJRN.js +1 -0
  50. package/build/client/_app/immutable/chunks/D64sGJRN.js.br +0 -0
  51. package/build/client/_app/immutable/chunks/D64sGJRN.js.gz +0 -0
  52. package/build/client/_app/immutable/chunks/DNaA4QRO2.js +1 -0
  53. package/build/client/_app/immutable/chunks/DNaA4QRO2.js.br +0 -0
  54. package/build/client/_app/immutable/chunks/DNaA4QRO2.js.gz +0 -0
  55. package/build/client/_app/immutable/chunks/Da59TXPe.js +1 -0
  56. package/build/client/_app/immutable/chunks/Da59TXPe.js.br +2 -0
  57. package/build/client/_app/immutable/chunks/Da59TXPe.js.gz +0 -0
  58. package/build/client/_app/immutable/chunks/DhTiE3j02.js +2 -0
  59. package/build/client/_app/immutable/chunks/DhTiE3j02.js.br +0 -0
  60. package/build/client/_app/immutable/chunks/DhTiE3j02.js.gz +0 -0
  61. package/build/client/_app/immutable/chunks/Dhqg7r_2.js.gz +0 -0
  62. package/build/client/_app/immutable/chunks/DmyaDy4d2.js +1 -0
  63. package/build/client/_app/immutable/chunks/DmyaDy4d2.js.br +0 -0
  64. package/build/client/_app/immutable/chunks/DmyaDy4d2.js.gz +0 -0
  65. package/build/client/_app/immutable/chunks/{DkxwAIfJ2.js → DryaQyjN2.js} +1 -1
  66. package/build/client/_app/immutable/chunks/DryaQyjN2.js.br +0 -0
  67. package/build/client/_app/immutable/chunks/DryaQyjN2.js.gz +0 -0
  68. package/build/client/_app/immutable/chunks/DtK8qK5Q2.js +1 -0
  69. package/build/client/_app/immutable/chunks/DtK8qK5Q2.js.br +0 -0
  70. package/build/client/_app/immutable/chunks/DtK8qK5Q2.js.gz +0 -0
  71. package/build/client/_app/immutable/chunks/DtblIi6X2.js +1 -0
  72. package/build/client/_app/immutable/chunks/DtblIi6X2.js.br +1 -0
  73. package/build/client/_app/immutable/chunks/DtblIi6X2.js.gz +0 -0
  74. package/build/client/_app/immutable/chunks/UkzDDeO42.js +1 -0
  75. package/build/client/_app/immutable/chunks/UkzDDeO42.js.br +0 -0
  76. package/build/client/_app/immutable/chunks/UkzDDeO42.js.gz +0 -0
  77. package/build/client/_app/immutable/chunks/{B_9TWPrx2.js → Vu8LzrwP2.js} +1 -1
  78. package/build/client/_app/immutable/chunks/Vu8LzrwP2.js.br +0 -0
  79. package/build/client/_app/immutable/chunks/Vu8LzrwP2.js.gz +0 -0
  80. package/build/client/_app/immutable/chunks/_b612aVb.js +1 -0
  81. package/build/client/_app/immutable/chunks/_b612aVb.js.br +0 -0
  82. package/build/client/_app/immutable/chunks/_b612aVb.js.gz +0 -0
  83. package/build/client/_app/immutable/chunks/aNMRV4sP2.js.gz +0 -0
  84. package/build/client/_app/immutable/chunks/cMamJTsF.js.gz +0 -0
  85. package/build/client/_app/immutable/chunks/ib21i2T_.js.gz +0 -0
  86. package/build/client/_app/immutable/chunks/kNaey6uv.js.gz +0 -0
  87. package/build/client/_app/immutable/chunks/oVMDLirx.js +1 -0
  88. package/build/client/_app/immutable/chunks/oVMDLirx.js.br +0 -0
  89. package/build/client/_app/immutable/chunks/oVMDLirx.js.gz +0 -0
  90. package/build/client/_app/immutable/chunks/olAc024e.js +1 -0
  91. package/build/client/_app/immutable/chunks/olAc024e.js.br +0 -0
  92. package/build/client/_app/immutable/chunks/olAc024e.js.gz +0 -0
  93. package/build/client/_app/immutable/chunks/suTxxv1t.js.gz +0 -0
  94. package/build/client/_app/immutable/chunks/wXIHzLMQ2.js +1 -0
  95. package/build/client/_app/immutable/chunks/wXIHzLMQ2.js.br +0 -0
  96. package/build/client/_app/immutable/chunks/wXIHzLMQ2.js.gz +0 -0
  97. package/build/client/_app/immutable/chunks/{B439_FLv.js → wrqalH0a.js} +1 -1
  98. package/build/client/_app/immutable/chunks/wrqalH0a.js.br +0 -0
  99. package/build/client/_app/immutable/chunks/wrqalH0a.js.gz +0 -0
  100. package/build/client/_app/immutable/chunks/x60Tn5kT.js +1 -0
  101. package/build/client/_app/immutable/chunks/x60Tn5kT.js.br +0 -0
  102. package/build/client/_app/immutable/chunks/x60Tn5kT.js.gz +0 -0
  103. package/build/client/_app/immutable/chunks/xihTtKlq.js.gz +0 -0
  104. package/build/client/_app/immutable/chunks/{BOrLmFwJ.js → yShDxCNj.js} +1 -1
  105. package/build/client/_app/immutable/chunks/yShDxCNj.js.br +2 -0
  106. package/build/client/_app/immutable/chunks/yShDxCNj.js.gz +0 -0
  107. package/build/client/_app/immutable/entry/app.Etd-exTb.js +2 -0
  108. package/build/client/_app/immutable/entry/app.Etd-exTb.js.br +0 -0
  109. package/build/client/_app/immutable/entry/app.Etd-exTb.js.gz +0 -0
  110. package/build/client/_app/immutable/entry/start.DY2B3u4g.js +1 -0
  111. package/build/client/_app/immutable/entry/start.DY2B3u4g.js.br +0 -0
  112. package/build/client/_app/immutable/entry/start.DY2B3u4g.js.gz +0 -0
  113. package/build/client/_app/immutable/nodes/0.tKfYV3__.js +8 -0
  114. package/build/client/_app/immutable/nodes/0.tKfYV3__.js.br +0 -0
  115. package/build/client/_app/immutable/nodes/0.tKfYV3__.js.gz +0 -0
  116. package/build/client/_app/immutable/nodes/{1.Dyte3Ggf.js → 1.CER5ICKt.js} +1 -1
  117. package/build/client/_app/immutable/nodes/1.CER5ICKt.js.br +1 -0
  118. package/build/client/_app/immutable/nodes/1.CER5ICKt.js.gz +0 -0
  119. package/build/client/_app/immutable/nodes/10.rT7cD8kX.js +1 -0
  120. package/build/client/_app/immutable/nodes/10.rT7cD8kX.js.br +0 -0
  121. package/build/client/_app/immutable/nodes/10.rT7cD8kX.js.gz +0 -0
  122. package/build/client/_app/immutable/nodes/11.BAnV_Y5Y.js +2 -0
  123. package/build/client/_app/immutable/nodes/11.BAnV_Y5Y.js.br +0 -0
  124. package/build/client/_app/immutable/nodes/11.BAnV_Y5Y.js.gz +0 -0
  125. package/build/client/_app/immutable/nodes/{11.wvMfJKC2.js → 12.DCTRFMqo.js} +4 -3
  126. package/build/client/_app/immutable/nodes/12.DCTRFMqo.js.br +0 -0
  127. package/build/client/_app/immutable/nodes/12.DCTRFMqo.js.gz +0 -0
  128. package/build/client/_app/immutable/nodes/{2.CmPPom9Z.js → 2.CF488WWF.js} +1 -1
  129. package/build/client/_app/immutable/nodes/2.CF488WWF.js.br +0 -0
  130. package/build/client/_app/immutable/nodes/2.CF488WWF.js.gz +0 -0
  131. package/build/client/_app/immutable/nodes/3.CP7CPPVH.js +1 -0
  132. package/build/client/_app/immutable/nodes/3.CP7CPPVH.js.br +0 -0
  133. package/build/client/_app/immutable/nodes/3.CP7CPPVH.js.gz +0 -0
  134. package/build/client/_app/immutable/nodes/4.D1bxCSiM.js +3 -0
  135. package/build/client/_app/immutable/nodes/4.D1bxCSiM.js.br +0 -0
  136. package/build/client/_app/immutable/nodes/4.D1bxCSiM.js.gz +0 -0
  137. package/build/client/_app/immutable/nodes/5.D6jZgh9y.js +48 -0
  138. package/build/client/_app/immutable/nodes/5.D6jZgh9y.js.br +0 -0
  139. package/build/client/_app/immutable/nodes/5.D6jZgh9y.js.gz +0 -0
  140. package/build/client/_app/immutable/nodes/6.BrBFUA0s.js +1 -0
  141. package/build/client/_app/immutable/nodes/6.BrBFUA0s.js.br +0 -0
  142. package/build/client/_app/immutable/nodes/6.BrBFUA0s.js.gz +0 -0
  143. package/build/client/_app/immutable/nodes/7.pajo8MfM.js +3 -0
  144. package/build/client/_app/immutable/nodes/7.pajo8MfM.js.br +0 -0
  145. package/build/client/_app/immutable/nodes/7.pajo8MfM.js.gz +0 -0
  146. package/build/client/_app/immutable/nodes/8.Cc80_Igi.js +5 -0
  147. package/build/client/_app/immutable/nodes/8.Cc80_Igi.js.br +0 -0
  148. package/build/client/_app/immutable/nodes/8.Cc80_Igi.js.gz +0 -0
  149. package/build/client/_app/immutable/nodes/{8.B-HweAc8.js → 9.D72NaL3l.js} +1 -1
  150. package/build/client/_app/immutable/nodes/9.D72NaL3l.js.br +1 -0
  151. package/build/client/_app/immutable/nodes/9.D72NaL3l.js.gz +0 -0
  152. package/build/client/_app/version.json +1 -1
  153. package/build/client/_app/version.json.br +0 -0
  154. package/build/client/_app/version.json.gz +0 -0
  155. package/build/client/lyriks_logo.svg.gz +0 -0
  156. package/build/server/chunks/0-8YZc572z.js +15 -0
  157. package/build/server/chunks/0-8YZc572z.js.map +1 -0
  158. package/build/server/chunks/1-DxkfSJLu.js +9 -0
  159. package/build/server/chunks/{1-BSUItTig.js.map → 1-DxkfSJLu.js.map} +1 -1
  160. package/build/server/chunks/10-DkObdGtU.js +9 -0
  161. package/build/server/chunks/10-DkObdGtU.js.map +1 -0
  162. package/build/server/chunks/11-DL94HxpZ.js +9 -0
  163. package/build/server/chunks/11-DL94HxpZ.js.map +1 -0
  164. package/build/server/chunks/12-CI74sCkt.js +9 -0
  165. package/build/server/chunks/12-CI74sCkt.js.map +1 -0
  166. package/build/server/chunks/2-qhWwQ4eL.js +9 -0
  167. package/build/server/chunks/2-qhWwQ4eL.js.map +1 -0
  168. package/build/server/chunks/3-CzoZtSTp.js +16 -0
  169. package/build/server/chunks/3-CzoZtSTp.js.map +1 -0
  170. package/build/server/chunks/4-CDa9DBsh.js +16 -0
  171. package/build/server/chunks/4-CDa9DBsh.js.map +1 -0
  172. package/build/server/chunks/5-qD2xxOrq.js +9 -0
  173. package/build/server/chunks/5-qD2xxOrq.js.map +1 -0
  174. package/build/server/chunks/6-B4mWzvDn.js +9 -0
  175. package/build/server/chunks/6-B4mWzvDn.js.map +1 -0
  176. package/build/server/chunks/7-zExv-fTN.js +9 -0
  177. package/build/server/chunks/7-zExv-fTN.js.map +1 -0
  178. package/build/server/chunks/8-BVrGdQg4.js +9 -0
  179. package/build/server/chunks/{7-C4hmS0dG.js.map → 8-BVrGdQg4.js.map} +1 -1
  180. package/build/server/chunks/9-BnZLRMYA.js +9 -0
  181. package/build/server/chunks/9-BnZLRMYA.js.map +1 -0
  182. package/build/server/chunks/{BehaviorGraph-m5kYj5HH.js → BehaviorGraph-C-9z37Sm.js} +43 -12
  183. package/build/server/chunks/BehaviorGraph-C-9z37Sm.js.map +1 -0
  184. package/build/server/chunks/Clock-BfMWQpmJ.js +5 -0
  185. package/build/server/chunks/Clock-BfMWQpmJ.js.map +1 -0
  186. package/build/server/chunks/DeleteDomain-BvHEgAyp.js +24 -0
  187. package/build/server/chunks/DeleteDomain-BvHEgAyp.js.map +1 -0
  188. package/build/server/chunks/{FeatureValidator-B8qEjAUW.js → DeleteFeature-DnK8sBJI.js} +142 -77
  189. package/build/server/chunks/DeleteFeature-DnK8sBJI.js.map +1 -0
  190. package/build/server/chunks/DeleteProject-BXZcehHZ.js +41 -0
  191. package/build/server/chunks/DeleteProject-BXZcehHZ.js.map +1 -0
  192. package/build/server/chunks/Effect-BJtLR-6l.js +46 -0
  193. package/build/server/chunks/Effect-BJtLR-6l.js.map +1 -0
  194. package/build/server/chunks/{FeatureCard-CfbXNYe8.js → FeatureCard-Bb50FEfp.js} +4 -4
  195. package/build/server/chunks/{FeatureCard-CfbXNYe8.js.map → FeatureCard-Bb50FEfp.js.map} +1 -1
  196. package/build/server/chunks/{FeatureJson-Bv-qiOSf.js → FeatureJson-DYvMEAub.js} +2 -2
  197. package/build/server/chunks/{FeatureJson-Bv-qiOSf.js.map → FeatureJson-DYvMEAub.js.map} +1 -1
  198. package/build/server/chunks/{FeatureTransforms-UWDHmWEg.js → FeatureTransforms-B0aI_CJD.js} +10 -3
  199. package/build/server/chunks/FeatureTransforms-B0aI_CJD.js.map +1 -0
  200. package/build/server/chunks/{ManageTagsDialog-DBxA3tM2.js → ManageTagsDialog-D5xbAVNB.js} +5 -5
  201. package/build/server/chunks/ManageTagsDialog-D5xbAVNB.js.map +1 -0
  202. package/build/server/chunks/{ProgressBar-DDoQJ_C9.js → ProgressBar-CUC2EZqG.js} +2 -2
  203. package/build/server/chunks/{ProgressBar-DDoQJ_C9.js.map → ProgressBar-CUC2EZqG.js.map} +1 -1
  204. package/build/server/chunks/{ProjectsIndex-DUVJ3hyL.js → ProjectsIndex-FgIu9dBp.js} +135 -14
  205. package/build/server/chunks/ProjectsIndex-FgIu9dBp.js.map +1 -0
  206. package/build/server/chunks/{RenameTag-BuWLMl1m.js → RenameTag-DWIIR4Bx.js} +3 -6
  207. package/build/server/chunks/RenameTag-DWIIR4Bx.js.map +1 -0
  208. package/build/server/chunks/ScenarioApplier-YPKECfZe.js +55 -0
  209. package/build/server/chunks/ScenarioApplier-YPKECfZe.js.map +1 -0
  210. package/build/server/chunks/SimulatorEngine-DM1F9nCO.js +1391 -0
  211. package/build/server/chunks/SimulatorEngine-DM1F9nCO.js.map +1 -0
  212. package/build/server/chunks/StateValue-BBjWox8f.js +105 -0
  213. package/build/server/chunks/StateValue-BBjWox8f.js.map +1 -0
  214. package/build/server/chunks/{TagDotStrip-B1XQ0m0Y.js → TagDotStrip-0rn-IJVE.js} +4 -4
  215. package/build/server/chunks/TagDotStrip-0rn-IJVE.js.map +1 -0
  216. package/build/server/chunks/{TagFilterSelect-DbO0Qduh.js → TagFilterSelect-Dbu-7Dg4.js} +5 -5
  217. package/build/server/chunks/{TagFilterSelect-DbO0Qduh.js.map → TagFilterSelect-Dbu-7Dg4.js.map} +1 -1
  218. package/build/server/chunks/{TagPalette-CtMNYCmu.js → TagPalette-CpdTiC_7.js} +101 -9
  219. package/build/server/chunks/TagPalette-CpdTiC_7.js.map +1 -0
  220. package/build/server/chunks/{TransitionCatalog-B8zHs-2E.js → TransitionCatalog-CYXUANy6.js} +2 -2
  221. package/build/server/chunks/TransitionCatalog-CYXUANy6.js.map +1 -0
  222. package/build/server/chunks/{_layout.svelte-CLTmk0xU.js → _layout.svelte-pSSG85WT.js} +689 -14
  223. package/build/server/chunks/_layout.svelte-pSSG85WT.js.map +1 -0
  224. package/build/server/chunks/{_page.svelte-Oj-W7G5s.js → _page.svelte-BNH3szkk.js} +22 -17
  225. package/build/server/chunks/{_page.svelte-Oj-W7G5s.js.map → _page.svelte-BNH3szkk.js.map} +1 -1
  226. package/build/server/chunks/_page.svelte-BcuGvUt1.js +37 -0
  227. package/build/server/chunks/{_page.svelte-Cham-dsM.js.map → _page.svelte-BcuGvUt1.js.map} +1 -1
  228. package/build/server/chunks/_page.svelte-BoOMG5Y0.js +37 -0
  229. package/build/server/chunks/{_page.svelte-B1nG3PKn.js.map → _page.svelte-BoOMG5Y0.js.map} +1 -1
  230. package/build/server/chunks/{_page.svelte-Caq7J0jU.js → _page.svelte-C4PRh_wP.js} +18 -12
  231. package/build/server/chunks/_page.svelte-C4PRh_wP.js.map +1 -0
  232. package/build/server/chunks/{_page.svelte-Z_kK2lHY.js → _page.svelte-Cqn34NXy.js} +19 -13
  233. package/build/server/chunks/_page.svelte-Cqn34NXy.js.map +1 -0
  234. package/build/server/chunks/{_page.svelte-B1s7jxaQ.js → _page.svelte-DSCeOGv7.js} +15 -10
  235. package/build/server/chunks/_page.svelte-DSCeOGv7.js.map +1 -0
  236. package/build/server/chunks/_page.svelte-DqWdGt48.js +182 -0
  237. package/build/server/chunks/_page.svelte-DqWdGt48.js.map +1 -0
  238. package/build/server/chunks/{_page.svelte-Dhwjwph_.js → _page.svelte-DsQHSEl4.js} +20 -12
  239. package/build/server/chunks/_page.svelte-DsQHSEl4.js.map +1 -0
  240. package/build/server/chunks/{_page.svelte-DlFVT40-.js → _page.svelte-Uioz8hsG.js} +18 -11
  241. package/build/server/chunks/{_page.svelte-DlFVT40-.js.map → _page.svelte-Uioz8hsG.js.map} +1 -1
  242. package/build/server/chunks/{_page.svelte-BW_nbAAH.js → _page.svelte-p38jot9e.js} +80 -173
  243. package/build/server/chunks/_page.svelte-p38jot9e.js.map +1 -0
  244. package/build/server/chunks/{_page.svelte-NVT2dzpG.js → _page.svelte-yN5kzgJ9.js} +218 -263
  245. package/build/server/chunks/_page.svelte-yN5kzgJ9.js.map +1 -0
  246. package/build/server/chunks/{_server.ts-DsbbVoOn.js → _server.ts-1CtrHhte.js} +4 -4
  247. package/build/server/chunks/{_server.ts-DsbbVoOn.js.map → _server.ts-1CtrHhte.js.map} +1 -1
  248. package/build/server/chunks/{_server.ts-CWvU15tL.js → _server.ts-71Qx1lQb.js} +4 -4
  249. package/build/server/chunks/{_server.ts-CWvU15tL.js.map → _server.ts-71Qx1lQb.js.map} +1 -1
  250. package/build/server/chunks/_server.ts-BAyekGHB.js +961 -0
  251. package/build/server/chunks/_server.ts-BAyekGHB.js.map +1 -0
  252. package/build/server/chunks/{_server.ts-BihpbxOW.js → _server.ts-BLWhU22T.js} +4 -4
  253. package/build/server/chunks/{_server.ts-BihpbxOW.js.map → _server.ts-BLWhU22T.js.map} +1 -1
  254. package/build/server/chunks/{_server.ts-YnfXkeMJ.js → _server.ts-C7EVZVxv.js} +22 -13
  255. package/build/server/chunks/_server.ts-C7EVZVxv.js.map +1 -0
  256. package/build/server/chunks/{_server.ts-vcaqdwxS.js → _server.ts-CGjYuLmo.js} +12 -7
  257. package/build/server/chunks/_server.ts-CGjYuLmo.js.map +1 -0
  258. package/build/server/chunks/{_server.ts-Dy5zQHe2.js → _server.ts-CX6H8fSE.js} +8 -31
  259. package/build/server/chunks/_server.ts-CX6H8fSE.js.map +1 -0
  260. package/build/server/chunks/{_server.ts-BuoQ02BW.js → _server.ts-CyEdTCLr.js} +4 -4
  261. package/build/server/chunks/{_server.ts-BuoQ02BW.js.map → _server.ts-CyEdTCLr.js.map} +1 -1
  262. package/build/server/chunks/_server.ts-DKVTM9Pj.js +77 -0
  263. package/build/server/chunks/_server.ts-DKVTM9Pj.js.map +1 -0
  264. package/build/server/chunks/{_server.ts-0uNTZKwF.js → _server.ts-Dip65hLJ.js} +15 -9
  265. package/build/server/chunks/_server.ts-Dip65hLJ.js.map +1 -0
  266. package/build/server/chunks/{_server.ts-D4EO0VHu.js → _server.ts-Dm0tCs2i.js} +5 -5
  267. package/build/server/chunks/{_server.ts-D4EO0VHu.js.map → _server.ts-Dm0tCs2i.js.map} +1 -1
  268. package/build/server/chunks/{_server.ts-BIBWjQI-.js → _server.ts-DsYwK_uW.js} +4 -4
  269. package/build/server/chunks/{_server.ts-BIBWjQI-.js.map → _server.ts-DsYwK_uW.js.map} +1 -1
  270. package/build/server/chunks/{_server.ts-DDa0Nk_S.js → _server.ts-RCEgegYU.js} +4 -4
  271. package/build/server/chunks/{_server.ts-DDa0Nk_S.js.map → _server.ts-RCEgegYU.js.map} +1 -1
  272. package/build/server/chunks/_server.ts-XOLAT4dd.js +146 -0
  273. package/build/server/chunks/_server.ts-XOLAT4dd.js.map +1 -0
  274. package/build/server/chunks/_server.ts-afh_zLVi.js +69 -0
  275. package/build/server/chunks/_server.ts-afh_zLVi.js.map +1 -0
  276. package/build/server/chunks/{browserContainer-CNX7ANld.js → browserContainer-BdldtueJ.js} +71 -1378
  277. package/build/server/chunks/browserContainer-BdldtueJ.js.map +1 -0
  278. package/build/server/chunks/buildSearchDocs-Cyfrnw9G.js +337 -0
  279. package/build/server/chunks/buildSearchDocs-Cyfrnw9G.js.map +1 -0
  280. package/build/server/chunks/{builderModeStore.svelte-BpRIU_zP.js → builderModeStore.svelte-BEZMQEqn.js} +7 -6
  281. package/build/server/chunks/builderModeStore.svelte-BEZMQEqn.js.map +1 -0
  282. package/build/server/chunks/{client-DeX3TC3s.js → client-C9Cat4DK.js} +3 -3
  283. package/build/server/chunks/{client-DeX3TC3s.js.map → client-C9Cat4DK.js.map} +1 -1
  284. package/build/server/chunks/{error.svelte-Cdjeq3L2.js → error.svelte-CzVR_A6P.js} +5 -5
  285. package/build/server/chunks/{error.svelte-Cdjeq3L2.js.map → error.svelte-CzVR_A6P.js.map} +1 -1
  286. package/build/server/chunks/featureQueueContext-DuXpyTdC.js +32 -0
  287. package/build/server/chunks/featureQueueContext-DuXpyTdC.js.map +1 -0
  288. package/build/server/chunks/{featureStore.svelte-DIYgPBVm.js → featureStore.svelte-DHZf88gu.js} +5 -4
  289. package/build/server/chunks/featureStore.svelte-DHZf88gu.js.map +1 -0
  290. package/build/server/chunks/{projectsStore.svelte-QDz5PchX.js → featuresStore.svelte-bUyQBg1-.js} +95 -3
  291. package/build/server/chunks/featuresStore.svelte-bUyQBg1-.js.map +1 -0
  292. package/build/server/chunks/humanize-CkCPfeWi.js +53 -0
  293. package/build/server/chunks/humanize-CkCPfeWi.js.map +1 -0
  294. package/build/server/chunks/{index-server-7H0jzj0M.js → index-server-DvBux_Gf.js} +47 -2
  295. package/build/server/chunks/{index-server-7H0jzj0M.js.map → index-server-DvBux_Gf.js.map} +1 -1
  296. package/build/server/chunks/{internal-KYK0WpL7.js → internal-BFt8yDlf.js} +3 -3
  297. package/build/server/chunks/{internal-KYK0WpL7.js.map → internal-BFt8yDlf.js.map} +1 -1
  298. package/build/server/chunks/projectBundleClient-BtvWPh87.js +168 -0
  299. package/build/server/chunks/projectBundleClient-BtvWPh87.js.map +1 -0
  300. package/build/server/chunks/projectContextStore.svelte-jRJGJZ42.js +141 -0
  301. package/build/server/chunks/projectContextStore.svelte-jRJGJZ42.js.map +1 -0
  302. package/build/server/chunks/projectFeaturesStore.svelte-BwNEtDIL.js +87 -0
  303. package/build/server/chunks/projectFeaturesStore.svelte-BwNEtDIL.js.map +1 -0
  304. package/build/server/chunks/{projectFeaturesStore.svelte-2o-72_vr.js → projectStore.svelte-BNuLNxk_.js} +5 -88
  305. package/build/server/chunks/projectStore.svelte-BNuLNxk_.js.map +1 -0
  306. package/build/server/chunks/{reconcile-B5xqb6-s.js → reconcile-CVG2LSlW.js} +60 -4
  307. package/build/server/chunks/reconcile-CVG2LSlW.js.map +1 -0
  308. package/build/server/chunks/{snapshotRepository-BPXCjX92.js → snapshotRepository-8f-2wTrb.js} +30 -5
  309. package/build/server/chunks/snapshotRepository-8f-2wTrb.js.map +1 -0
  310. package/build/server/chunks/{state-DBjl9lhV.js → state-CZZtjXLE.js} +3 -3
  311. package/build/server/chunks/{state-DBjl9lhV.js.map → state-CZZtjXLE.js.map} +1 -1
  312. package/build/server/chunks/{sync-DZ3dn761.js → sync-Bn6eSUhC.js} +3 -3
  313. package/build/server/chunks/{sync-DZ3dn761.js.map → sync-Bn6eSUhC.js.map} +1 -1
  314. package/build/server/chunks/{syncBridge-BwXzPdjJ.js → syncAwareRepositories-DvUjq5Q6.js} +27 -3
  315. package/build/server/chunks/syncAwareRepositories-DvUjq5Q6.js.map +1 -0
  316. package/build/server/chunks/{tagPaletteStore.svelte-DfZOBvgY.js → tagPaletteStore.svelte-C71bdzDl.js} +4 -4
  317. package/build/server/chunks/{tagPaletteStore.svelte-DfZOBvgY.js.map → tagPaletteStore.svelte-C71bdzDl.js.map} +1 -1
  318. package/build/server/index.js +2 -2
  319. package/build/server/index.js.map +1 -1
  320. package/build/server/manifest.js +59 -30
  321. package/build/server/manifest.js.map +1 -1
  322. package/cli/README.md +70 -2
  323. package/cli/commands/check.ts +190 -0
  324. package/cli/commands/ci.ts +71 -0
  325. package/cli/commands/coverage-ingest.ts +112 -0
  326. package/cli/commands/scenarios-adapter.ts +96 -0
  327. package/cli/scenarios/adapter-scaffold.ts +99 -0
  328. package/cli/scenarios/codegen.ts +7 -1
  329. package/cli/scenarios/results.ts +85 -0
  330. package/cli/skills/unspa-audit/SKILL.md +19 -0
  331. package/cli/skills/unspa-edit/SKILL.md +20 -3
  332. package/cli/skills/unspa-implement/SKILL.md +28 -0
  333. package/cli/unspa.ts +98 -0
  334. package/cli/util/context-files.ts +13 -2
  335. package/mcp-server/bin.ts +104 -104
  336. package/mcp-server/migrate-defaults.ts +164 -164
  337. package/mcp-server/repo-link.ts +142 -134
  338. package/mcp-server/resources/guide.ts +24 -4
  339. package/mcp-server/resources/operations.ts +3 -0
  340. package/mcp-server/seed-snapshots.ts +22 -22
  341. package/mcp-server/server.ts +8 -4
  342. package/mcp-server/sync-aware-repos.ts +79 -79
  343. package/mcp-server/sync-notifier.ts +180 -180
  344. package/mcp-server/tools/_codegen.ts +115 -115
  345. package/mcp-server/tools/_entity_builders.ts +30 -0
  346. package/mcp-server/tools/_shared.ts +210 -210
  347. package/mcp-server/tools/action.ts +210 -210
  348. package/mcp-server/tools/batch.ts +29 -5
  349. package/mcp-server/tools/effect.ts +139 -135
  350. package/mcp-server/tools/entity.ts +132 -132
  351. package/mcp-server/tools/entityField.ts +132 -132
  352. package/mcp-server/tools/event.ts +116 -116
  353. package/mcp-server/tools/feature.ts +264 -264
  354. package/mcp-server/tools/invariant.ts +275 -275
  355. package/mcp-server/tools/persona.ts +141 -141
  356. package/mcp-server/tools/project.ts +500 -391
  357. package/mcp-server/tools/reachabilityGoal.ts +97 -0
  358. package/mcp-server/tools/read.ts +526 -483
  359. package/mcp-server/tools/reorder.ts +114 -114
  360. package/mcp-server/tools/resource.ts +194 -194
  361. package/mcp-server/tools/rule.ts +302 -302
  362. package/mcp-server/tools/scenario.ts +4 -1
  363. package/mcp-server/tools/specGaps.ts +221 -221
  364. package/mcp-server/tools/state.ts +10 -2
  365. package/mcp-server/tools/surface.ts +102 -102
  366. package/mcp-server/tools/transition.ts +96 -96
  367. package/mcp-server/tools/verification.ts +131 -0
  368. package/package.json +14 -2
  369. package/src/app.css +26 -14
  370. package/src/features/behavior-model/application/ports/FeatureRepository.ts +16 -16
  371. package/src/features/behavior-model/application/use-cases/CreateFeature.ts +24 -24
  372. package/src/features/behavior-model/application/use-cases/DeleteFeature.ts +8 -8
  373. package/src/features/behavior-model/application/use-cases/GetFeature.ts +9 -9
  374. package/src/features/behavior-model/application/use-cases/ListFeatures.ts +10 -10
  375. package/src/features/behavior-model/application/use-cases/MutateFeature.ts +90 -90
  376. package/src/features/behavior-model/application/use-cases/SaveFeature.ts +31 -31
  377. package/src/features/behavior-model/domain/entities/Entity.ts +45 -45
  378. package/src/features/behavior-model/domain/entities/EventDefinition.ts +35 -35
  379. package/src/features/behavior-model/domain/entities/Feature.ts +10 -0
  380. package/src/features/behavior-model/domain/entities/Persona.ts +33 -33
  381. package/src/features/behavior-model/domain/entities/ReachabilityGoal.ts +39 -0
  382. package/src/features/behavior-model/domain/entities/Resource.ts +54 -54
  383. package/src/features/behavior-model/domain/entities/Scenario.ts +15 -0
  384. package/src/features/behavior-model/domain/entities/StateDefinition.ts +13 -0
  385. package/src/features/behavior-model/domain/entities/Surface.ts +75 -75
  386. package/src/features/behavior-model/domain/entities/index.ts +9 -9
  387. package/src/features/behavior-model/domain/services/BehaviorGraphModel.ts +25 -0
  388. package/src/features/behavior-model/domain/services/DerivedState.ts +67 -0
  389. package/src/features/behavior-model/domain/services/EffectApplier.ts +112 -3
  390. package/src/features/behavior-model/domain/services/EffectiveEntities.ts +166 -166
  391. package/src/features/behavior-model/domain/services/EntityDeducer.ts +83 -83
  392. package/src/features/behavior-model/domain/services/EventCatalog.ts +141 -141
  393. package/src/features/behavior-model/domain/services/FeatureExpressionNormalizer.ts +43 -5
  394. package/src/features/behavior-model/domain/services/FeatureSharedStateNormalizer.ts +24 -3
  395. package/src/features/behavior-model/domain/services/FeatureTransforms.ts +33 -0
  396. package/src/features/behavior-model/domain/services/FeatureValidator.ts +124 -16
  397. package/src/features/behavior-model/domain/services/PersonaApplier.ts +39 -39
  398. package/src/features/behavior-model/domain/services/ResourceDeducer.ts +64 -64
  399. package/src/features/behavior-model/domain/services/ResourceUsage.ts +79 -79
  400. package/src/features/behavior-model/domain/services/ScenarioApplier.ts +40 -40
  401. package/src/features/behavior-model/domain/services/SharedStateDefinitions.ts +32 -32
  402. package/src/features/behavior-model/domain/services/StatePathReferences.ts +249 -217
  403. package/src/features/behavior-model/domain/services/TransitionCatalog.ts +173 -173
  404. package/src/features/behavior-model/domain/value-objects/Effect.ts +100 -3
  405. package/src/features/behavior-model/domain/value-objects/EntityFieldType.ts +57 -57
  406. package/src/features/behavior-model/domain/value-objects/Expression.ts +22 -2
  407. package/src/features/behavior-model/domain/value-objects/ParameterType.ts +57 -57
  408. package/src/features/behavior-model/domain/value-objects/Resource.ts +210 -210
  409. package/src/features/behavior-model/domain/value-objects/RuleCategory.ts +57 -57
  410. package/src/features/behavior-model/domain/value-objects/RuleCondition.ts +52 -1
  411. package/src/features/behavior-model/domain/value-objects/SimulationClock.ts +35 -0
  412. package/src/features/behavior-model/domain/value-objects/ids.ts +2 -0
  413. package/src/features/behavior-model/infrastructure/io/FeatureJson.ts +89 -89
  414. package/src/features/behavior-model/infrastructure/persistence/HttpFeatureRepository.ts +43 -43
  415. package/src/features/behavior-model/infrastructure/persistence/JsonFolderFeatureRepository.ts +10 -0
  416. package/src/features/behavior-model/infrastructure/persistence/snapshot-discovery.ts +76 -76
  417. package/src/features/behavior-model/infrastructure/seed/seedStorefront.ts +967 -967
  418. package/src/features/behavior-model/presentation/adapters/VisBehaviorGraphRenderer.ts +10 -1
  419. package/src/features/behavior-model/presentation/components/ActionEditor.svelte +683 -682
  420. package/src/features/behavior-model/presentation/components/ActionsEditor.svelte +232 -232
  421. package/src/features/behavior-model/presentation/components/BehaviorGraph.svelte +275 -77
  422. package/src/features/behavior-model/presentation/components/EffectEditor.svelte +168 -168
  423. package/src/features/behavior-model/presentation/components/EntityEditor.svelte +241 -248
  424. package/src/features/behavior-model/presentation/components/EntityFieldRow.svelte +180 -181
  425. package/src/features/behavior-model/presentation/components/EntityManager.svelte +252 -251
  426. package/src/features/behavior-model/presentation/components/EventsManager.svelte +373 -372
  427. package/src/features/behavior-model/presentation/components/FeatureEditor.svelte +396 -348
  428. package/src/features/behavior-model/presentation/components/FeatureHeader.svelte +152 -143
  429. package/src/features/behavior-model/presentation/components/FeatureHealthStrip.svelte +110 -110
  430. package/src/features/behavior-model/presentation/components/HistoryPanel.svelte +154 -154
  431. package/src/features/behavior-model/presentation/components/NewFeatureForm.svelte +66 -66
  432. package/src/features/behavior-model/presentation/components/ParameterNameSelect.svelte +84 -84
  433. package/src/features/behavior-model/presentation/components/ParametersEditor.svelte +411 -411
  434. package/src/features/behavior-model/presentation/components/PersonaEditor.svelte +244 -244
  435. package/src/features/behavior-model/presentation/components/PersonasManager.svelte +130 -130
  436. package/src/features/behavior-model/presentation/components/ReachabilityGoalEditor.svelte +230 -0
  437. package/src/features/behavior-model/presentation/components/ReachabilityGoalsEditor.svelte +86 -0
  438. package/src/features/behavior-model/presentation/components/ResourcesManager.svelte +291 -290
  439. package/src/features/behavior-model/presentation/components/ScenariosEditor.svelte +496 -496
  440. package/src/features/behavior-model/presentation/components/StateDefinitionsEditor.svelte +356 -356
  441. package/src/features/behavior-model/presentation/components/SurfaceEntitiesView.svelte +88 -88
  442. package/src/features/behavior-model/presentation/components/SurfaceInvariantsEditor.svelte +76 -76
  443. package/src/features/behavior-model/presentation/components/SurfaceList.svelte +300 -300
  444. package/src/features/behavior-model/presentation/components/SurfaceMetaEditor.svelte +158 -156
  445. package/src/features/behavior-model/presentation/components/SurfacePanel.svelte +198 -198
  446. package/src/features/behavior-model/presentation/components/SurfacePersonasView.svelte +122 -122
  447. package/src/features/behavior-model/presentation/components/SurfaceResourcesView.svelte +113 -113
  448. package/src/features/behavior-model/presentation/components/SurfaceRulesEditor.svelte +69 -69
  449. package/src/features/behavior-model/presentation/components/TransitionsManager.svelte +322 -321
  450. package/src/features/behavior-model/presentation/context/featureQueueContext.ts +78 -0
  451. package/src/features/behavior-model/presentation/stores/editorStore.svelte.ts +132 -131
  452. package/src/features/behavior-model/presentation/stores/featureStore.svelte.ts +177 -177
  453. package/src/features/behavior-model/presentation/stores/featuresStore.svelte.ts +98 -98
  454. package/src/features/behavior-model/presentation/view-models/BehaviorGraphTheme.ts +1 -0
  455. package/src/features/behavior-model/presentation/view-models/factories.ts +181 -132
  456. package/src/features/domains/infrastructure/persistence/JsonFolderDomainRepository.ts +9 -0
  457. package/src/features/global-search/application/use-cases/LoadSearchIndex.ts +70 -0
  458. package/src/features/global-search/domain/SearchDoc.ts +111 -0
  459. package/src/features/global-search/domain/buildSearchDocs.ts +483 -0
  460. package/src/features/global-search/domain/searchNav.ts +58 -0
  461. package/src/features/global-search/domain/searchScoring.ts +81 -0
  462. package/src/features/global-search/infrastructure/adapters/defaultSearchHost.ts +28 -0
  463. package/src/features/global-search/presentation/components/GlobalSearch.svelte +262 -0
  464. package/src/features/global-search/presentation/ports/SearchHostPorts.ts +41 -0
  465. package/src/features/global-search/presentation/searchKindMeta.ts +108 -0
  466. package/src/features/global-search/presentation/stores/globalSearchStore.svelte.ts +171 -0
  467. package/src/features/implementation-queue/presentation/components/FloatingQueueWidget.svelte +264 -0
  468. package/src/features/implementation-queue/presentation/stores/globalQueueStore.svelte.ts +172 -0
  469. package/src/features/implementation-status/application/ports/ImplementationStatusRepository.ts +8 -8
  470. package/src/features/implementation-status/application/use-cases/GetImplementationStatus.ts +8 -8
  471. package/src/features/implementation-status/domain/ApplyCapturedToSpec.ts +323 -322
  472. package/src/features/implementation-status/domain/FieldDiff.ts +238 -236
  473. package/src/features/implementation-status/infrastructure/persistence/InMemoryImplementationStatusRepository.ts +21 -21
  474. package/src/features/implementation-status/presentation/components/ImplementationStatusPanel.svelte +831 -831
  475. package/src/features/implementation-status/presentation/stores/implementationStatusStore.svelte.ts +97 -97
  476. package/src/features/library/application/use-cases/ApplyBlueprintsToFeature.ts +33 -33
  477. package/src/features/library/domain/services/BlueprintApplier.ts +94 -94
  478. package/src/features/library/infrastructure/blueprints/auth/ResetPasswordBlueprint.ts +332 -332
  479. package/src/features/library/infrastructure/blueprints/auth/SignInBlueprint.ts +281 -281
  480. package/src/features/library/infrastructure/blueprints/auth/SignUpBlueprint.ts +299 -299
  481. package/src/features/library/infrastructure/blueprints/auth/VerifyEmailBlueprint.ts +288 -288
  482. package/src/features/library/infrastructure/blueprints/auth/shared.ts +146 -146
  483. package/src/features/library/infrastructure/blueprints/commerce/CartBlueprint.ts +222 -222
  484. package/src/features/library/infrastructure/blueprints/commerce/CatalogBlueprint.ts +190 -190
  485. package/src/features/library/infrastructure/blueprints/commerce/CheckoutBlueprint.ts +322 -322
  486. package/src/features/library/infrastructure/blueprints/commerce/OrderConfirmationBlueprint.ts +172 -172
  487. package/src/features/library/infrastructure/blueprints/commerce/ProductDetailsBlueprint.ts +290 -290
  488. package/src/features/library/infrastructure/blueprints/content/ReviewsBlueprint.ts +392 -392
  489. package/src/features/library/infrastructure/blueprints/onboarding/OnboardingWizardBlueprint.ts +344 -344
  490. package/src/features/library/infrastructure/blueprints/utility/CanvasBlueprint.ts +419 -419
  491. package/src/features/library/infrastructure/blueprints/utility/CookieConsentBlueprint.ts +195 -195
  492. package/src/features/library/infrastructure/blueprints/utility/NotFoundBlueprint.ts +86 -86
  493. package/src/features/library/infrastructure/blueprints/utility/SearchPaletteBlueprint.ts +192 -192
  494. package/src/features/library/infrastructure/blueprints/utility/StoreLocatorBlueprint.ts +221 -221
  495. package/src/features/library/infrastructure/blueprints/utility/TaskBoardBlueprint.ts +196 -196
  496. package/src/features/maturity/application/use-cases/ScoreFeature.ts +7 -7
  497. package/src/features/maturity/domain/MaturityReport.ts +70 -70
  498. package/src/features/maturity/domain/MaturityScorer.ts +1001 -985
  499. package/src/features/maturity/presentation/components/MaturityPanel.svelte +376 -372
  500. package/src/features/mcp-tools/application/tools/dryRunSimulate.ts +24 -24
  501. package/src/features/mcp-tools/application/tools/findStateReferences.ts +19 -19
  502. package/src/features/mcp-tools/application/tools/generateTypes.ts +0 -1
  503. package/src/features/mcp-tools/application/tools/getAction.ts +165 -165
  504. package/src/features/mcp-tools/application/tools/getFeature.ts +5 -5
  505. package/src/features/mcp-tools/application/tools/getFeatureIndex.ts +79 -79
  506. package/src/features/mcp-tools/application/tools/getNeighborhood.ts +319 -319
  507. package/src/features/mcp-tools/application/tools/getSurface.ts +86 -86
  508. package/src/features/mcp-tools/application/tools/index.ts +56 -56
  509. package/src/features/mcp-tools/application/tools/listActions.ts +49 -49
  510. package/src/features/mcp-tools/application/tools/listFeatures.ts +7 -7
  511. package/src/features/mcp-tools/application/tools/scoreFeature.ts +153 -153
  512. package/src/features/projects/application/ports/ProjectRepository.ts +14 -14
  513. package/src/features/projects/application/use-cases/AddFeatureToProject.ts +23 -23
  514. package/src/features/projects/application/use-cases/CreateProject.ts +16 -16
  515. package/src/features/projects/application/use-cases/FindProjectContainingFeature.ts +23 -23
  516. package/src/features/projects/application/use-cases/GetProjectAggregate.ts +131 -131
  517. package/src/features/projects/application/use-cases/ImportProjectBundle.ts +45 -0
  518. package/src/features/projects/application/use-cases/MoveFeatureInProject.ts +36 -36
  519. package/src/features/projects/application/use-cases/RemoveFeatureFromProject.ts +23 -23
  520. package/src/features/projects/domain/entities/Project.ts +12 -0
  521. package/src/features/projects/domain/services/InheritedFromProject.ts +130 -130
  522. package/src/features/projects/infrastructure/persistence/JsonFolderProjectRepository.ts +9 -0
  523. package/src/features/projects/presentation/components/ProjectCard.svelte +27 -8
  524. package/src/features/projects/presentation/components/ProjectEditor.svelte +17 -20
  525. package/src/features/projects/presentation/components/ProjectFeaturesPanel.svelte +433 -433
  526. package/src/features/projects/presentation/components/ProjectsIndex.svelte +54 -10
  527. package/src/features/projects/presentation/stores/projectContextStore.svelte.ts +170 -170
  528. package/src/features/projects/presentation/stores/projectFeaturesStore.svelte.ts +114 -114
  529. package/src/features/projects/presentation/stores/projectStore.svelte.ts +265 -266
  530. package/src/features/projects/presentation/stores/projectsStore.svelte.ts +134 -134
  531. package/src/features/simulator/application/use-cases/RunScenarios.ts +12 -0
  532. package/src/features/simulator/application/use-cases/SimulateAction.ts +47 -47
  533. package/src/features/simulator/domain/SimulationResult.ts +79 -79
  534. package/src/features/simulator/domain/SimulatorEngine.ts +43 -9
  535. package/src/features/simulator/domain/StateExplorer.ts +369 -0
  536. package/src/features/simulator/domain/SurfaceReachability.ts +130 -0
  537. package/src/features/simulator/presentation/components/ParameterInputs.svelte +277 -277
  538. package/src/features/simulator/presentation/components/PersonaPicker.svelte +52 -52
  539. package/src/features/simulator/presentation/components/ScenarioPicker.svelte +42 -45
  540. package/src/features/simulator/presentation/components/SidePanel.svelte +170 -170
  541. package/src/features/simulator/presentation/components/SimulationResultView.svelte +394 -394
  542. package/src/features/simulator/presentation/components/SimulatorPanel.svelte +293 -293
  543. package/src/features/simulator/presentation/components/StateInspector.svelte +101 -101
  544. package/src/features/simulator/presentation/stores/simulatorStore.svelte.ts +268 -268
  545. package/src/features/tutorial/presentation/components/CodeBlock.svelte +5 -1
  546. package/src/features/verification/application/ports/BehavioralIndexReader.ts +12 -0
  547. package/src/features/verification/application/use-cases/VerifyFeatures.ts +151 -0
  548. package/src/features/verification/domain/DriftReport.ts +37 -0
  549. package/src/features/verification/domain/EventCoherenceReport.ts +27 -0
  550. package/src/features/verification/domain/IndexedImplementation.ts +27 -0
  551. package/src/features/verification/domain/VerificationReport.ts +59 -0
  552. package/src/features/verification/domain/VerificationThresholds.ts +52 -0
  553. package/src/features/verification/domain/VerificationVerdict.ts +43 -0
  554. package/src/features/verification/domain/aggregateVerdict.ts +244 -0
  555. package/src/features/verification/domain/analyzeEventCoherence.ts +43 -0
  556. package/src/features/verification/domain/detectDrift.ts +166 -0
  557. package/src/features/verification/domain/verifiedCoverage.ts +37 -0
  558. package/src/features/verification/infrastructure/persistence/FileBehavioralIndexReader.ts +81 -0
  559. package/src/features/verification/infrastructure/persistence/StaticBehavioralIndexReader.ts +15 -0
  560. package/src/features/verification/presentation/components/VerifyPanel.svelte +74 -0
  561. package/src/features/verification/presentation/stores/verificationStore.svelte.ts +64 -0
  562. package/src/lib/server/openLocalDirectory.ts +40 -0
  563. package/src/lib/server/searchIndex.ts +161 -0
  564. package/src/lib/server/snapshotRepository.ts +37 -37
  565. package/src/lib/server/sync/YDocManager.ts +391 -391
  566. package/src/lib/server/sync/historyStore.ts +276 -276
  567. package/src/lib/server/sync/wsServer.ts +1 -1
  568. package/src/lib/sync/protocol.ts +147 -147
  569. package/src/lib/sync/roomId.ts +33 -33
  570. package/src/routes/+layout.svelte +104 -0
  571. package/src/routes/api/domains/[id]/+server.ts +7 -3
  572. package/src/routes/api/projects/[id]/+server.ts +14 -4
  573. package/src/routes/api/projects/import/+server.ts +16 -38
  574. package/src/routes/api/search-index/+server.ts +16 -0
  575. package/src/routes/api/snapshots/[id]/+server.ts +56 -44
  576. package/src/routes/api/snapshots/[id]/implementation-status/+server.ts +13 -13
  577. package/src/routes/api/snapshots/[id]/verify/+server.ts +37 -0
  578. package/src/routes/api/sync/reload/+server.ts +157 -157
  579. package/src/routes/api/system/hub-directory/+server.ts +24 -0
  580. package/src/routes/features/+page.svelte +484 -484
  581. package/src/routes/features/[id]/+page.svelte +55 -49
  582. package/src/routes/features/[id]/graph/+page.svelte +5 -0
  583. package/src/routes/features/[id]/verify/+page.svelte +89 -0
  584. package/src/routes/mcp/+page.svelte +16 -1
  585. package/src/routes/projects/[id]/+page.svelte +70 -70
  586. package/src/routes/tutorial/+page.svelte +3 -2
  587. package/src/shared/infrastructure/browserContainer.ts +61 -61
  588. package/src/shared/presentation/components/KebabMenu.svelte +95 -0
  589. package/src/shared/presentation/components/MenuItem.svelte +29 -0
  590. package/vite.config.ts +47 -47
  591. package/build/client/_app/immutable/assets/0.DSctqr5I.css +0 -1
  592. package/build/client/_app/immutable/assets/0.DSctqr5I.css.br +0 -0
  593. package/build/client/_app/immutable/assets/0.DSctqr5I.css.gz +0 -0
  594. package/build/client/_app/immutable/assets/11.nv0I59TU.css.gz +0 -0
  595. package/build/client/_app/immutable/chunks/9nXQ5qrY2.js +0 -1
  596. package/build/client/_app/immutable/chunks/9nXQ5qrY2.js.br +0 -0
  597. package/build/client/_app/immutable/chunks/9nXQ5qrY2.js.gz +0 -0
  598. package/build/client/_app/immutable/chunks/B439_FLv.js.br +0 -0
  599. package/build/client/_app/immutable/chunks/B439_FLv.js.gz +0 -0
  600. package/build/client/_app/immutable/chunks/BCEY79Dw.js +0 -1
  601. package/build/client/_app/immutable/chunks/BCEY79Dw.js.br +0 -2
  602. package/build/client/_app/immutable/chunks/BCEY79Dw.js.gz +0 -0
  603. package/build/client/_app/immutable/chunks/BOrLmFwJ.js.br +0 -0
  604. package/build/client/_app/immutable/chunks/BOrLmFwJ.js.gz +0 -0
  605. package/build/client/_app/immutable/chunks/BYIrIC5L.js +0 -1
  606. package/build/client/_app/immutable/chunks/BYIrIC5L.js.br +0 -0
  607. package/build/client/_app/immutable/chunks/BYIrIC5L.js.gz +0 -0
  608. package/build/client/_app/immutable/chunks/B_9TWPrx2.js.br +0 -0
  609. package/build/client/_app/immutable/chunks/B_9TWPrx2.js.gz +0 -0
  610. package/build/client/_app/immutable/chunks/BfMYiIUi.js.br +0 -0
  611. package/build/client/_app/immutable/chunks/BfMYiIUi.js.gz +0 -0
  612. package/build/client/_app/immutable/chunks/Bp2_Vghh.js +0 -1
  613. package/build/client/_app/immutable/chunks/Bp2_Vghh.js.br +0 -0
  614. package/build/client/_app/immutable/chunks/Bp2_Vghh.js.gz +0 -0
  615. package/build/client/_app/immutable/chunks/Bp8HpEPe2.js +0 -4
  616. package/build/client/_app/immutable/chunks/Bp8HpEPe2.js.br +0 -0
  617. package/build/client/_app/immutable/chunks/Bp8HpEPe2.js.gz +0 -0
  618. package/build/client/_app/immutable/chunks/BvOhVtZg.js +0 -1
  619. package/build/client/_app/immutable/chunks/BvOhVtZg.js.br +0 -1
  620. package/build/client/_app/immutable/chunks/BvOhVtZg.js.gz +0 -0
  621. package/build/client/_app/immutable/chunks/C8rRKIXT.js +0 -1
  622. package/build/client/_app/immutable/chunks/C8rRKIXT.js.br +0 -0
  623. package/build/client/_app/immutable/chunks/C8rRKIXT.js.gz +0 -0
  624. package/build/client/_app/immutable/chunks/CJjJLwzv2.js +0 -1
  625. package/build/client/_app/immutable/chunks/CJjJLwzv2.js.br +0 -0
  626. package/build/client/_app/immutable/chunks/CJjJLwzv2.js.gz +0 -0
  627. package/build/client/_app/immutable/chunks/CY3em1ma2.js +0 -1
  628. package/build/client/_app/immutable/chunks/CY3em1ma2.js.br +0 -0
  629. package/build/client/_app/immutable/chunks/CY3em1ma2.js.gz +0 -0
  630. package/build/client/_app/immutable/chunks/CgdRZPgI.js +0 -1
  631. package/build/client/_app/immutable/chunks/CgdRZPgI.js.br +0 -0
  632. package/build/client/_app/immutable/chunks/CgdRZPgI.js.gz +0 -0
  633. package/build/client/_app/immutable/chunks/CxyLMlpt2.js.br +0 -0
  634. package/build/client/_app/immutable/chunks/CxyLMlpt2.js.gz +0 -0
  635. package/build/client/_app/immutable/chunks/D6jhrpTg.js +0 -1
  636. package/build/client/_app/immutable/chunks/D6jhrpTg.js.br +0 -0
  637. package/build/client/_app/immutable/chunks/D6jhrpTg.js.gz +0 -0
  638. package/build/client/_app/immutable/chunks/D8YEa1po.js +0 -1
  639. package/build/client/_app/immutable/chunks/D8YEa1po.js.br +0 -0
  640. package/build/client/_app/immutable/chunks/D8YEa1po.js.gz +0 -0
  641. package/build/client/_app/immutable/chunks/D9dKmajw.js +0 -1
  642. package/build/client/_app/immutable/chunks/D9dKmajw.js.br +0 -0
  643. package/build/client/_app/immutable/chunks/D9dKmajw.js.gz +0 -0
  644. package/build/client/_app/immutable/chunks/DKgYpi6_.js +0 -1
  645. package/build/client/_app/immutable/chunks/DKgYpi6_.js.br +0 -0
  646. package/build/client/_app/immutable/chunks/DKgYpi6_.js.gz +0 -0
  647. package/build/client/_app/immutable/chunks/Dg0acPpT.js +0 -1
  648. package/build/client/_app/immutable/chunks/Dg0acPpT.js.br +0 -0
  649. package/build/client/_app/immutable/chunks/Dg0acPpT.js.gz +0 -0
  650. package/build/client/_app/immutable/chunks/DkxwAIfJ2.js.br +0 -0
  651. package/build/client/_app/immutable/chunks/DkxwAIfJ2.js.gz +0 -0
  652. package/build/client/_app/immutable/chunks/HKLi1Yz3.js +0 -1
  653. package/build/client/_app/immutable/chunks/HKLi1Yz3.js.br +0 -0
  654. package/build/client/_app/immutable/chunks/HKLi1Yz3.js.gz +0 -0
  655. package/build/client/_app/immutable/chunks/N7PXjlRH.js +0 -1
  656. package/build/client/_app/immutable/chunks/N7PXjlRH.js.br +0 -0
  657. package/build/client/_app/immutable/chunks/N7PXjlRH.js.gz +0 -0
  658. package/build/client/_app/immutable/chunks/OJscNS3T.js +0 -1
  659. package/build/client/_app/immutable/chunks/OJscNS3T.js.br +0 -0
  660. package/build/client/_app/immutable/chunks/OJscNS3T.js.gz +0 -0
  661. package/build/client/_app/immutable/chunks/U9p9CtKG2.js +0 -2
  662. package/build/client/_app/immutable/chunks/U9p9CtKG2.js.br +0 -0
  663. package/build/client/_app/immutable/chunks/U9p9CtKG2.js.gz +0 -0
  664. package/build/client/_app/immutable/chunks/hpWJNn0t2.js +0 -2
  665. package/build/client/_app/immutable/chunks/hpWJNn0t2.js.br +0 -0
  666. package/build/client/_app/immutable/chunks/hpWJNn0t2.js.gz +0 -0
  667. package/build/client/_app/immutable/entry/app.Cd4S3giu.js +0 -2
  668. package/build/client/_app/immutable/entry/app.Cd4S3giu.js.br +0 -0
  669. package/build/client/_app/immutable/entry/app.Cd4S3giu.js.gz +0 -0
  670. package/build/client/_app/immutable/entry/start.C3xXQVkq.js +0 -1
  671. package/build/client/_app/immutable/entry/start.C3xXQVkq.js.br +0 -0
  672. package/build/client/_app/immutable/entry/start.C3xXQVkq.js.gz +0 -0
  673. package/build/client/_app/immutable/nodes/0.dIOlQ-0y.js +0 -4
  674. package/build/client/_app/immutable/nodes/0.dIOlQ-0y.js.br +0 -0
  675. package/build/client/_app/immutable/nodes/0.dIOlQ-0y.js.gz +0 -0
  676. package/build/client/_app/immutable/nodes/1.Dyte3Ggf.js.br +0 -2
  677. package/build/client/_app/immutable/nodes/1.Dyte3Ggf.js.gz +0 -0
  678. package/build/client/_app/immutable/nodes/10.ivxAosDg.js +0 -2
  679. package/build/client/_app/immutable/nodes/10.ivxAosDg.js.br +0 -0
  680. package/build/client/_app/immutable/nodes/10.ivxAosDg.js.gz +0 -0
  681. package/build/client/_app/immutable/nodes/11.wvMfJKC2.js.br +0 -0
  682. package/build/client/_app/immutable/nodes/11.wvMfJKC2.js.gz +0 -0
  683. package/build/client/_app/immutable/nodes/2.CmPPom9Z.js.br +0 -0
  684. package/build/client/_app/immutable/nodes/2.CmPPom9Z.js.gz +0 -0
  685. package/build/client/_app/immutable/nodes/3.D-iCGCEx.js +0 -1
  686. package/build/client/_app/immutable/nodes/3.D-iCGCEx.js.br +0 -0
  687. package/build/client/_app/immutable/nodes/3.D-iCGCEx.js.gz +0 -0
  688. package/build/client/_app/immutable/nodes/4.DbfAvO8Z.js +0 -3
  689. package/build/client/_app/immutable/nodes/4.DbfAvO8Z.js.br +0 -0
  690. package/build/client/_app/immutable/nodes/4.DbfAvO8Z.js.gz +0 -0
  691. package/build/client/_app/immutable/nodes/5.CC5Q7lVw.js +0 -42
  692. package/build/client/_app/immutable/nodes/5.CC5Q7lVw.js.br +0 -0
  693. package/build/client/_app/immutable/nodes/5.CC5Q7lVw.js.gz +0 -0
  694. package/build/client/_app/immutable/nodes/6.CHIjlzpO.js +0 -1
  695. package/build/client/_app/immutable/nodes/6.CHIjlzpO.js.br +0 -0
  696. package/build/client/_app/immutable/nodes/6.CHIjlzpO.js.gz +0 -0
  697. package/build/client/_app/immutable/nodes/7.Ejs18ZUc.js +0 -5
  698. package/build/client/_app/immutable/nodes/7.Ejs18ZUc.js.br +0 -0
  699. package/build/client/_app/immutable/nodes/7.Ejs18ZUc.js.gz +0 -0
  700. package/build/client/_app/immutable/nodes/8.B-HweAc8.js.br +0 -0
  701. package/build/client/_app/immutable/nodes/8.B-HweAc8.js.gz +0 -0
  702. package/build/client/_app/immutable/nodes/9.CKPeM6tx.js +0 -5
  703. package/build/client/_app/immutable/nodes/9.CKPeM6tx.js.br +0 -0
  704. package/build/client/_app/immutable/nodes/9.CKPeM6tx.js.gz +0 -0
  705. package/build/server/chunks/0-Co8kcANG.js +0 -15
  706. package/build/server/chunks/0-Co8kcANG.js.map +0 -1
  707. package/build/server/chunks/1-BSUItTig.js +0 -9
  708. package/build/server/chunks/10-BygvxrZp.js +0 -9
  709. package/build/server/chunks/10-BygvxrZp.js.map +0 -1
  710. package/build/server/chunks/11-DRx0tRx2.js +0 -9
  711. package/build/server/chunks/11-DRx0tRx2.js.map +0 -1
  712. package/build/server/chunks/2-BQT3m1vc.js +0 -9
  713. package/build/server/chunks/2-BQT3m1vc.js.map +0 -1
  714. package/build/server/chunks/3-DPZ9BquJ.js +0 -16
  715. package/build/server/chunks/3-DPZ9BquJ.js.map +0 -1
  716. package/build/server/chunks/4-DHo47YX6.js +0 -16
  717. package/build/server/chunks/4-DHo47YX6.js.map +0 -1
  718. package/build/server/chunks/5-Cp9evBAG.js +0 -9
  719. package/build/server/chunks/5-Cp9evBAG.js.map +0 -1
  720. package/build/server/chunks/6-DiBq3bOV.js +0 -9
  721. package/build/server/chunks/6-DiBq3bOV.js.map +0 -1
  722. package/build/server/chunks/7-C4hmS0dG.js +0 -9
  723. package/build/server/chunks/8-CFFuDzBC.js +0 -9
  724. package/build/server/chunks/8-CFFuDzBC.js.map +0 -1
  725. package/build/server/chunks/9-nhhKZJrs.js +0 -9
  726. package/build/server/chunks/9-nhhKZJrs.js.map +0 -1
  727. package/build/server/chunks/BehaviorGraph-m5kYj5HH.js.map +0 -1
  728. package/build/server/chunks/FeatureTransforms-UWDHmWEg.js.map +0 -1
  729. package/build/server/chunks/FeatureValidator-B8qEjAUW.js.map +0 -1
  730. package/build/server/chunks/ManageTagsDialog-DBxA3tM2.js.map +0 -1
  731. package/build/server/chunks/ProjectsIndex-DUVJ3hyL.js.map +0 -1
  732. package/build/server/chunks/RenameTag-BuWLMl1m.js.map +0 -1
  733. package/build/server/chunks/TagDotStrip-B1XQ0m0Y.js.map +0 -1
  734. package/build/server/chunks/TagPalette-CtMNYCmu.js.map +0 -1
  735. package/build/server/chunks/TransitionCatalog-B8zHs-2E.js.map +0 -1
  736. package/build/server/chunks/_layout.svelte-CLTmk0xU.js.map +0 -1
  737. package/build/server/chunks/_page.svelte-B1nG3PKn.js +0 -29
  738. package/build/server/chunks/_page.svelte-B1s7jxaQ.js.map +0 -1
  739. package/build/server/chunks/_page.svelte-BW_nbAAH.js.map +0 -1
  740. package/build/server/chunks/_page.svelte-Caq7J0jU.js.map +0 -1
  741. package/build/server/chunks/_page.svelte-Cham-dsM.js +0 -29
  742. package/build/server/chunks/_page.svelte-Dhwjwph_.js.map +0 -1
  743. package/build/server/chunks/_page.svelte-NVT2dzpG.js.map +0 -1
  744. package/build/server/chunks/_page.svelte-Z_kK2lHY.js.map +0 -1
  745. package/build/server/chunks/_server.ts-0uNTZKwF.js.map +0 -1
  746. package/build/server/chunks/_server.ts-DcZPhyhK.js +0 -59
  747. package/build/server/chunks/_server.ts-DcZPhyhK.js.map +0 -1
  748. package/build/server/chunks/_server.ts-Dy5zQHe2.js.map +0 -1
  749. package/build/server/chunks/_server.ts-YnfXkeMJ.js.map +0 -1
  750. package/build/server/chunks/_server.ts-vcaqdwxS.js.map +0 -1
  751. package/build/server/chunks/browserContainer-CNX7ANld.js.map +0 -1
  752. package/build/server/chunks/builderModeStore.svelte-BpRIU_zP.js.map +0 -1
  753. package/build/server/chunks/featureStore.svelte-DIYgPBVm.js.map +0 -1
  754. package/build/server/chunks/featuresStore.svelte-DR1gYZyu.js +0 -98
  755. package/build/server/chunks/featuresStore.svelte-DR1gYZyu.js.map +0 -1
  756. package/build/server/chunks/identityStore.svelte-IIvW2_3b.js +0 -59
  757. package/build/server/chunks/identityStore.svelte-IIvW2_3b.js.map +0 -1
  758. package/build/server/chunks/projectFeaturesStore.svelte-2o-72_vr.js.map +0 -1
  759. package/build/server/chunks/projectsStore.svelte-QDz5PchX.js.map +0 -1
  760. package/build/server/chunks/reconcile-B5xqb6-s.js.map +0 -1
  761. package/build/server/chunks/snapshotRepository-BPXCjX92.js.map +0 -1
  762. package/build/server/chunks/syncBridge-BwXzPdjJ.js.map +0 -1
  763. package/src/features/implementation-queue/presentation/components/QueuePanel.svelte +0 -204
  764. package/src/features/implementation-queue/presentation/stores/queueStore.svelte.ts +0 -143
  765. /package/build/client/_app/immutable/assets/{11.nv0I59TU.css → 12.nv0I59TU.css} +0 -0
  766. /package/build/client/_app/immutable/assets/{11.nv0I59TU.css.br → 12.nv0I59TU.css.br} +0 -0
@@ -0,0 +1,71 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
2
+ import { dirname, isAbsolute, join, resolve } from 'node:path';
3
+ import pc from 'picocolors';
4
+ import { log } from '../util/log';
5
+
6
+ export type CiOptions = {
7
+ readonly cwd?: string;
8
+ /** Output path. Defaults to .github/workflows/unspaghettit.yml. */
9
+ readonly out?: string;
10
+ /** Run bounded model checking in the generated workflow (slower, deeper). */
11
+ readonly modelCheck?: boolean;
12
+ readonly dryRun?: boolean;
13
+ readonly force?: boolean;
14
+ };
15
+
16
+ const workflowYaml = (modelCheck: boolean): string => {
17
+ const checkCmd = modelCheck ? 'unspa check --model-check' : 'unspa check';
18
+ return `# Generated by \`unspa ci\`. Verifies the Unspaghettit spec on every push / PR:
19
+ # scenarios as executable tests, maturity, surface reachability, spec→code drift,
20
+ # cross-feature event coherence${modelCheck ? ', and bounded model checking (invariant + liveness counterexamples)' : ''}.
21
+ # Requires the behavior model to travel with the repo — run \`unspa init --local\`
22
+ # so \`unspa/\` is committed. Tighten the gate with flags, e.g.
23
+ # \`unspa check --min-maturity 80 --fail-on-drift\`.
24
+ name: unspaghettit
25
+ on:
26
+ push:
27
+ branches: [main]
28
+ pull_request:
29
+ jobs:
30
+ verify:
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+ - uses: actions/setup-node@v4
35
+ with:
36
+ node-version: '20'
37
+ - run: npm install -g unspaghettit
38
+ - run: ${checkCmd}
39
+ `;
40
+ };
41
+
42
+ export const runCiCommand = async (options: CiOptions = {}): Promise<number> => {
43
+ const cwd = options.cwd ?? process.cwd();
44
+ const yaml = workflowYaml(options.modelCheck === true);
45
+
46
+ if (options.dryRun) {
47
+ process.stdout.write(`${yaml}`);
48
+ return 0;
49
+ }
50
+
51
+ const outPath = options.out
52
+ ? isAbsolute(options.out)
53
+ ? options.out
54
+ : resolve(cwd, options.out)
55
+ : resolve(cwd, join('.github', 'workflows', 'unspaghettit.yml'));
56
+
57
+ if (existsSync(outPath) && options.force !== true) {
58
+ log.err(`Refusing to overwrite existing file: ${outPath}`);
59
+ log.dim('Re-run with --force to overwrite, or pass --out <path> to write elsewhere.');
60
+ return 1;
61
+ }
62
+
63
+ const outDir = dirname(outPath);
64
+ if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
65
+ writeFileSync(outPath, yaml, 'utf8');
66
+
67
+ log.ok(`Wrote ${pc.cyan(outPath)}`);
68
+ log.dim('Commit it (and the unspa/ folder) so CI verifies the spec on every push / PR.');
69
+ log.dim('The model must travel with the repo: `unspa init --local` if you haven\'t already.');
70
+ return 0;
71
+ };
@@ -0,0 +1,112 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import pc from 'picocolors';
3
+ import { parseScenarioResults, summarizeByAction } from '../scenarios/results';
4
+ import { linkPath } from '../util/link';
5
+ import { readJson, writeJson } from '../util/json';
6
+ import { log } from '../util/log';
7
+
8
+ export type CoverageIngestOptions = {
9
+ readonly file: string;
10
+ readonly cwd?: string;
11
+ /** ISO timestamp to stamp (injected for tests; defaults to now). */
12
+ readonly now?: string;
13
+ readonly dryRun?: boolean;
14
+ };
15
+
16
+ type IndexEntry = Record<string, unknown>;
17
+ type Link = { index?: Record<string, IndexEntry> } & Record<string, unknown>;
18
+
19
+ /**
20
+ * Promote indexed actions from "claimed implemented" to "proven against the
21
+ * spec" by reading a Vitest JSON report of the generated scenario spec
22
+ * (`vitest run --reporter=json --outputFile=<file>`). An action whose every
23
+ * scenario passed gets `verifiedAt` stamped on its `.unspa.json` entry; one
24
+ * that now fails has a stale `verifiedAt` cleared. Recording only — the gate
25
+ * is `unspa check --min-verified`.
26
+ */
27
+ export const runCoverageIngestCommand = async (
28
+ options: CoverageIngestOptions
29
+ ): Promise<number> => {
30
+ const cwd = options.cwd ?? process.cwd();
31
+
32
+ if (!existsSync(options.file)) {
33
+ log.err(`Results file not found: ${options.file}`);
34
+ log.dim('Run: vitest run <spec> --reporter=json --outputFile=<file>, then ingest that file.');
35
+ return 1;
36
+ }
37
+
38
+ let report: unknown;
39
+ try {
40
+ report = JSON.parse(readFileSync(options.file, 'utf8'));
41
+ } catch (e) {
42
+ log.err(`Could not parse ${options.file} as JSON: ${(e as Error).message}`);
43
+ return 1;
44
+ }
45
+
46
+ const perAction = summarizeByAction(parseScenarioResults(report));
47
+ if (perAction.length === 0) {
48
+ log.warn('No unspa-tagged scenario tests found in the report.');
49
+ log.dim('Generate the spec with `unspa scenarios export <featureId>`, then run vitest with --reporter=json.');
50
+ return 0;
51
+ }
52
+
53
+ const path = linkPath(cwd);
54
+ const link = readJson<Link>(path);
55
+ if (!link) {
56
+ log.err(`No .unspa.json found at ${cwd}.`);
57
+ log.dim('Link the repo (`unspa link`) and record implementations before ingesting verification.');
58
+ return 1;
59
+ }
60
+ const index = link.index ?? {};
61
+ const stampedAt = options.now ?? new Date().toISOString();
62
+
63
+ let stamped = 0;
64
+ let cleared = 0;
65
+ const unindexed: string[] = [];
66
+
67
+ for (const action of perAction) {
68
+ const key = `action:${action.actionId}`;
69
+ const entry = index[key];
70
+ if (action.verified) {
71
+ if (!entry) {
72
+ unindexed.push(action.actionId);
73
+ continue;
74
+ }
75
+ index[key] = { ...entry, verifiedAt: stampedAt, verifiedScenarios: action.passed };
76
+ stamped += 1;
77
+ } else if (entry && entry.verifiedAt !== undefined) {
78
+ // Was verified, now a scenario fails — the proof is stale, drop it.
79
+ const next = { ...entry };
80
+ delete next.verifiedAt;
81
+ delete next.verifiedScenarios;
82
+ index[key] = next;
83
+ cleared += 1;
84
+ }
85
+ }
86
+
87
+ const verifiedCount = perAction.filter((a) => a.verified).length;
88
+ log.step(`Verified coverage from ${pc.cyan(options.file)}`);
89
+ log.dim(
90
+ `${perAction.length} action(s) tested · ${verifiedCount} fully passing · ${perAction.length - verifiedCount} with failures`
91
+ );
92
+ if (unindexed.length > 0) {
93
+ log.warn(
94
+ `${unindexed.length} passing action(s) aren't in .unspa.json yet — record them (implementation status), then re-ingest to mark them verified.`
95
+ );
96
+ }
97
+
98
+ if (options.dryRun) {
99
+ log.dim('(dry-run; .unspa.json not written)');
100
+ return 0;
101
+ }
102
+ if (stamped === 0 && cleared === 0) {
103
+ log.dim('No indexed actions to update.');
104
+ return 0;
105
+ }
106
+
107
+ await writeJson(path, { ...link, index });
108
+ log.ok(
109
+ `Stamped ${stamped} action(s) verified${cleared > 0 ? `, cleared ${cleared} stale` : ''} in .unspa.json`
110
+ );
111
+ return 0;
112
+ };
@@ -0,0 +1,96 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { dirname, isAbsolute, join, resolve } from 'node:path';
3
+ import pc from 'picocolors';
4
+ import { discoverSnapshotDirectory } from '../../src/features/behavior-model/infrastructure/persistence/snapshot-discovery';
5
+ import { JsonFolderFeatureRepository } from '../../src/features/behavior-model/infrastructure/persistence/JsonFolderFeatureRepository';
6
+ import type { FeatureId } from '../../src/features/behavior-model/domain/value-objects/ids';
7
+ import { generateAdapterStub, type IndexHint } from '../scenarios/adapter-scaffold';
8
+ import { log } from '../util/log';
9
+
10
+ export type ScenariosAdapterOptions = {
11
+ readonly featureId: string;
12
+ readonly cwd?: string;
13
+ /** Output path. Defaults to ./unspa.adapter.ts so the export command's default import resolves. */
14
+ readonly out?: string;
15
+ readonly adapterExport?: string;
16
+ readonly dryRun?: boolean;
17
+ readonly force?: boolean;
18
+ };
19
+
20
+ const EXPERIMENTAL_BANNER = 'experimental — adapter contract may change between minor versions';
21
+
22
+ /** Best-effort read of the behavioral index from `.unspa.json` for impl hints. */
23
+ const readIndex = (cwd: string): Readonly<Record<string, IndexHint>> => {
24
+ try {
25
+ const raw = JSON.parse(readFileSync(join(cwd, '.unspa.json'), 'utf8')) as {
26
+ index?: Record<string, IndexHint>;
27
+ };
28
+ return raw.index ?? {};
29
+ } catch {
30
+ return {};
31
+ }
32
+ };
33
+
34
+ export const runScenariosAdapterCommand = async (
35
+ options: ScenariosAdapterOptions
36
+ ): Promise<number> => {
37
+ const cwd = options.cwd ?? process.cwd();
38
+ log.dim(`(${EXPERIMENTAL_BANNER})`);
39
+ const { directory } = discoverSnapshotDirectory({ cwd });
40
+
41
+ if (!existsSync(directory)) {
42
+ log.err(`No unspa/ folder found at or above ${cwd}.`);
43
+ log.dim('Run `unspa init` first, then add a feature with scenarios.');
44
+ return 1;
45
+ }
46
+
47
+ const repo = new JsonFolderFeatureRepository(directory);
48
+ const feature = await repo.get(options.featureId as FeatureId);
49
+ if (!feature) {
50
+ log.err(`No feature with id "${options.featureId}" in ${directory}.`);
51
+ log.dim('Use `unspa list` (then open a project) or the dashboard to find feature ids.');
52
+ return 1;
53
+ }
54
+
55
+ const { code, actionCount } = generateAdapterStub(feature, {
56
+ index: readIndex(cwd),
57
+ ...(options.adapterExport ? { adapterExportName: options.adapterExport } : {})
58
+ });
59
+
60
+ if (actionCount === 0) {
61
+ log.warn(
62
+ `Feature "${feature.name}" has no scenarios on any action, so the adapter would be empty.`
63
+ );
64
+ log.dim('Author scenarios first, then re-run; the stub mirrors the actions the export tests cover.');
65
+ return 0;
66
+ }
67
+
68
+ if (options.dryRun) {
69
+ process.stdout.write(`${code}\n`);
70
+ log.dim(`(dry-run; ${actionCount} action case${actionCount === 1 ? '' : 's'} would be written)`);
71
+ return 0;
72
+ }
73
+
74
+ const outPath = options.out
75
+ ? isAbsolute(options.out)
76
+ ? options.out
77
+ : resolve(cwd, options.out)
78
+ : resolve(cwd, 'unspa.adapter.ts');
79
+
80
+ if (existsSync(outPath) && options.force !== true) {
81
+ log.err(`Refusing to overwrite existing file: ${outPath}`);
82
+ log.dim('Re-run with --force to overwrite, or pass --out <path> to write elsewhere.');
83
+ return 1;
84
+ }
85
+
86
+ const outDir = dirname(outPath);
87
+ if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
88
+ writeFileSync(outPath, code, 'utf8');
89
+
90
+ log.ok(`Wrote ${pc.cyan(outPath)}`);
91
+ log.dim(`${actionCount} action case${actionCount === 1 ? '' : 's'} to fill in.`);
92
+ log.dim(
93
+ `Next: implement the cases, then \`unspa scenarios export ${feature.id}\` and run vitest.`
94
+ );
95
+ return 0;
96
+ };
@@ -0,0 +1,99 @@
1
+ import type { Feature } from '../../src/features/behavior-model/domain/entities/Feature';
2
+
3
+ /**
4
+ * Scaffolds the user-authored adapter that `unspa scenarios export` calls. The
5
+ * export command generates the Vitest spec from a feature's scenarios; the only
6
+ * thing the human still had to write by hand was this adapter. This generates
7
+ * its skeleton — one `case` per scenario-bearing action, pre-seeded with the
8
+ * implementation location recorded in `.unspa.json` (when known) — so the loop
9
+ * from spec to a passing/failing code-vs-spec test is "fill the TODOs", not
10
+ * "write the bridge from scratch".
11
+ */
12
+
13
+ export type IndexHint = {
14
+ readonly file?: string;
15
+ readonly line?: number;
16
+ readonly signature?: string;
17
+ };
18
+
19
+ export type AdapterScaffoldOptions = {
20
+ /** Named export for the adapter. Defaults to `adapter` (matches the export command's default). */
21
+ readonly adapterExportName?: string;
22
+ /** Behavioral index (`.unspa.json` `index`) for implementation-location hints, keyed `action:<id>`. */
23
+ readonly index?: Readonly<Record<string, IndexHint>>;
24
+ };
25
+
26
+ export type AdapterScaffoldResult = {
27
+ readonly code: string;
28
+ /** Number of actions that got a case (those carrying at least one scenario). */
29
+ readonly actionCount: number;
30
+ };
31
+
32
+ const BANNER = `/**
33
+ * GENERATED ADAPTER STUB — \`unspa scenarios adapter\`.
34
+ *
35
+ * EXPERIMENTAL: the adapter contract (UnspaAdapter / AdapterInvocation /
36
+ * AdapterResult) may change between minor versions.
37
+ *
38
+ * Fill each case: drive your real implementation from input.initialState +
39
+ * input.parameters and return its actual outcome { status, finalState }. Then
40
+ * run \`unspa scenarios export <featureId>\` and \`vitest\` — the generated tests
41
+ * assert your implementation against the same oracle the simulator uses, so
42
+ * spec↔code drift fails loudly.
43
+ */`;
44
+
45
+ const hintComment = (hint: IndexHint | undefined): string => {
46
+ if (!hint?.file) return ' // impl: (not recorded in .unspa.json yet)';
47
+ const loc = `${hint.file}${hint.line ? `:${hint.line}` : ''}`;
48
+ return ` // impl: ${loc}${hint.signature ? ` — ${hint.signature}` : ''}`;
49
+ };
50
+
51
+ export const generateAdapterStub = (
52
+ feature: Feature,
53
+ options: AdapterScaffoldOptions = {}
54
+ ): AdapterScaffoldResult => {
55
+ const exportName = options.adapterExportName ?? 'adapter';
56
+ const index = options.index ?? {};
57
+
58
+ const cases: string[] = [];
59
+ for (const surface of feature.surfaces) {
60
+ for (const action of surface.actions) {
61
+ // The export command only emits tests for scenario-bearing actions, so
62
+ // those are exactly the cases the adapter needs.
63
+ if ((action.scenarios ?? []).length === 0) continue;
64
+ cases.push(
65
+ [
66
+ ` // ${surface.name} › ${action.name}`,
67
+ hintComment(index[`action:${action.id}`]),
68
+ ` case ${JSON.stringify(String(action.id))}: {`,
69
+ ` // TODO: call your implementation; return only the paths the scenario asserts.`,
70
+ ` throw new Error('Adapter not implemented: ${action.name.replace(/'/g, "\\'")} (' + input.actionId + ')');`,
71
+ ` }`
72
+ ].join('\n')
73
+ );
74
+ }
75
+ }
76
+
77
+ const body =
78
+ cases.length > 0 ? cases.join('\n\n') : ' // (no scenario-bearing actions yet)';
79
+
80
+ const code = `${BANNER}
81
+ import type {
82
+ AdapterInvocation,
83
+ AdapterResult,
84
+ UnspaAdapter
85
+ } from 'unspaghettit/cli/scenarios';
86
+
87
+ export const ${exportName}: UnspaAdapter = {
88
+ async invoke(input: AdapterInvocation): Promise<AdapterResult> {
89
+ switch (input.actionId) {
90
+ ${body}
91
+ default:
92
+ throw new Error('No adapter case for action ' + input.actionName + ' (' + input.actionId + ')');
93
+ }
94
+ }
95
+ };
96
+ `;
97
+
98
+ return { code, actionCount: cases.length };
99
+ };
@@ -17,6 +17,7 @@ import {
17
17
  import { mergeSnapshotWithDefaults } from '../../src/features/behavior-model/domain/services/StateSnapshot';
18
18
  import { isExpression } from '../../src/features/behavior-model/domain/value-objects/Expression';
19
19
  import { simulate } from '../../src/features/simulator/domain/SimulatorEngine';
20
+ import { scenarioTitleToken } from './results';
20
21
 
21
22
  export type CodegenOptions = {
22
23
  /**
@@ -206,8 +207,13 @@ const renderScenarioBlock = (
206
207
  }
207
208
  }
208
209
 
210
+ const titleToken = scenarioTitleToken(
211
+ String(surface.id),
212
+ String(action.id),
213
+ String(scenario.id)
214
+ );
209
215
  const code = [
210
- ` it(${tsString(scenario.name)}, async () => {`,
216
+ ` it(${tsString(`${titleToken} ${scenario.name}`)}, async () => {`,
211
217
  driftBanner.trimEnd(),
212
218
  ` const initialState = ${jsonLiteral(initialState)};`,
213
219
  ` const parameters = ${jsonLiteral(parameters)};`,
@@ -0,0 +1,85 @@
1
+ /**
2
+ * The bridge that turns a real `vitest run` into verified spec coverage.
3
+ *
4
+ * The generated scenario spec prefixes each `it(...)` title with a machine
5
+ * token — `[unspa:<surfaceId>:<actionId>:<scenarioId>]` — so a standard Vitest
6
+ * JSON report (`vitest run --reporter=json --outputFile=...`) can be parsed
7
+ * back into "which scenarios the IMPLEMENTATION actually passed", with no
8
+ * custom reporter or config. `unspa coverage ingest` reads that report and
9
+ * stamps `verifiedAt` on the matching `.unspa.json` entries — promoting an
10
+ * entity from "claimed implemented" to "proven against the spec".
11
+ *
12
+ * Pure + framework-agnostic: the token format lives here once, used by the
13
+ * codegen (to emit) and the ingester (to parse), so the two can't drift.
14
+ */
15
+
16
+ /** Build the title token the codegen prepends to each generated `it(...)`. */
17
+ export const scenarioTitleToken = (
18
+ surfaceId: string,
19
+ actionId: string,
20
+ scenarioId: string
21
+ ): string => `[unspa:${surfaceId}:${actionId}:${scenarioId}]`;
22
+
23
+ const TOKEN = /\[unspa:([^:\]]+):([^:\]]+):([^:\]]+)\]/;
24
+
25
+ export type ScenarioResult = {
26
+ readonly surfaceId: string;
27
+ readonly actionId: string;
28
+ readonly scenarioId: string;
29
+ readonly passed: boolean;
30
+ };
31
+
32
+ /**
33
+ * Parse a Vitest JSON report (Jest-compatible shape) into per-scenario
34
+ * pass/fail. Ignores tests with no unspa token (the user's own tests in the
35
+ * same run). Tolerant of partial shapes — a malformed report yields [].
36
+ */
37
+ export const parseScenarioResults = (raw: unknown): ScenarioResult[] => {
38
+ const root = raw as {
39
+ testResults?: ReadonlyArray<{
40
+ assertionResults?: ReadonlyArray<{
41
+ title?: string;
42
+ fullName?: string;
43
+ status?: string;
44
+ }>;
45
+ }>;
46
+ };
47
+ const out: ScenarioResult[] = [];
48
+ for (const file of root?.testResults ?? []) {
49
+ for (const a of file?.assertionResults ?? []) {
50
+ const match = TOKEN.exec(a.title ?? a.fullName ?? '');
51
+ if (!match) continue;
52
+ const [, surfaceId, actionId, scenarioId] = match;
53
+ if (!surfaceId || !actionId || !scenarioId) continue;
54
+ out.push({ surfaceId, actionId, scenarioId, passed: a.status === 'passed' });
55
+ }
56
+ }
57
+ return out;
58
+ };
59
+
60
+ export type ActionVerification = {
61
+ readonly actionId: string;
62
+ readonly total: number;
63
+ readonly passed: number;
64
+ /** True when the action has at least one scenario result and every one passed. */
65
+ readonly verified: boolean;
66
+ };
67
+
68
+ /** Roll per-scenario results up to per-action: an action is verified iff all its scenarios passed. */
69
+ export const summarizeByAction = (
70
+ results: readonly ScenarioResult[]
71
+ ): readonly ActionVerification[] => {
72
+ const byAction = new Map<string, { total: number; passed: number }>();
73
+ for (const r of results) {
74
+ const acc = byAction.get(r.actionId) ?? { total: 0, passed: 0 };
75
+ acc.total += 1;
76
+ if (r.passed) acc.passed += 1;
77
+ byAction.set(r.actionId, acc);
78
+ }
79
+ return [...byAction.entries()].map(([actionId, { total, passed }]) => ({
80
+ actionId,
81
+ total,
82
+ passed,
83
+ verified: total > 0 && passed === total
84
+ }));
85
+ };
@@ -24,6 +24,8 @@ source code is not annotated.
24
24
  | `get_implementation_gaps` | Authoritative "what is missing/partial/implemented" report. Read this before deciding where to point the user. |
25
25
  | `get_implementation_status` | Detailed sidecar for one feature (or filtered to one action/surface). Shows captured fields, locations, staleness flags. |
26
26
  | `get_spec_gaps` | Spec-depth diagnostics. Critical + recommended to-do list grounded in entities. Catches shallow specs (effect-less actions, stateless surfaces, untested destructive paths, etc.), orthogonal to "is code indexed?". |
27
+ | `get_drift` | Spec→code drift: implementations audited against an OLDER spec than the one now on disk — the `entry.specVersion` vs `feature.updatedAt` comparison, done for you. Returns `stale` (re-audit these), `unversioned` (audited but never stamped), and `orphans` (keys that no longer resolve). The fastest "what silently went stale" read. |
28
+ | `verify` | One gated `pass`/`warn`/`fail` verdict per feature — scenarios + maturity + reachability + bounded model check + drift + cross-feature event coherence. The in-chat form of the `unspa check` CLI. Use to confirm the spec itself is sound before declaring an audit clean. |
27
29
  | `sync_from_index` | After you rewrite `.unspa.json`, the MCP re-reads it, resolves UUIDs, and posts one report per action and per surface. Use this instead of the lower-level `report_implementation_status_batch` unless you need per-entity granularity. |
28
30
  | `report_implementation_status` | Fine-grained: sync ONE action or surface plus its children. Use when you intentionally do not want to push the whole index. |
29
31
 
@@ -66,6 +68,23 @@ source code is not annotated.
66
68
  Resolve every critical gap before declaring the audit clean.
67
69
  Recommended gaps are a defensible backlog.
68
70
 
71
+ 6. **Check for drift, then verify.** Call `get_drift` to find code audited
72
+ against an older spec than the one on disk (a rule changed under an
73
+ implementation you previously mapped) — re-audit the `stale` entries. Then
74
+ `verify` for the one-call verdict: it runs the whole spine (scenarios +
75
+ maturity + reachability + model check + drift + cross-feature event
76
+ coherence + verified coverage) and reports `pass` / `warn` / `fail` per
77
+ check. A clean `verify` (plus zero critical spec gaps) is what "the audit is
78
+ clean" means. The same gate runs headlessly in CI as `unspa check`.
79
+
80
+ 7. **Distinguish claimed from proven.** A `.unspa.json` `{file,line}` entry
81
+ says an entity is *implemented*, not *correct*. To prove it, run the
82
+ feature's scenarios against the real code: `unspa scenarios export` →
83
+ `vitest run --reporter=json` → `unspa coverage ingest <report>`, which
84
+ stamps `verifiedAt` on actions whose scenarios all passed. `verify` reports
85
+ the proven share; `unspa check --min-verified <pct>` gates on it. An honest
86
+ audit reports both: indexed coverage **and** verified coverage.
87
+
69
88
  ## Reading the index correctly
70
89
 
71
90
  `.unspa.json` is keyed `"<entityType>:<id-name-or-path>"` where the
@@ -29,7 +29,9 @@ many Features. Use `add_feature_to_project` to attach.
29
29
  ## The domain in 60 seconds
30
30
 
31
31
  A **Feature** holds `surfaces[]`, `personas[]`, `resources[]`, `entities[]`,
32
- `events[]`, and optional `devContext`, `expectedActions[]`, `nonGoals[]`.
32
+ `events[]`, `featureInvariants[]` (cross-surface safety), `reachabilityGoals[]`
33
+ (liveness: `reachable` / `always_reachable` target states), and optional
34
+ `devContext`, `expectedActions[]`, `nonGoals[]`.
33
35
 
34
36
  A **Surface** is one context (screen, terminal, workflow, canvas, ...) with
35
37
  `stateDefinitions[]`, `actions[]`, `rules[]`, `invariants[]`,
@@ -117,7 +119,10 @@ Atomic state-from-state-and-param write:
117
119
  `remove_surface_rule`, `add_action_invariant`,
118
120
  `update_action_invariant`, `remove_action_invariant`,
119
121
  `add_surface_invariant`, `update_surface_invariant`,
120
- `remove_surface_invariant`, `add_transition`, `update_transition`,
122
+ `remove_surface_invariant`, `add_feature_invariant`,
123
+ `update_feature_invariant`, `remove_feature_invariant`,
124
+ `add_reachability_goal`, `update_reachability_goal`, `remove_reachability_goal`,
125
+ `add_transition`, `update_transition`,
121
126
  `remove_transition`, `add_effect`, `update_effect`, `remove_effect`,
122
127
  `add_event`, `update_event`, `remove_event`, `add_scenario`,
123
128
  `update_scenario`, `remove_scenario`, `add_persona`, `update_persona`,
@@ -126,7 +131,16 @@ Atomic state-from-state-and-param write:
126
131
  `update_entity_field`, `remove_entity_field`,
127
132
  `create_project`, `update_project`, `replace_project`, `delete_project`,
128
133
  `add_feature_to_project`, `remove_feature_from_project`,
129
- `move_feature_in_project`.
134
+ `move_feature_in_project`, `add_project_invariant`,
135
+ `update_project_invariant`, `remove_project_invariant`.
136
+
137
+ **Cross-feature invariants** live on the Project, not a feature:
138
+ `project.projectInvariants` are safety properties spanning member features
139
+ (referencing state paths in different features, which a feature invariant
140
+ can't). Author with `add_project_invariant` / `update_project_invariant` /
141
+ `remove_project_invariant`; the model checker enforces them across the
142
+ project's state. Use a feature invariant when the property is within one
143
+ feature, a project invariant when it spans two or more.
130
144
 
131
145
  Use the granular tools for one-off tweaks. For anything ≥ 2 ops, use
132
146
  `apply_batch`.
@@ -138,6 +152,9 @@ Use the granular tools for one-off tweaks. For anything ≥ 2 ops, use
138
152
  | `get_spec_gaps` | Spec-depth diagnostics. Prioritized critical + recommended gaps. |
139
153
  | `get_implementation_gaps` | Implementation coverage gaps (spec vs. `.unspa.json` index). |
140
154
  | `get_implementation_status` | Detailed per-action / per-surface coverage report. |
155
+ | `model_check` | Bounded state-space exploration: invariant counterexamples (shortest action path), dead actions, deadlocks, unreachable surfaces, reachability-goal results. |
156
+ | `verify` | One gated `pass`/`warn`/`fail` verdict per feature (scenarios + maturity + reachability + model check + drift + event coherence) — the in-chat form of `unspa check`. |
157
+ | `get_drift` | Implementations audited against an older spec than the one now on disk (stale / unversioned / orphan). |
141
158
 
142
159
  ## Workflow
143
160
 
@@ -183,6 +183,34 @@ own key will be reported as missing even when the parent is `implemented`.
183
183
  `get_spec_gaps` to catch shallow specs that *look* covered but lack
184
184
  scenarios, blocking validation rules, etc.
185
185
 
186
+ ## Prove the code matches the spec (close the loop)
187
+
188
+ Recording a `{file, line}` says "implemented", not "correct". To turn the
189
+ feature's scenarios into a real code-vs-spec test:
190
+
191
+ 1. `unspa scenarios adapter <featureId>` — scaffolds `unspa.adapter.ts`, one
192
+ `case` per scenario-bearing action, pre-seeded with the `.unspa.json`
193
+ implementation locations. Fill each `case` so it drives the real code from
194
+ `input.initialState` + `input.parameters` and returns `{ status, finalState }`.
195
+ 2. `unspa scenarios export <featureId>` — generates a Vitest spec whose oracle
196
+ is the simulator's prediction for each scenario.
197
+ 3. Run vitest with the JSON reporter:
198
+ `vitest run <spec> --reporter=json --outputFile=unspa-results.json`. Green
199
+ means the implementation agrees with the spec on every authored scenario; a
200
+ failure is a real spec↔code divergence — fix the code (or the spec, if the
201
+ spec was wrong) and re-run.
202
+ 4. `unspa coverage ingest unspa-results.json` — stamps `verifiedAt` on every
203
+ action whose scenarios all passed (and clears it on a regression), promoting
204
+ those entities from "claimed implemented" to **proven against the spec**.
205
+ 5. CI: `unspa ci` drops a workflow running `unspa check`; add
206
+ `--min-verified <pct>` to require that share of actions be proven, and run
207
+ the generated scenario spec + ingest in the same job so the code is gated
208
+ against the spec on every push.
209
+
210
+ This is the experimental wedge — the adapter contract may shift between minor
211
+ versions. Recording presence in `.unspa.json` (step 5 above) is still the
212
+ baseline; this proves the behavior on top of it.
213
+
186
214
  ## "Don't ask, just build" mode
187
215
 
188
216
  If the user's prompt signals one-shot autonomy ("one pass", "make