unspaghettit 0.2.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.
- package/README.md +56 -18
- package/build/client/_app/immutable/assets/0.DCOD5ne_.css +1 -0
- package/build/client/_app/immutable/assets/0.DCOD5ne_.css.br +0 -0
- package/build/client/_app/immutable/assets/0.DCOD5ne_.css.gz +0 -0
- package/build/client/_app/immutable/assets/12.nv0I59TU.css.gz +0 -0
- package/build/client/_app/immutable/assets/3.B3akUL9A.css.gz +0 -0
- package/build/client/_app/immutable/assets/BehaviorGraph.Bk0xQRZk.css +1 -0
- package/build/client/_app/immutable/assets/BehaviorGraph.Bk0xQRZk.css.br +0 -0
- package/build/client/_app/immutable/assets/BehaviorGraph.Bk0xQRZk.css.gz +0 -0
- package/build/client/_app/immutable/chunks/B3vnQs252.js +1 -0
- package/build/client/_app/immutable/chunks/B3vnQs252.js.br +0 -0
- package/build/client/_app/immutable/chunks/B3vnQs252.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CxyLMlpt2.js → BANF9BhQ2.js} +1 -1
- package/build/client/_app/immutable/chunks/BANF9BhQ2.js.br +0 -0
- package/build/client/_app/immutable/chunks/BANF9BhQ2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BJdTO_n6.js +1 -0
- package/build/client/_app/immutable/chunks/BJdTO_n6.js.br +0 -0
- package/build/client/_app/immutable/chunks/BJdTO_n6.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BPl9BITm.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BQ9GodWX2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bcyn5YUg.js +4 -0
- package/build/client/_app/immutable/chunks/Bcyn5YUg.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bcyn5YUg.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bfc9rQXP.js +1 -0
- package/build/client/_app/immutable/chunks/Bfc9rQXP.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bfc9rQXP.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BfMYiIUi.js → BjxqhpPG.js} +1 -1
- package/build/client/_app/immutable/chunks/BjxqhpPG.js.br +0 -0
- package/build/client/_app/immutable/chunks/BjxqhpPG.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ByaoVvNB.js +1 -0
- package/build/client/_app/immutable/chunks/ByaoVvNB.js.br +0 -0
- package/build/client/_app/immutable/chunks/ByaoVvNB.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BzLd0mTH.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C8b3IMj8.js +1 -0
- package/build/client/_app/immutable/chunks/C8b3IMj8.js.br +0 -0
- package/build/client/_app/immutable/chunks/C8b3IMj8.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CXvvf4uQ.js +1 -0
- package/build/client/_app/immutable/chunks/CXvvf4uQ.js.br +0 -0
- package/build/client/_app/immutable/chunks/CXvvf4uQ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Cl7Z3e6-.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ClC4qR7W2.js +2 -0
- package/build/client/_app/immutable/chunks/ClC4qR7W2.js.br +0 -0
- package/build/client/_app/immutable/chunks/ClC4qR7W2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CuGlh1c2.js +1 -0
- package/build/client/_app/immutable/chunks/CuGlh1c2.js.br +0 -0
- package/build/client/_app/immutable/chunks/CuGlh1c2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CwzIdrQR.js +1 -0
- package/build/client/_app/immutable/chunks/CwzIdrQR.js.br +0 -0
- package/build/client/_app/immutable/chunks/CwzIdrQR.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D5speDV82.js +908 -0
- package/build/client/_app/immutable/chunks/D5speDV82.js.br +0 -0
- package/build/client/_app/immutable/chunks/D5speDV82.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D64sGJRN.js +1 -0
- package/build/client/_app/immutable/chunks/D64sGJRN.js.br +0 -0
- package/build/client/_app/immutable/chunks/D64sGJRN.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DNaA4QRO2.js +1 -0
- package/build/client/_app/immutable/chunks/DNaA4QRO2.js.br +0 -0
- package/build/client/_app/immutable/chunks/DNaA4QRO2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Da59TXPe.js +1 -0
- package/build/client/_app/immutable/chunks/Da59TXPe.js.br +2 -0
- package/build/client/_app/immutable/chunks/Da59TXPe.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DhTiE3j02.js +2 -0
- package/build/client/_app/immutable/chunks/DhTiE3j02.js.br +0 -0
- package/build/client/_app/immutable/chunks/DhTiE3j02.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dhqg7r_2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DmyaDy4d2.js +1 -0
- package/build/client/_app/immutable/chunks/DmyaDy4d2.js.br +0 -0
- package/build/client/_app/immutable/chunks/DmyaDy4d2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DryaQyjN2.js +1 -0
- package/build/client/_app/immutable/chunks/DryaQyjN2.js.br +0 -0
- package/build/client/_app/immutable/chunks/DryaQyjN2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DtK8qK5Q2.js +1 -0
- package/build/client/_app/immutable/chunks/DtK8qK5Q2.js.br +0 -0
- package/build/client/_app/immutable/chunks/DtK8qK5Q2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DtblIi6X2.js +1 -0
- package/build/client/_app/immutable/chunks/DtblIi6X2.js.br +1 -0
- package/build/client/_app/immutable/chunks/DtblIi6X2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/UkzDDeO42.js +1 -0
- package/build/client/_app/immutable/chunks/UkzDDeO42.js.br +0 -0
- package/build/client/_app/immutable/chunks/UkzDDeO42.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Vu8LzrwP2.js +1 -0
- package/build/client/_app/immutable/chunks/Vu8LzrwP2.js.br +0 -0
- package/build/client/_app/immutable/chunks/Vu8LzrwP2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/_b612aVb.js +1 -0
- package/build/client/_app/immutable/chunks/_b612aVb.js.br +0 -0
- package/build/client/_app/immutable/chunks/_b612aVb.js.gz +0 -0
- package/build/client/_app/immutable/chunks/aNMRV4sP2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/cMamJTsF.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ib21i2T_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/kNaey6uv.js.gz +0 -0
- package/build/client/_app/immutable/chunks/oVMDLirx.js +1 -0
- package/build/client/_app/immutable/chunks/oVMDLirx.js.br +0 -0
- package/build/client/_app/immutable/chunks/oVMDLirx.js.gz +0 -0
- package/build/client/_app/immutable/chunks/olAc024e.js +1 -0
- package/build/client/_app/immutable/chunks/olAc024e.js.br +0 -0
- package/build/client/_app/immutable/chunks/olAc024e.js.gz +0 -0
- package/build/client/_app/immutable/chunks/suTxxv1t.js.gz +0 -0
- package/build/client/_app/immutable/chunks/wXIHzLMQ2.js +1 -0
- package/build/client/_app/immutable/chunks/wXIHzLMQ2.js.br +0 -0
- package/build/client/_app/immutable/chunks/wXIHzLMQ2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/wrqalH0a.js +1 -0
- package/build/client/_app/immutable/chunks/wrqalH0a.js.br +0 -0
- package/build/client/_app/immutable/chunks/wrqalH0a.js.gz +0 -0
- package/build/client/_app/immutable/chunks/x60Tn5kT.js +1 -0
- package/build/client/_app/immutable/chunks/x60Tn5kT.js.br +0 -0
- package/build/client/_app/immutable/chunks/x60Tn5kT.js.gz +0 -0
- package/build/client/_app/immutable/chunks/xihTtKlq.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BOrLmFwJ.js → yShDxCNj.js} +1 -1
- package/build/client/_app/immutable/chunks/yShDxCNj.js.br +2 -0
- package/build/client/_app/immutable/chunks/yShDxCNj.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.Etd-exTb.js +2 -0
- package/build/client/_app/immutable/entry/app.Etd-exTb.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Etd-exTb.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.DY2B3u4g.js +1 -0
- package/build/client/_app/immutable/entry/start.DY2B3u4g.js.br +0 -0
- package/build/client/_app/immutable/entry/start.DY2B3u4g.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.tKfYV3__.js +8 -0
- package/build/client/_app/immutable/nodes/0.tKfYV3__.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.tKfYV3__.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{1.KYdA6ppX.js → 1.CER5ICKt.js} +1 -1
- package/build/client/_app/immutable/nodes/1.CER5ICKt.js.br +1 -0
- package/build/client/_app/immutable/nodes/1.CER5ICKt.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.rT7cD8kX.js +1 -0
- package/build/client/_app/immutable/nodes/10.rT7cD8kX.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.rT7cD8kX.js.gz +0 -0
- package/build/client/_app/immutable/nodes/11.BAnV_Y5Y.js +2 -0
- package/build/client/_app/immutable/nodes/11.BAnV_Y5Y.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.BAnV_Y5Y.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{9.CMW6a2Lg.js → 12.DCTRFMqo.js} +4 -3
- package/build/client/_app/immutable/nodes/12.DCTRFMqo.js.br +0 -0
- package/build/client/_app/immutable/nodes/12.DCTRFMqo.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{2.DBz20KgG.js → 2.CF488WWF.js} +1 -1
- package/build/client/_app/immutable/nodes/2.CF488WWF.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.CF488WWF.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.CP7CPPVH.js +1 -0
- package/build/client/_app/immutable/nodes/3.CP7CPPVH.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.CP7CPPVH.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.D1bxCSiM.js +3 -0
- package/build/client/_app/immutable/nodes/4.D1bxCSiM.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.D1bxCSiM.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.D6jZgh9y.js +48 -0
- package/build/client/_app/immutable/nodes/5.D6jZgh9y.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.D6jZgh9y.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.BrBFUA0s.js +1 -0
- package/build/client/_app/immutable/nodes/6.BrBFUA0s.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.BrBFUA0s.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.pajo8MfM.js +3 -0
- package/build/client/_app/immutable/nodes/7.pajo8MfM.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.pajo8MfM.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.Cc80_Igi.js +5 -0
- package/build/client/_app/immutable/nodes/8.Cc80_Igi.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.Cc80_Igi.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{7.CemgNJfw.js → 9.D72NaL3l.js} +1 -1
- package/build/client/_app/immutable/nodes/9.D72NaL3l.js.br +1 -0
- package/build/client/_app/immutable/nodes/9.D72NaL3l.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/client/lyriks_logo.svg +148 -0
- package/build/client/lyriks_logo.svg.br +0 -0
- package/build/client/lyriks_logo.svg.gz +0 -0
- package/build/server/chunks/0-8YZc572z.js +15 -0
- package/build/server/chunks/0-8YZc572z.js.map +1 -0
- package/build/server/chunks/1-DxkfSJLu.js +9 -0
- package/build/server/chunks/{1-DPpKAKXV.js.map → 1-DxkfSJLu.js.map} +1 -1
- package/build/server/chunks/10-DkObdGtU.js +9 -0
- package/build/server/chunks/10-DkObdGtU.js.map +1 -0
- package/build/server/chunks/11-DL94HxpZ.js +9 -0
- package/build/server/chunks/11-DL94HxpZ.js.map +1 -0
- package/build/server/chunks/12-CI74sCkt.js +9 -0
- package/build/server/chunks/12-CI74sCkt.js.map +1 -0
- package/build/server/chunks/2-qhWwQ4eL.js +9 -0
- package/build/server/chunks/2-qhWwQ4eL.js.map +1 -0
- package/build/server/chunks/3-CzoZtSTp.js +16 -0
- package/build/server/chunks/3-CzoZtSTp.js.map +1 -0
- package/build/server/chunks/4-CDa9DBsh.js +16 -0
- package/build/server/chunks/4-CDa9DBsh.js.map +1 -0
- package/build/server/chunks/5-qD2xxOrq.js +9 -0
- package/build/server/chunks/5-qD2xxOrq.js.map +1 -0
- package/build/server/chunks/6-B4mWzvDn.js +9 -0
- package/build/server/chunks/6-B4mWzvDn.js.map +1 -0
- package/build/server/chunks/7-zExv-fTN.js +9 -0
- package/build/server/chunks/7-zExv-fTN.js.map +1 -0
- package/build/server/chunks/8-BVrGdQg4.js +9 -0
- package/build/server/chunks/{6-QQ7r8Rd5.js.map → 8-BVrGdQg4.js.map} +1 -1
- package/build/server/chunks/9-BnZLRMYA.js +9 -0
- package/build/server/chunks/9-BnZLRMYA.js.map +1 -0
- package/build/server/chunks/BehaviorGraph-C-9z37Sm.js +788 -0
- package/build/server/chunks/BehaviorGraph-C-9z37Sm.js.map +1 -0
- package/build/server/chunks/Clock-BfMWQpmJ.js +5 -0
- package/build/server/chunks/Clock-BfMWQpmJ.js.map +1 -0
- package/build/server/chunks/DeleteDomain-BvHEgAyp.js +24 -0
- package/build/server/chunks/DeleteDomain-BvHEgAyp.js.map +1 -0
- package/build/server/chunks/{FeatureValidator-B8qEjAUW.js → DeleteFeature-DnK8sBJI.js} +142 -77
- package/build/server/chunks/DeleteFeature-DnK8sBJI.js.map +1 -0
- package/build/server/chunks/DeleteProject-BXZcehHZ.js +41 -0
- package/build/server/chunks/DeleteProject-BXZcehHZ.js.map +1 -0
- package/build/server/chunks/Effect-BJtLR-6l.js +46 -0
- package/build/server/chunks/Effect-BJtLR-6l.js.map +1 -0
- package/build/server/chunks/{FeatureCard-BQOY6gJQ.js → FeatureCard-Bb50FEfp.js} +4 -4
- package/build/server/chunks/{FeatureCard-BQOY6gJQ.js.map → FeatureCard-Bb50FEfp.js.map} +1 -1
- package/build/server/chunks/{FeatureJson-Bv-qiOSf.js → FeatureJson-DYvMEAub.js} +2 -2
- package/build/server/chunks/{FeatureJson-Bv-qiOSf.js.map → FeatureJson-DYvMEAub.js.map} +1 -1
- package/build/server/chunks/{FeatureTransforms-UWDHmWEg.js → FeatureTransforms-B0aI_CJD.js} +10 -3
- package/build/server/chunks/FeatureTransforms-B0aI_CJD.js.map +1 -0
- package/build/server/chunks/{ManageTagsDialog-DBxA3tM2.js → ManageTagsDialog-D5xbAVNB.js} +5 -5
- package/build/server/chunks/ManageTagsDialog-D5xbAVNB.js.map +1 -0
- package/build/server/chunks/{ProgressBar-CfhccQ83.js → ProgressBar-CUC2EZqG.js} +3 -3
- package/build/server/chunks/ProgressBar-CUC2EZqG.js.map +1 -0
- package/build/server/chunks/{ProjectsIndex-CoDrvRya.js → ProjectsIndex-FgIu9dBp.js} +135 -14
- package/build/server/chunks/ProjectsIndex-FgIu9dBp.js.map +1 -0
- package/build/server/chunks/{RenameTag-BuWLMl1m.js → RenameTag-DWIIR4Bx.js} +3 -6
- package/build/server/chunks/RenameTag-DWIIR4Bx.js.map +1 -0
- package/build/server/chunks/ScenarioApplier-YPKECfZe.js +55 -0
- package/build/server/chunks/ScenarioApplier-YPKECfZe.js.map +1 -0
- package/build/server/chunks/SimulatorEngine-DM1F9nCO.js +1391 -0
- package/build/server/chunks/SimulatorEngine-DM1F9nCO.js.map +1 -0
- package/build/server/chunks/StateValue-BBjWox8f.js +105 -0
- package/build/server/chunks/StateValue-BBjWox8f.js.map +1 -0
- package/build/server/chunks/{TagDotStrip-B1XQ0m0Y.js → TagDotStrip-0rn-IJVE.js} +4 -4
- package/build/server/chunks/TagDotStrip-0rn-IJVE.js.map +1 -0
- package/build/server/chunks/{TagFilterSelect-DbO0Qduh.js → TagFilterSelect-Dbu-7Dg4.js} +5 -5
- package/build/server/chunks/{TagFilterSelect-DbO0Qduh.js.map → TagFilterSelect-Dbu-7Dg4.js.map} +1 -1
- package/build/server/chunks/{TagPalette-CtMNYCmu.js → TagPalette-CpdTiC_7.js} +101 -9
- package/build/server/chunks/TagPalette-CpdTiC_7.js.map +1 -0
- package/build/server/chunks/TransitionCatalog-CYXUANy6.js +271 -0
- package/build/server/chunks/TransitionCatalog-CYXUANy6.js.map +1 -0
- package/build/server/chunks/_layout.svelte-pSSG85WT.js +1342 -0
- package/build/server/chunks/_layout.svelte-pSSG85WT.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BKTveFAj.js → _page.svelte-BNH3szkk.js} +22 -17
- package/build/server/chunks/{_page.svelte-BKTveFAj.js.map → _page.svelte-BNH3szkk.js.map} +1 -1
- package/build/server/chunks/_page.svelte-BcuGvUt1.js +37 -0
- package/build/server/chunks/{_page.svelte-B7hT3P8E.js.map → _page.svelte-BcuGvUt1.js.map} +1 -1
- package/build/server/chunks/_page.svelte-BoOMG5Y0.js +37 -0
- package/build/server/chunks/{_page.svelte-De508ek8.js.map → _page.svelte-BoOMG5Y0.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-BqSC-1vK.js → _page.svelte-C4PRh_wP.js} +104 -54
- package/build/server/chunks/_page.svelte-C4PRh_wP.js.map +1 -0
- package/build/server/chunks/_page.svelte-Cqn34NXy.js +74 -0
- package/build/server/chunks/_page.svelte-Cqn34NXy.js.map +1 -0
- package/build/server/chunks/{_page.svelte-B1s7jxaQ.js → _page.svelte-DSCeOGv7.js} +15 -10
- package/build/server/chunks/_page.svelte-DSCeOGv7.js.map +1 -0
- package/build/server/chunks/_page.svelte-DqWdGt48.js +182 -0
- package/build/server/chunks/_page.svelte-DqWdGt48.js.map +1 -0
- package/build/server/chunks/_page.svelte-DsQHSEl4.js +49 -0
- package/build/server/chunks/_page.svelte-DsQHSEl4.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BKKCa9H5.js → _page.svelte-Uioz8hsG.js} +18 -11
- package/build/server/chunks/{_page.svelte-BKKCa9H5.js.map → _page.svelte-Uioz8hsG.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-Zf9H4KOP.js → _page.svelte-p38jot9e.js} +81 -478
- package/build/server/chunks/_page.svelte-p38jot9e.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BtI2zZ_Z.js → _page.svelte-yN5kzgJ9.js} +251 -447
- package/build/server/chunks/_page.svelte-yN5kzgJ9.js.map +1 -0
- package/build/server/chunks/{_server.ts-DsbbVoOn.js → _server.ts-1CtrHhte.js} +4 -4
- package/build/server/chunks/{_server.ts-DsbbVoOn.js.map → _server.ts-1CtrHhte.js.map} +1 -1
- package/build/server/chunks/{_server.ts-CWvU15tL.js → _server.ts-71Qx1lQb.js} +4 -4
- package/build/server/chunks/{_server.ts-CWvU15tL.js.map → _server.ts-71Qx1lQb.js.map} +1 -1
- package/build/server/chunks/_server.ts-BAyekGHB.js +961 -0
- package/build/server/chunks/_server.ts-BAyekGHB.js.map +1 -0
- package/build/server/chunks/{_server.ts-BihpbxOW.js → _server.ts-BLWhU22T.js} +4 -4
- package/build/server/chunks/{_server.ts-BihpbxOW.js.map → _server.ts-BLWhU22T.js.map} +1 -1
- package/build/server/chunks/{_server.ts-YnfXkeMJ.js → _server.ts-C7EVZVxv.js} +22 -13
- package/build/server/chunks/_server.ts-C7EVZVxv.js.map +1 -0
- package/build/server/chunks/{_server.ts-vcaqdwxS.js → _server.ts-CGjYuLmo.js} +12 -7
- package/build/server/chunks/_server.ts-CGjYuLmo.js.map +1 -0
- package/build/server/chunks/{_server.ts-Dy5zQHe2.js → _server.ts-CX6H8fSE.js} +8 -31
- package/build/server/chunks/_server.ts-CX6H8fSE.js.map +1 -0
- package/build/server/chunks/{_server.ts-BuoQ02BW.js → _server.ts-CyEdTCLr.js} +4 -4
- package/build/server/chunks/{_server.ts-BuoQ02BW.js.map → _server.ts-CyEdTCLr.js.map} +1 -1
- package/build/server/chunks/_server.ts-DKVTM9Pj.js +77 -0
- package/build/server/chunks/_server.ts-DKVTM9Pj.js.map +1 -0
- package/build/server/chunks/{_server.ts-0uNTZKwF.js → _server.ts-Dip65hLJ.js} +15 -9
- package/build/server/chunks/_server.ts-Dip65hLJ.js.map +1 -0
- package/build/server/chunks/{_server.ts-D4EO0VHu.js → _server.ts-Dm0tCs2i.js} +5 -5
- package/build/server/chunks/{_server.ts-D4EO0VHu.js.map → _server.ts-Dm0tCs2i.js.map} +1 -1
- package/build/server/chunks/{_server.ts-BIBWjQI-.js → _server.ts-DsYwK_uW.js} +4 -4
- package/build/server/chunks/{_server.ts-BIBWjQI-.js.map → _server.ts-DsYwK_uW.js.map} +1 -1
- package/build/server/chunks/{_server.ts-DDa0Nk_S.js → _server.ts-RCEgegYU.js} +4 -4
- package/build/server/chunks/{_server.ts-DDa0Nk_S.js.map → _server.ts-RCEgegYU.js.map} +1 -1
- package/build/server/chunks/_server.ts-XOLAT4dd.js +146 -0
- package/build/server/chunks/_server.ts-XOLAT4dd.js.map +1 -0
- package/build/server/chunks/_server.ts-afh_zLVi.js +69 -0
- package/build/server/chunks/_server.ts-afh_zLVi.js.map +1 -0
- package/build/server/chunks/{browserContainer-CNX7ANld.js → browserContainer-BdldtueJ.js} +71 -1378
- package/build/server/chunks/browserContainer-BdldtueJ.js.map +1 -0
- package/build/server/chunks/buildSearchDocs-Cyfrnw9G.js +337 -0
- package/build/server/chunks/buildSearchDocs-Cyfrnw9G.js.map +1 -0
- package/build/server/chunks/{builderModeStore.svelte-ihupr-3p.js → builderModeStore.svelte-BEZMQEqn.js} +223 -11
- package/build/server/chunks/builderModeStore.svelte-BEZMQEqn.js.map +1 -0
- package/build/server/chunks/client-C9Cat4DK.js +51 -0
- package/build/server/chunks/{client-DfpLcAZ9.js.map → client-C9Cat4DK.js.map} +1 -1
- package/build/server/chunks/{error.svelte-C35KOpru.js → error.svelte-CzVR_A6P.js} +5 -5
- package/build/server/chunks/{error.svelte-C35KOpru.js.map → error.svelte-CzVR_A6P.js.map} +1 -1
- package/build/server/chunks/featureQueueContext-DuXpyTdC.js +32 -0
- package/build/server/chunks/featureQueueContext-DuXpyTdC.js.map +1 -0
- package/build/server/chunks/featureStore.svelte-DHZf88gu.js +162 -0
- package/build/server/chunks/featureStore.svelte-DHZf88gu.js.map +1 -0
- package/build/server/chunks/{projectsStore.svelte-QDz5PchX.js → featuresStore.svelte-bUyQBg1-.js} +95 -3
- package/build/server/chunks/featuresStore.svelte-bUyQBg1-.js.map +1 -0
- package/build/server/chunks/{hooks.server-Rv301GTB.js → hooks.server-y3jdg_sB.js} +6 -2
- package/build/server/chunks/hooks.server-y3jdg_sB.js.map +1 -0
- package/build/server/chunks/humanize-CkCPfeWi.js +53 -0
- package/build/server/chunks/humanize-CkCPfeWi.js.map +1 -0
- package/build/server/chunks/{index-server-7H0jzj0M.js → index-server-DvBux_Gf.js} +47 -2
- package/build/server/chunks/{index-server-7H0jzj0M.js.map → index-server-DvBux_Gf.js.map} +1 -1
- package/build/server/chunks/{internal-BPKrFkK1.js → internal-BFt8yDlf.js} +5 -5
- package/build/server/chunks/{internal-BPKrFkK1.js.map → internal-BFt8yDlf.js.map} +1 -1
- package/build/server/chunks/projectBundleClient-BtvWPh87.js +168 -0
- package/build/server/chunks/projectBundleClient-BtvWPh87.js.map +1 -0
- package/build/server/chunks/projectContextStore.svelte-jRJGJZ42.js +141 -0
- package/build/server/chunks/projectContextStore.svelte-jRJGJZ42.js.map +1 -0
- package/build/server/chunks/projectFeaturesStore.svelte-BwNEtDIL.js +87 -0
- package/build/server/chunks/projectFeaturesStore.svelte-BwNEtDIL.js.map +1 -0
- package/build/server/chunks/projectStore.svelte-BNuLNxk_.js +230 -0
- package/build/server/chunks/projectStore.svelte-BNuLNxk_.js.map +1 -0
- package/build/server/chunks/{reconcile-Dv7jS3C8.js → reconcile-CVG2LSlW.js} +54 -267
- package/build/server/chunks/reconcile-CVG2LSlW.js.map +1 -0
- package/build/server/chunks/registry-DqAn_hVE.js +21 -0
- package/build/server/chunks/registry-DqAn_hVE.js.map +1 -0
- package/build/server/chunks/{snapshotRepository-BPXCjX92.js → snapshotRepository-8f-2wTrb.js} +30 -5
- package/build/server/chunks/snapshotRepository-8f-2wTrb.js.map +1 -0
- package/build/server/chunks/{state-CpLVNZq7.js → state-CZZtjXLE.js} +3 -3
- package/build/server/chunks/{state-CpLVNZq7.js.map → state-CZZtjXLE.js.map} +1 -1
- package/build/server/chunks/{sync-DZ3dn761.js → sync-Bn6eSUhC.js} +3 -3
- package/build/server/chunks/{sync-DZ3dn761.js.map → sync-Bn6eSUhC.js.map} +1 -1
- package/build/server/chunks/{syncBridge-BwXzPdjJ.js → syncAwareRepositories-DvUjq5Q6.js} +27 -3
- package/build/server/chunks/syncAwareRepositories-DvUjq5Q6.js.map +1 -0
- package/build/server/chunks/{tagPaletteStore.svelte-DfZOBvgY.js → tagPaletteStore.svelte-C71bdzDl.js} +4 -4
- package/build/server/chunks/{tagPaletteStore.svelte-DfZOBvgY.js.map → tagPaletteStore.svelte-C71bdzDl.js.map} +1 -1
- package/build/server/index.js +2 -2
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +74 -29
- package/build/server/manifest.js.map +1 -1
- package/cli/README.md +70 -2
- package/cli/commands/check.ts +190 -0
- package/cli/commands/ci.ts +71 -0
- package/cli/commands/coverage-ingest.ts +112 -0
- package/cli/commands/dashboard.ts +14 -0
- package/cli/commands/init.ts +26 -0
- package/cli/commands/scenarios-adapter.ts +96 -0
- package/cli/commands/theme.ts +62 -0
- package/cli/scenarios/adapter-scaffold.ts +99 -0
- package/cli/scenarios/codegen.ts +7 -1
- package/cli/scenarios/results.ts +85 -0
- package/cli/skills/unspa-audit/SKILL.md +19 -0
- package/cli/skills/unspa-edit/SKILL.md +20 -3
- package/cli/skills/unspa-implement/SKILL.md +28 -0
- package/cli/unspa.ts +136 -2
- package/cli/util/context-files.ts +18 -2
- package/cli/util/theme.ts +34 -0
- package/mcp-server/bin.ts +104 -104
- package/mcp-server/migrate-defaults.ts +164 -164
- package/mcp-server/repo-link.ts +142 -134
- package/mcp-server/resources/guide.ts +24 -4
- package/mcp-server/resources/operations.ts +3 -0
- package/mcp-server/seed-snapshots.ts +22 -22
- package/mcp-server/server.ts +8 -4
- package/mcp-server/sync-aware-repos.ts +79 -79
- package/mcp-server/sync-notifier.ts +180 -127
- package/mcp-server/tools/_codegen.ts +115 -115
- package/mcp-server/tools/_entity_builders.ts +30 -0
- package/mcp-server/tools/_shared.ts +210 -210
- package/mcp-server/tools/action.ts +210 -210
- package/mcp-server/tools/batch.ts +29 -5
- package/mcp-server/tools/effect.ts +139 -135
- package/mcp-server/tools/entity.ts +132 -132
- package/mcp-server/tools/entityField.ts +132 -132
- package/mcp-server/tools/event.ts +116 -116
- package/mcp-server/tools/feature.ts +264 -264
- package/mcp-server/tools/invariant.ts +275 -275
- package/mcp-server/tools/persona.ts +141 -141
- package/mcp-server/tools/project.ts +500 -391
- package/mcp-server/tools/reachabilityGoal.ts +97 -0
- package/mcp-server/tools/read.ts +526 -483
- package/mcp-server/tools/reorder.ts +114 -114
- package/mcp-server/tools/resource.ts +194 -194
- package/mcp-server/tools/rule.ts +302 -302
- package/mcp-server/tools/scenario.ts +4 -1
- package/mcp-server/tools/specGaps.ts +221 -221
- package/mcp-server/tools/state.ts +10 -2
- package/mcp-server/tools/surface.ts +102 -102
- package/mcp-server/tools/transition.ts +96 -96
- package/mcp-server/tools/verification.ts +131 -0
- package/package.json +15 -2
- package/src/app.css +208 -9
- package/src/app.html +15 -1
- package/src/features/behavior-model/application/ports/FeatureRepository.ts +16 -16
- package/src/features/behavior-model/application/use-cases/CreateFeature.ts +24 -24
- package/src/features/behavior-model/application/use-cases/DeleteFeature.ts +8 -8
- package/src/features/behavior-model/application/use-cases/GetFeature.ts +9 -9
- package/src/features/behavior-model/application/use-cases/ListFeatures.ts +10 -10
- package/src/features/behavior-model/application/use-cases/MutateFeature.ts +90 -90
- package/src/features/behavior-model/application/use-cases/SaveFeature.ts +31 -31
- package/src/features/behavior-model/domain/entities/Entity.ts +45 -45
- package/src/features/behavior-model/domain/entities/EventDefinition.ts +35 -35
- package/src/features/behavior-model/domain/entities/Feature.ts +10 -0
- package/src/features/behavior-model/domain/entities/Persona.ts +33 -33
- package/src/features/behavior-model/domain/entities/ReachabilityGoal.ts +39 -0
- package/src/features/behavior-model/domain/entities/Resource.ts +54 -54
- package/src/features/behavior-model/domain/entities/Scenario.ts +15 -0
- package/src/features/behavior-model/domain/entities/StateDefinition.ts +13 -0
- package/src/features/behavior-model/domain/entities/Surface.ts +75 -75
- package/src/features/behavior-model/domain/entities/index.ts +9 -9
- package/src/features/behavior-model/domain/services/BehaviorGraphModel.ts +556 -0
- package/src/features/behavior-model/domain/services/DerivedState.ts +67 -0
- package/src/features/behavior-model/domain/services/EffectApplier.ts +112 -3
- package/src/features/behavior-model/domain/services/EffectiveEntities.ts +166 -166
- package/src/features/behavior-model/domain/services/EntityDeducer.ts +83 -83
- package/src/features/behavior-model/domain/services/EventCatalog.ts +141 -141
- package/src/features/behavior-model/domain/services/FeatureExpressionNormalizer.ts +43 -5
- package/src/features/behavior-model/domain/services/FeatureSharedStateNormalizer.ts +24 -3
- package/src/features/behavior-model/domain/services/FeatureTransforms.ts +33 -0
- package/src/features/behavior-model/domain/services/FeatureValidator.ts +124 -16
- package/src/features/behavior-model/domain/services/PersonaApplier.ts +39 -39
- package/src/features/behavior-model/domain/services/ResourceDeducer.ts +64 -64
- package/src/features/behavior-model/domain/services/ResourceUsage.ts +79 -79
- package/src/features/behavior-model/domain/services/ScenarioApplier.ts +40 -40
- package/src/features/behavior-model/domain/services/SharedStateDefinitions.ts +32 -32
- package/src/features/behavior-model/domain/services/StatePathReferences.ts +249 -217
- package/src/features/behavior-model/domain/services/TransitionCatalog.ts +173 -173
- package/src/features/behavior-model/domain/value-objects/Effect.ts +100 -3
- package/src/features/behavior-model/domain/value-objects/EntityFieldType.ts +57 -57
- package/src/features/behavior-model/domain/value-objects/Expression.ts +22 -2
- package/src/features/behavior-model/domain/value-objects/ParameterType.ts +57 -57
- package/src/features/behavior-model/domain/value-objects/Resource.ts +210 -210
- package/src/features/behavior-model/domain/value-objects/RuleCategory.ts +57 -57
- package/src/features/behavior-model/domain/value-objects/RuleCondition.ts +52 -1
- package/src/features/behavior-model/domain/value-objects/SimulationClock.ts +35 -0
- package/src/features/behavior-model/domain/value-objects/ids.ts +2 -0
- package/src/features/behavior-model/infrastructure/io/FeatureJson.ts +89 -89
- package/src/features/behavior-model/infrastructure/persistence/HttpFeatureRepository.ts +43 -43
- package/src/features/behavior-model/infrastructure/persistence/JsonFolderFeatureRepository.ts +10 -0
- package/src/features/behavior-model/infrastructure/persistence/snapshot-discovery.ts +76 -76
- package/src/features/behavior-model/infrastructure/seed/seedStorefront.ts +967 -967
- package/src/features/behavior-model/presentation/adapters/VisBehaviorGraphRenderer.ts +501 -0
- package/src/features/behavior-model/presentation/components/ActionEditor.svelte +683 -682
- package/src/features/behavior-model/presentation/components/ActionsEditor.svelte +232 -232
- package/src/features/behavior-model/presentation/components/BehaviorGraph.svelte +568 -0
- package/src/features/behavior-model/presentation/components/EffectEditor.svelte +168 -168
- package/src/features/behavior-model/presentation/components/EntityEditor.svelte +241 -248
- package/src/features/behavior-model/presentation/components/EntityFieldRow.svelte +180 -181
- package/src/features/behavior-model/presentation/components/EntityManager.svelte +252 -251
- package/src/features/behavior-model/presentation/components/EventsManager.svelte +373 -372
- package/src/features/behavior-model/presentation/components/FeatureEditor.svelte +396 -348
- package/src/features/behavior-model/presentation/components/FeatureHeader.svelte +165 -148
- package/src/features/behavior-model/presentation/components/FeatureHealthStrip.svelte +110 -110
- package/src/features/behavior-model/presentation/components/HistoryPanel.svelte +154 -154
- package/src/features/behavior-model/presentation/components/NewFeatureForm.svelte +66 -66
- package/src/features/behavior-model/presentation/components/ParameterNameSelect.svelte +84 -84
- package/src/features/behavior-model/presentation/components/ParametersEditor.svelte +411 -411
- package/src/features/behavior-model/presentation/components/PersonaEditor.svelte +244 -244
- package/src/features/behavior-model/presentation/components/PersonasManager.svelte +130 -130
- package/src/features/behavior-model/presentation/components/ReachabilityGoalEditor.svelte +230 -0
- package/src/features/behavior-model/presentation/components/ReachabilityGoalsEditor.svelte +86 -0
- package/src/features/behavior-model/presentation/components/ResourcesManager.svelte +291 -290
- package/src/features/behavior-model/presentation/components/ScenariosEditor.svelte +496 -496
- package/src/features/behavior-model/presentation/components/StateDefinitionsEditor.svelte +356 -356
- package/src/features/behavior-model/presentation/components/SurfaceEntitiesView.svelte +88 -88
- package/src/features/behavior-model/presentation/components/SurfaceInvariantsEditor.svelte +76 -76
- package/src/features/behavior-model/presentation/components/SurfaceList.svelte +300 -300
- package/src/features/behavior-model/presentation/components/SurfaceMetaEditor.svelte +158 -156
- package/src/features/behavior-model/presentation/components/SurfacePanel.svelte +198 -198
- package/src/features/behavior-model/presentation/components/SurfacePersonasView.svelte +122 -122
- package/src/features/behavior-model/presentation/components/SurfaceResourcesView.svelte +113 -113
- package/src/features/behavior-model/presentation/components/SurfaceRulesEditor.svelte +69 -69
- package/src/features/behavior-model/presentation/components/TransitionsManager.svelte +322 -321
- package/src/features/behavior-model/presentation/context/featureQueueContext.ts +78 -0
- package/src/features/behavior-model/presentation/stores/editorStore.svelte.ts +132 -131
- package/src/features/behavior-model/presentation/stores/featureStore.svelte.ts +177 -177
- package/src/features/behavior-model/presentation/stores/featuresStore.svelte.ts +98 -98
- package/src/features/behavior-model/presentation/view-models/BehaviorGraphTheme.ts +44 -0
- package/src/features/behavior-model/presentation/view-models/factories.ts +181 -132
- package/src/features/builder-mode/domain/BuilderModeDashboard.ts +7 -1
- package/src/features/builder-mode/presentation/components/BuilderModeDashboard.svelte +78 -16
- package/src/features/builder-mode/presentation/components/BuilderTagChips.svelte +25 -0
- package/src/features/builder-mode/presentation/stores/builderModeStore.svelte.ts +247 -3
- package/src/features/domains/infrastructure/persistence/JsonFolderDomainRepository.ts +9 -0
- package/src/features/global-search/application/use-cases/LoadSearchIndex.ts +70 -0
- package/src/features/global-search/domain/SearchDoc.ts +111 -0
- package/src/features/global-search/domain/buildSearchDocs.ts +483 -0
- package/src/features/global-search/domain/searchNav.ts +58 -0
- package/src/features/global-search/domain/searchScoring.ts +81 -0
- package/src/features/global-search/infrastructure/adapters/defaultSearchHost.ts +28 -0
- package/src/features/global-search/presentation/components/GlobalSearch.svelte +262 -0
- package/src/features/global-search/presentation/ports/SearchHostPorts.ts +41 -0
- package/src/features/global-search/presentation/searchKindMeta.ts +108 -0
- package/src/features/global-search/presentation/stores/globalSearchStore.svelte.ts +171 -0
- package/src/features/implementation-queue/presentation/components/FloatingQueueWidget.svelte +264 -0
- package/src/features/implementation-queue/presentation/stores/globalQueueStore.svelte.ts +172 -0
- package/src/features/implementation-status/application/ports/ImplementationStatusRepository.ts +8 -8
- package/src/features/implementation-status/application/use-cases/GetImplementationStatus.ts +8 -8
- package/src/features/implementation-status/domain/ApplyCapturedToSpec.ts +323 -322
- package/src/features/implementation-status/domain/FieldDiff.ts +238 -236
- package/src/features/implementation-status/infrastructure/persistence/InMemoryImplementationStatusRepository.ts +21 -21
- package/src/features/implementation-status/presentation/components/ImplementationStatusPanel.svelte +831 -831
- package/src/features/implementation-status/presentation/stores/implementationStatusStore.svelte.ts +97 -97
- package/src/features/library/application/use-cases/ApplyBlueprintsToFeature.ts +33 -33
- package/src/features/library/domain/services/BlueprintApplier.ts +94 -94
- package/src/features/library/infrastructure/blueprints/auth/ResetPasswordBlueprint.ts +332 -332
- package/src/features/library/infrastructure/blueprints/auth/SignInBlueprint.ts +281 -281
- package/src/features/library/infrastructure/blueprints/auth/SignUpBlueprint.ts +299 -299
- package/src/features/library/infrastructure/blueprints/auth/VerifyEmailBlueprint.ts +288 -288
- package/src/features/library/infrastructure/blueprints/auth/shared.ts +146 -146
- package/src/features/library/infrastructure/blueprints/commerce/CartBlueprint.ts +222 -222
- package/src/features/library/infrastructure/blueprints/commerce/CatalogBlueprint.ts +190 -190
- package/src/features/library/infrastructure/blueprints/commerce/CheckoutBlueprint.ts +322 -322
- package/src/features/library/infrastructure/blueprints/commerce/OrderConfirmationBlueprint.ts +172 -172
- package/src/features/library/infrastructure/blueprints/commerce/ProductDetailsBlueprint.ts +290 -290
- package/src/features/library/infrastructure/blueprints/content/ReviewsBlueprint.ts +392 -392
- package/src/features/library/infrastructure/blueprints/onboarding/OnboardingWizardBlueprint.ts +344 -344
- package/src/features/library/infrastructure/blueprints/utility/CanvasBlueprint.ts +419 -419
- package/src/features/library/infrastructure/blueprints/utility/CookieConsentBlueprint.ts +195 -195
- package/src/features/library/infrastructure/blueprints/utility/NotFoundBlueprint.ts +86 -86
- package/src/features/library/infrastructure/blueprints/utility/SearchPaletteBlueprint.ts +192 -192
- package/src/features/library/infrastructure/blueprints/utility/StoreLocatorBlueprint.ts +221 -221
- package/src/features/library/infrastructure/blueprints/utility/TaskBoardBlueprint.ts +196 -196
- package/src/features/maturity/application/use-cases/ScoreFeature.ts +7 -7
- package/src/features/maturity/domain/MaturityReport.ts +70 -70
- package/src/features/maturity/domain/MaturityScorer.ts +1001 -985
- package/src/features/maturity/presentation/components/MaturityPanel.svelte +376 -372
- package/src/features/mcp-tools/application/tools/dryRunSimulate.ts +24 -24
- package/src/features/mcp-tools/application/tools/findStateReferences.ts +19 -19
- package/src/features/mcp-tools/application/tools/generateTypes.ts +0 -1
- package/src/features/mcp-tools/application/tools/getAction.ts +165 -165
- package/src/features/mcp-tools/application/tools/getFeature.ts +5 -5
- package/src/features/mcp-tools/application/tools/getFeatureIndex.ts +79 -79
- package/src/features/mcp-tools/application/tools/getNeighborhood.ts +319 -319
- package/src/features/mcp-tools/application/tools/getSurface.ts +86 -86
- package/src/features/mcp-tools/application/tools/index.ts +56 -56
- package/src/features/mcp-tools/application/tools/listActions.ts +49 -49
- package/src/features/mcp-tools/application/tools/listFeatures.ts +7 -7
- package/src/features/mcp-tools/application/tools/scoreFeature.ts +153 -153
- package/src/features/projects/application/ports/ProjectRepository.ts +14 -14
- package/src/features/projects/application/use-cases/AddFeatureToProject.ts +23 -23
- package/src/features/projects/application/use-cases/CreateProject.ts +16 -16
- package/src/features/projects/application/use-cases/FindProjectContainingFeature.ts +23 -23
- package/src/features/projects/application/use-cases/GetProjectAggregate.ts +131 -131
- package/src/features/projects/application/use-cases/ImportProjectBundle.ts +45 -0
- package/src/features/projects/application/use-cases/MoveFeatureInProject.ts +36 -36
- package/src/features/projects/application/use-cases/RemoveFeatureFromProject.ts +23 -23
- package/src/features/projects/domain/entities/Project.ts +12 -0
- package/src/features/projects/domain/services/InheritedFromProject.ts +130 -130
- package/src/features/projects/infrastructure/persistence/JsonFolderProjectRepository.ts +9 -0
- package/src/features/projects/presentation/components/ProjectCard.svelte +27 -8
- package/src/features/projects/presentation/components/ProjectEditor.svelte +23 -19
- package/src/features/projects/presentation/components/ProjectFeaturesPanel.svelte +433 -433
- package/src/features/projects/presentation/components/ProjectsIndex.svelte +54 -10
- package/src/features/projects/presentation/stores/projectContextStore.svelte.ts +170 -170
- package/src/features/projects/presentation/stores/projectFeaturesStore.svelte.ts +114 -114
- package/src/features/projects/presentation/stores/projectStore.svelte.ts +265 -266
- package/src/features/projects/presentation/stores/projectsStore.svelte.ts +134 -134
- package/src/features/simulator/application/use-cases/RunScenarios.ts +27 -1
- package/src/features/simulator/application/use-cases/SimulateAction.ts +47 -47
- package/src/features/simulator/domain/SimulationResult.ts +79 -79
- package/src/features/simulator/domain/SimulatorEngine.ts +43 -9
- package/src/features/simulator/domain/StateExplorer.ts +369 -0
- package/src/features/simulator/domain/SurfaceReachability.ts +130 -0
- package/src/features/simulator/presentation/components/ParameterInputs.svelte +277 -277
- package/src/features/simulator/presentation/components/PersonaPicker.svelte +52 -52
- package/src/features/simulator/presentation/components/ScenarioPicker.svelte +42 -45
- package/src/features/simulator/presentation/components/SidePanel.svelte +170 -170
- package/src/features/simulator/presentation/components/SimulationResultView.svelte +394 -394
- package/src/features/simulator/presentation/components/SimulatorPanel.svelte +293 -293
- package/src/features/simulator/presentation/components/StateInspector.svelte +101 -101
- package/src/features/simulator/presentation/stores/simulatorStore.svelte.ts +268 -268
- package/src/features/tutorial/presentation/components/CodeBlock.svelte +5 -1
- package/src/features/verification/application/ports/BehavioralIndexReader.ts +12 -0
- package/src/features/verification/application/use-cases/VerifyFeatures.ts +151 -0
- package/src/features/verification/domain/DriftReport.ts +37 -0
- package/src/features/verification/domain/EventCoherenceReport.ts +27 -0
- package/src/features/verification/domain/IndexedImplementation.ts +27 -0
- package/src/features/verification/domain/VerificationReport.ts +59 -0
- package/src/features/verification/domain/VerificationThresholds.ts +52 -0
- package/src/features/verification/domain/VerificationVerdict.ts +43 -0
- package/src/features/verification/domain/aggregateVerdict.ts +244 -0
- package/src/features/verification/domain/analyzeEventCoherence.ts +43 -0
- package/src/features/verification/domain/detectDrift.ts +166 -0
- package/src/features/verification/domain/verifiedCoverage.ts +37 -0
- package/src/features/verification/infrastructure/persistence/FileBehavioralIndexReader.ts +81 -0
- package/src/features/verification/infrastructure/persistence/StaticBehavioralIndexReader.ts +15 -0
- package/src/features/verification/presentation/components/VerifyPanel.svelte +74 -0
- package/src/features/verification/presentation/stores/verificationStore.svelte.ts +64 -0
- package/src/hooks.server.ts +11 -1
- package/src/lib/server/openLocalDirectory.ts +40 -0
- package/src/lib/server/searchIndex.ts +161 -0
- package/src/lib/server/snapshotRepository.ts +37 -37
- package/src/lib/server/sync/YDocManager.ts +391 -391
- package/src/lib/server/sync/historyStore.ts +276 -276
- package/src/lib/server/sync/wsServer.ts +1 -1
- package/src/lib/sync/protocol.ts +147 -147
- package/src/lib/sync/roomId.ts +33 -33
- package/src/lib/theme/registry.ts +77 -0
- package/src/lib/theme/themeStore.svelte.ts +64 -0
- package/src/routes/+layout.svelte +288 -30
- package/src/routes/api/domains/[id]/+server.ts +7 -3
- package/src/routes/api/projects/[id]/+server.ts +14 -4
- package/src/routes/api/projects/import/+server.ts +16 -38
- package/src/routes/api/search-index/+server.ts +16 -0
- package/src/routes/api/snapshots/[id]/+server.ts +56 -44
- package/src/routes/api/snapshots/[id]/implementation-status/+server.ts +13 -13
- package/src/routes/api/snapshots/[id]/verify/+server.ts +37 -0
- package/src/routes/api/sync/reload/+server.ts +157 -157
- package/src/routes/api/system/hub-directory/+server.ts +24 -0
- package/src/routes/features/+page.svelte +484 -484
- package/src/routes/features/[id]/+page.svelte +55 -49
- package/src/routes/features/[id]/graph/+page.svelte +39 -0
- package/src/routes/features/[id]/verify/+page.svelte +89 -0
- package/src/routes/mcp/+page.svelte +16 -1
- package/src/routes/projects/[id]/+page.svelte +70 -70
- package/src/routes/projects/[id]/graph/+page.svelte +79 -0
- package/src/routes/tutorial/+page.svelte +3 -2
- package/src/shared/infrastructure/browserContainer.ts +61 -61
- package/src/shared/presentation/components/KebabMenu.svelte +95 -0
- package/src/shared/presentation/components/MenuItem.svelte +29 -0
- package/src/shared/presentation/components/ProgressBar.svelte +1 -1
- package/src/shared/presentation/toast/SyncToast.svelte +14 -3
- package/src/shared/presentation/toast/viewLinkResolver.ts +32 -0
- package/static/lyriks_logo.svg +148 -0
- package/vite.config.ts +47 -47
- package/build/client/_app/immutable/assets/0.DFMDYAU9.css +0 -1
- package/build/client/_app/immutable/assets/0.DFMDYAU9.css.br +0 -0
- package/build/client/_app/immutable/assets/0.DFMDYAU9.css.gz +0 -0
- package/build/client/_app/immutable/assets/9.nv0I59TU.css.gz +0 -0
- package/build/client/_app/immutable/chunks/BO66rBOa2.js +0 -1
- package/build/client/_app/immutable/chunks/BO66rBOa2.js.br +0 -0
- package/build/client/_app/immutable/chunks/BO66rBOa2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BOrLmFwJ.js.br +0 -0
- package/build/client/_app/immutable/chunks/BOrLmFwJ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BfMYiIUi.js.br +0 -0
- package/build/client/_app/immutable/chunks/BfMYiIUi.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bp2_Vghh.js +0 -1
- package/build/client/_app/immutable/chunks/Bp2_Vghh.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bp2_Vghh.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bp8HpEPe2.js +0 -4
- package/build/client/_app/immutable/chunks/Bp8HpEPe2.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bp8HpEPe2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C8rRKIXT.js +0 -1
- package/build/client/_app/immutable/chunks/C8rRKIXT.js.br +0 -0
- package/build/client/_app/immutable/chunks/C8rRKIXT.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CJjJLwzv2.js +0 -1
- package/build/client/_app/immutable/chunks/CJjJLwzv2.js.br +0 -0
- package/build/client/_app/immutable/chunks/CJjJLwzv2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CxyLMlpt2.js.br +0 -0
- package/build/client/_app/immutable/chunks/CxyLMlpt2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D6jhrpTg.js +0 -1
- package/build/client/_app/immutable/chunks/D6jhrpTg.js.br +0 -0
- package/build/client/_app/immutable/chunks/D6jhrpTg.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D8YEa1po.js +0 -1
- package/build/client/_app/immutable/chunks/D8YEa1po.js.br +0 -0
- package/build/client/_app/immutable/chunks/D8YEa1po.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D9dKmajw.js +0 -1
- package/build/client/_app/immutable/chunks/D9dKmajw.js.br +0 -0
- package/build/client/_app/immutable/chunks/D9dKmajw.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DBJWcC6Y.js +0 -1
- package/build/client/_app/immutable/chunks/DBJWcC6Y.js.br +0 -0
- package/build/client/_app/immutable/chunks/DBJWcC6Y.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DHoA038D.js +0 -1
- package/build/client/_app/immutable/chunks/DHoA038D.js.br +0 -2
- package/build/client/_app/immutable/chunks/DHoA038D.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DKgYpi6_.js +0 -1
- package/build/client/_app/immutable/chunks/DKgYpi6_.js.br +0 -0
- package/build/client/_app/immutable/chunks/DKgYpi6_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DatGSObE.js +0 -1
- package/build/client/_app/immutable/chunks/DatGSObE.js.br +0 -0
- package/build/client/_app/immutable/chunks/DatGSObE.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dg0acPpT.js +0 -1
- package/build/client/_app/immutable/chunks/Dg0acPpT.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dg0acPpT.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DjWKKtqp.js +0 -1
- package/build/client/_app/immutable/chunks/DjWKKtqp.js.br +0 -1
- package/build/client/_app/immutable/chunks/DjWKKtqp.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dq0DUAz1.js +0 -1
- package/build/client/_app/immutable/chunks/Dq0DUAz1.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dq0DUAz1.js.gz +0 -0
- package/build/client/_app/immutable/chunks/HKLi1Yz3.js +0 -1
- package/build/client/_app/immutable/chunks/HKLi1Yz3.js.br +0 -0
- package/build/client/_app/immutable/chunks/HKLi1Yz3.js.gz +0 -0
- package/build/client/_app/immutable/chunks/N7PXjlRH.js +0 -1
- package/build/client/_app/immutable/chunks/N7PXjlRH.js.br +0 -0
- package/build/client/_app/immutable/chunks/N7PXjlRH.js.gz +0 -0
- package/build/client/_app/immutable/chunks/hpWJNn0t2.js +0 -2
- package/build/client/_app/immutable/chunks/hpWJNn0t2.js.br +0 -0
- package/build/client/_app/immutable/chunks/hpWJNn0t2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/iQu0D9Ux.js +0 -1
- package/build/client/_app/immutable/chunks/iQu0D9Ux.js.br +0 -0
- package/build/client/_app/immutable/chunks/iQu0D9Ux.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.CLgh6Mx_.js +0 -2
- package/build/client/_app/immutable/entry/app.CLgh6Mx_.js.br +0 -0
- package/build/client/_app/immutable/entry/app.CLgh6Mx_.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.D5GPCQZD.js +0 -1
- package/build/client/_app/immutable/entry/start.D5GPCQZD.js.br +0 -0
- package/build/client/_app/immutable/entry/start.D5GPCQZD.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.BOoI-hsu.js +0 -4
- package/build/client/_app/immutable/nodes/0.BOoI-hsu.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.BOoI-hsu.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.KYdA6ppX.js.br +0 -2
- package/build/client/_app/immutable/nodes/1.KYdA6ppX.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.DBz20KgG.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.DBz20KgG.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.19DIoFtw.js +0 -1
- package/build/client/_app/immutable/nodes/3.19DIoFtw.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.19DIoFtw.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.BvMzqBJj.js +0 -3
- package/build/client/_app/immutable/nodes/4.BvMzqBJj.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.BvMzqBJj.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.Dq6obSGG.js +0 -42
- package/build/client/_app/immutable/nodes/5.Dq6obSGG.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.Dq6obSGG.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.BOHISqs-.js +0 -5
- package/build/client/_app/immutable/nodes/6.BOHISqs-.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.BOHISqs-.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.CemgNJfw.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.CemgNJfw.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.DejSfIYh.js +0 -5
- package/build/client/_app/immutable/nodes/8.DejSfIYh.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.DejSfIYh.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.CMW6a2Lg.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.CMW6a2Lg.js.gz +0 -0
- package/build/server/chunks/0-C_o0oz-N.js +0 -15
- package/build/server/chunks/0-C_o0oz-N.js.map +0 -1
- package/build/server/chunks/1-DPpKAKXV.js +0 -9
- package/build/server/chunks/2-AlfFqtL1.js +0 -9
- package/build/server/chunks/2-AlfFqtL1.js.map +0 -1
- package/build/server/chunks/3-vbjUt_51.js +0 -16
- package/build/server/chunks/3-vbjUt_51.js.map +0 -1
- package/build/server/chunks/4-BNow4x6D.js +0 -16
- package/build/server/chunks/4-BNow4x6D.js.map +0 -1
- package/build/server/chunks/5-D7OCJpxD.js +0 -9
- package/build/server/chunks/5-D7OCJpxD.js.map +0 -1
- package/build/server/chunks/6-QQ7r8Rd5.js +0 -9
- package/build/server/chunks/7-CbPLGaIG.js +0 -9
- package/build/server/chunks/7-CbPLGaIG.js.map +0 -1
- package/build/server/chunks/8-CVO-E-sf.js +0 -9
- package/build/server/chunks/8-CVO-E-sf.js.map +0 -1
- package/build/server/chunks/9-DxT1baO5.js +0 -9
- package/build/server/chunks/9-DxT1baO5.js.map +0 -1
- package/build/server/chunks/FeatureTransforms-UWDHmWEg.js.map +0 -1
- package/build/server/chunks/FeatureValidator-B8qEjAUW.js.map +0 -1
- package/build/server/chunks/ManageTagsDialog-DBxA3tM2.js.map +0 -1
- package/build/server/chunks/ProgressBar-CfhccQ83.js.map +0 -1
- package/build/server/chunks/ProjectsIndex-CoDrvRya.js.map +0 -1
- package/build/server/chunks/RenameTag-BuWLMl1m.js.map +0 -1
- package/build/server/chunks/TagDotStrip-B1XQ0m0Y.js.map +0 -1
- package/build/server/chunks/TagPalette-CtMNYCmu.js.map +0 -1
- package/build/server/chunks/_layout.svelte-BREws55o.js +0 -616
- package/build/server/chunks/_layout.svelte-BREws55o.js.map +0 -1
- package/build/server/chunks/_page.svelte-B1s7jxaQ.js.map +0 -1
- package/build/server/chunks/_page.svelte-B7hT3P8E.js +0 -29
- package/build/server/chunks/_page.svelte-BqSC-1vK.js.map +0 -1
- package/build/server/chunks/_page.svelte-BtI2zZ_Z.js.map +0 -1
- package/build/server/chunks/_page.svelte-De508ek8.js +0 -29
- package/build/server/chunks/_page.svelte-Zf9H4KOP.js.map +0 -1
- package/build/server/chunks/_server.ts-0uNTZKwF.js.map +0 -1
- package/build/server/chunks/_server.ts-DcZPhyhK.js +0 -59
- package/build/server/chunks/_server.ts-DcZPhyhK.js.map +0 -1
- package/build/server/chunks/_server.ts-Dy5zQHe2.js.map +0 -1
- package/build/server/chunks/_server.ts-YnfXkeMJ.js.map +0 -1
- package/build/server/chunks/_server.ts-vcaqdwxS.js.map +0 -1
- package/build/server/chunks/browserContainer-CNX7ANld.js.map +0 -1
- package/build/server/chunks/builderModeStore.svelte-ihupr-3p.js.map +0 -1
- package/build/server/chunks/client-DfpLcAZ9.js +0 -24
- package/build/server/chunks/featuresStore.svelte-DR1gYZyu.js +0 -98
- package/build/server/chunks/featuresStore.svelte-DR1gYZyu.js.map +0 -1
- package/build/server/chunks/hooks.server-Rv301GTB.js.map +0 -1
- package/build/server/chunks/identityStore.svelte-IIvW2_3b.js +0 -59
- package/build/server/chunks/identityStore.svelte-IIvW2_3b.js.map +0 -1
- package/build/server/chunks/projectsStore.svelte-QDz5PchX.js.map +0 -1
- package/build/server/chunks/reconcile-Dv7jS3C8.js.map +0 -1
- package/build/server/chunks/snapshotRepository-BPXCjX92.js.map +0 -1
- package/build/server/chunks/syncBridge-BwXzPdjJ.js.map +0 -1
- package/src/features/implementation-queue/presentation/components/QueuePanel.svelte +0 -204
- package/src/features/implementation-queue/presentation/stores/queueStore.svelte.ts +0 -143
- /package/build/client/_app/immutable/assets/{9.nv0I59TU.css → 12.nv0I59TU.css} +0 -0
- /package/build/client/_app/immutable/assets/{9.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
|
+
};
|
|
@@ -3,7 +3,9 @@ import { existsSync } from 'node:fs';
|
|
|
3
3
|
import { dirname, resolve } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { discoverSnapshotDirectory } from '../../src/features/behavior-model/infrastructure/persistence/snapshot-discovery';
|
|
6
|
+
import { parseThemeId } from '../../src/lib/theme/registry';
|
|
6
7
|
import { readEnabledViews } from '../util/views';
|
|
8
|
+
import { readSelectedTheme } from '../util/theme';
|
|
7
9
|
import { log } from '../util/log';
|
|
8
10
|
|
|
9
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -45,6 +47,7 @@ export const runDashboardCommand = async (
|
|
|
45
47
|
readonly host?: string;
|
|
46
48
|
readonly snapshots?: string;
|
|
47
49
|
readonly views?: string;
|
|
50
|
+
readonly theme?: string;
|
|
48
51
|
}
|
|
49
52
|
): Promise<number> => {
|
|
50
53
|
const repoRoot = resolve(__dirname, '..', '..');
|
|
@@ -126,6 +129,17 @@ export const runDashboardCommand = async (
|
|
|
126
129
|
log.dim(`Views: expert + ${views.join(', ')}`);
|
|
127
130
|
}
|
|
128
131
|
|
|
132
|
+
// Colour theme (cosmetic). A `--theme` flag overrides the persisted choice
|
|
133
|
+
// (`unspa theme set`) for this run; both feed the app as PUBLIC_UNSPA_THEME,
|
|
134
|
+
// which seeds the no-flash server-rendered <html data-theme>. The in-app
|
|
135
|
+
// switcher can still change it live in the browser. Unknown ids fall back to
|
|
136
|
+
// the default, so a typo never blanks the UI.
|
|
137
|
+
const theme = parseThemeId(args.theme ?? readSelectedTheme(directory));
|
|
138
|
+
if (theme !== 'default') {
|
|
139
|
+
env.PUBLIC_UNSPA_THEME = theme;
|
|
140
|
+
log.dim(`Theme: ${theme}`);
|
|
141
|
+
}
|
|
142
|
+
|
|
129
143
|
return await new Promise<number>((resolvePromise) => {
|
|
130
144
|
const child = spawn(process.execPath, [serverShim], {
|
|
131
145
|
stdio: 'inherit',
|
package/cli/commands/init.ts
CHANGED
|
@@ -7,12 +7,14 @@ import { ALL_CLIENTS, clientById, SERVER_NAME, type ClientAdapter } from '../cli
|
|
|
7
7
|
import { buildUnspaMcpEntry } from '../clients/claude-code';
|
|
8
8
|
import type { ApplyResult, ConfigScope, McpServerEntry } from '../clients/types';
|
|
9
9
|
import { isOptionalViewId, optionalViews } from '../../src/lib/views/registry';
|
|
10
|
+
import { isThemeId, parseThemeId } from '../../src/lib/theme/registry';
|
|
10
11
|
import { ask } from '../util/ask';
|
|
11
12
|
import { writeUnspaContextBlocks } from '../util/context-files';
|
|
12
13
|
import { upsertGitignoreBlock } from '../util/gitignore';
|
|
13
14
|
import { log } from '../util/log';
|
|
14
15
|
import { installUnspaSkills } from '../util/skills';
|
|
15
16
|
import { readEnabledViews, writeEnabledViews } from '../util/views';
|
|
17
|
+
import { writeSelectedTheme } from '../util/theme';
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Expand a user-supplied hub path: tilde-expansion, relative→absolute (resolved
|
|
@@ -119,6 +121,13 @@ export type InitOptions = {
|
|
|
119
121
|
* always on regardless.
|
|
120
122
|
*/
|
|
121
123
|
readonly withViews?: string;
|
|
124
|
+
/**
|
|
125
|
+
* Dashboard colour theme to persist at setup (e.g. "lyriks"). Cosmetic only;
|
|
126
|
+
* written to `<snapshots>/theme.json`, same as `unspa theme set`, so
|
|
127
|
+
* `unspa dashboard` boots with it. The in-app header switcher can change it
|
|
128
|
+
* live later. Unknown ids fall back to the default with a warning.
|
|
129
|
+
*/
|
|
130
|
+
readonly theme?: string;
|
|
122
131
|
};
|
|
123
132
|
|
|
124
133
|
const resolveClientsArg = async (
|
|
@@ -338,6 +347,23 @@ export const runInitCommand = async (options: InitOptions = {}): Promise<number>
|
|
|
338
347
|
log.dim('Shows as a view switcher in `unspa dashboard`. Turn off later with `unspa view remove <id>`.');
|
|
339
348
|
}
|
|
340
349
|
|
|
350
|
+
// 1c. Optional colour theme. Cosmetic only — persists the chosen skin into
|
|
351
|
+
// `<snapshots>/theme.json` so `unspa dashboard` boots with it. An unknown
|
|
352
|
+
// id is a no-op (keeps the default) with a warning rather than a hard
|
|
353
|
+
// fail. Switchable later via `unspa theme set` or the in-app switcher.
|
|
354
|
+
if (options.theme !== undefined) {
|
|
355
|
+
const raw = options.theme.trim().toLowerCase();
|
|
356
|
+
if (raw && raw !== 'default' && !isThemeId(raw)) {
|
|
357
|
+
log.warn(`Unknown theme "${raw}" — keeping the default theme.`);
|
|
358
|
+
}
|
|
359
|
+
const id = parseThemeId(options.theme);
|
|
360
|
+
writeSelectedTheme(target.dir, id);
|
|
361
|
+
if (id !== 'default') {
|
|
362
|
+
log.ok(`Dashboard theme set to ${pc.cyan(id)}.`);
|
|
363
|
+
log.dim('Cosmetic skin. Change it with `unspa theme set <id>` or the dashboard header switcher.');
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
341
367
|
// 2. Pick clients, write MCP server entry. `mergeMcpServerEntry` compares
|
|
342
368
|
// before writing so re-runs are a no-op when nothing changed. Detection
|
|
343
369
|
// is scoped to this cwd/home so the pre-selection (interactive) and the
|
|
@@ -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,62 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
import { discoverSnapshotDirectory } from '../../src/features/behavior-model/infrastructure/persistence/snapshot-discovery';
|
|
3
|
+
import { ALL_THEMES, isThemeId, parseThemeId } from '../../src/lib/theme/registry';
|
|
4
|
+
import { readSelectedTheme, writeSelectedTheme } from '../util/theme';
|
|
5
|
+
import { log } from '../util/log';
|
|
6
|
+
|
|
7
|
+
export type ThemeCommandOptions = {
|
|
8
|
+
readonly action: 'list' | 'set' | 'reset';
|
|
9
|
+
readonly id?: string;
|
|
10
|
+
readonly cwd?: string;
|
|
11
|
+
readonly snapshots?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const known = (): string => ALL_THEMES.map((t) => t.id).join(', ');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Pick the dashboard's colour theme. Purely cosmetic: it only changes which
|
|
18
|
+
* skin the design system renders with, never a feature. The selection persists
|
|
19
|
+
* in `<snapshots>/theme.json` so `unspa dashboard` boots with it; the in-app
|
|
20
|
+
* header switcher can flip it live in the browser without touching this file.
|
|
21
|
+
*/
|
|
22
|
+
export const runThemeCommand = async (options: ThemeCommandOptions): Promise<number> => {
|
|
23
|
+
const cwd = options.cwd ?? process.cwd();
|
|
24
|
+
const { directory, source } = discoverSnapshotDirectory({ cwd, override: options.snapshots });
|
|
25
|
+
const active = parseThemeId(readSelectedTheme(directory));
|
|
26
|
+
|
|
27
|
+
if (options.action === 'list') {
|
|
28
|
+
log.step(`Themes for ${pc.cyan(directory)} (${source})`);
|
|
29
|
+
log.dim(`Active default: ${pc.cyan(active)}`);
|
|
30
|
+
for (const theme of ALL_THEMES) {
|
|
31
|
+
const on = active === theme.id;
|
|
32
|
+
const marker = on ? pc.green('● active') : pc.dim('○ ');
|
|
33
|
+
process.stdout.write(`${marker} ${pc.cyan(theme.label)} ${pc.dim(`(${theme.id})`)} — ${theme.description}\n`);
|
|
34
|
+
}
|
|
35
|
+
log.blank();
|
|
36
|
+
log.dim('Set with `unspa theme set <id>`, revert with `unspa theme reset`.');
|
|
37
|
+
log.dim('Or flip it live from the dashboard header (the palette button).');
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (options.action === 'reset') {
|
|
42
|
+
writeSelectedTheme(directory, 'default');
|
|
43
|
+
log.ok('Theme reset to default.');
|
|
44
|
+
log.dim('Restart `unspa dashboard` to apply (or use the in-app switcher).');
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// set
|
|
49
|
+
const id = (options.id ?? '').trim().toLowerCase();
|
|
50
|
+
if (!id) {
|
|
51
|
+
log.err(`Missing theme id. Known themes: ${known()}.`);
|
|
52
|
+
return 1;
|
|
53
|
+
}
|
|
54
|
+
if (!isThemeId(id)) {
|
|
55
|
+
log.err(`Unknown theme "${id}". Known themes: ${known()}.`);
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
const next = writeSelectedTheme(directory, id);
|
|
59
|
+
log.ok(`Theme set to ${pc.cyan(next)}.`);
|
|
60
|
+
log.dim('Restart `unspa dashboard` to apply, or switch live via the dashboard header.');
|
|
61
|
+
return 0;
|
|
62
|
+
};
|
|
@@ -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
|
+
};
|
package/cli/scenarios/codegen.ts
CHANGED
|
@@ -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
|