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.
- 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.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.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/{DkxwAIfJ2.js → DryaQyjN2.js} +1 -1
- 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/{B_9TWPrx2.js → Vu8LzrwP2.js} +1 -1
- 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/{B439_FLv.js → wrqalH0a.js} +1 -1
- 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.Dyte3Ggf.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/{11.wvMfJKC2.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.CmPPom9Z.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/{8.B-HweAc8.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.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-BSUItTig.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/{7-C4hmS0dG.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-m5kYj5HH.js → BehaviorGraph-C-9z37Sm.js} +43 -12
- 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-CfbXNYe8.js → FeatureCard-Bb50FEfp.js} +4 -4
- package/build/server/chunks/{FeatureCard-CfbXNYe8.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-DDoQJ_C9.js → ProgressBar-CUC2EZqG.js} +2 -2
- package/build/server/chunks/{ProgressBar-DDoQJ_C9.js.map → ProgressBar-CUC2EZqG.js.map} +1 -1
- package/build/server/chunks/{ProjectsIndex-DUVJ3hyL.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-B8zHs-2E.js → TransitionCatalog-CYXUANy6.js} +2 -2
- package/build/server/chunks/TransitionCatalog-CYXUANy6.js.map +1 -0
- package/build/server/chunks/{_layout.svelte-CLTmk0xU.js → _layout.svelte-pSSG85WT.js} +689 -14
- package/build/server/chunks/_layout.svelte-pSSG85WT.js.map +1 -0
- package/build/server/chunks/{_page.svelte-Oj-W7G5s.js → _page.svelte-BNH3szkk.js} +22 -17
- package/build/server/chunks/{_page.svelte-Oj-W7G5s.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-Cham-dsM.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-B1nG3PKn.js.map → _page.svelte-BoOMG5Y0.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-Caq7J0jU.js → _page.svelte-C4PRh_wP.js} +18 -12
- package/build/server/chunks/_page.svelte-C4PRh_wP.js.map +1 -0
- package/build/server/chunks/{_page.svelte-Z_kK2lHY.js → _page.svelte-Cqn34NXy.js} +19 -13
- 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-Dhwjwph_.js → _page.svelte-DsQHSEl4.js} +20 -12
- package/build/server/chunks/_page.svelte-DsQHSEl4.js.map +1 -0
- package/build/server/chunks/{_page.svelte-DlFVT40-.js → _page.svelte-Uioz8hsG.js} +18 -11
- package/build/server/chunks/{_page.svelte-DlFVT40-.js.map → _page.svelte-Uioz8hsG.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-BW_nbAAH.js → _page.svelte-p38jot9e.js} +80 -173
- package/build/server/chunks/_page.svelte-p38jot9e.js.map +1 -0
- package/build/server/chunks/{_page.svelte-NVT2dzpG.js → _page.svelte-yN5kzgJ9.js} +218 -263
- 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-BpRIU_zP.js → builderModeStore.svelte-BEZMQEqn.js} +7 -6
- package/build/server/chunks/builderModeStore.svelte-BEZMQEqn.js.map +1 -0
- package/build/server/chunks/{client-DeX3TC3s.js → client-C9Cat4DK.js} +3 -3
- package/build/server/chunks/{client-DeX3TC3s.js.map → client-C9Cat4DK.js.map} +1 -1
- package/build/server/chunks/{error.svelte-Cdjeq3L2.js → error.svelte-CzVR_A6P.js} +5 -5
- package/build/server/chunks/{error.svelte-Cdjeq3L2.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-DIYgPBVm.js → featureStore.svelte-DHZf88gu.js} +5 -4
- 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/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-KYK0WpL7.js → internal-BFt8yDlf.js} +3 -3
- package/build/server/chunks/{internal-KYK0WpL7.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/{projectFeaturesStore.svelte-2o-72_vr.js → projectStore.svelte-BNuLNxk_.js} +5 -88
- package/build/server/chunks/projectStore.svelte-BNuLNxk_.js.map +1 -0
- package/build/server/chunks/{reconcile-B5xqb6-s.js → reconcile-CVG2LSlW.js} +60 -4
- package/build/server/chunks/reconcile-CVG2LSlW.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-DBjl9lhV.js → state-CZZtjXLE.js} +3 -3
- package/build/server/chunks/{state-DBjl9lhV.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 +59 -30
- 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/scenarios-adapter.ts +96 -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 +98 -0
- package/cli/util/context-files.ts +13 -2
- 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 -180
- 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 +14 -2
- package/src/app.css +26 -14
- 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 +25 -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 +10 -1
- 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 +275 -77
- 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 +152 -143
- 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 +1 -0
- package/src/features/behavior-model/presentation/view-models/factories.ts +181 -132
- 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 +17 -20
- 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 +12 -0
- 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/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/routes/+layout.svelte +104 -0
- 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 +5 -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/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/vite.config.ts +47 -47
- package/build/client/_app/immutable/assets/0.DSctqr5I.css +0 -1
- package/build/client/_app/immutable/assets/0.DSctqr5I.css.br +0 -0
- package/build/client/_app/immutable/assets/0.DSctqr5I.css.gz +0 -0
- package/build/client/_app/immutable/assets/11.nv0I59TU.css.gz +0 -0
- package/build/client/_app/immutable/chunks/9nXQ5qrY2.js +0 -1
- package/build/client/_app/immutable/chunks/9nXQ5qrY2.js.br +0 -0
- package/build/client/_app/immutable/chunks/9nXQ5qrY2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B439_FLv.js.br +0 -0
- package/build/client/_app/immutable/chunks/B439_FLv.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BCEY79Dw.js +0 -1
- package/build/client/_app/immutable/chunks/BCEY79Dw.js.br +0 -2
- package/build/client/_app/immutable/chunks/BCEY79Dw.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/BYIrIC5L.js +0 -1
- package/build/client/_app/immutable/chunks/BYIrIC5L.js.br +0 -0
- package/build/client/_app/immutable/chunks/BYIrIC5L.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B_9TWPrx2.js.br +0 -0
- package/build/client/_app/immutable/chunks/B_9TWPrx2.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/BvOhVtZg.js +0 -1
- package/build/client/_app/immutable/chunks/BvOhVtZg.js.br +0 -1
- package/build/client/_app/immutable/chunks/BvOhVtZg.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/CY3em1ma2.js +0 -1
- package/build/client/_app/immutable/chunks/CY3em1ma2.js.br +0 -0
- package/build/client/_app/immutable/chunks/CY3em1ma2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CgdRZPgI.js +0 -1
- package/build/client/_app/immutable/chunks/CgdRZPgI.js.br +0 -0
- package/build/client/_app/immutable/chunks/CgdRZPgI.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/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/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/DkxwAIfJ2.js.br +0 -0
- package/build/client/_app/immutable/chunks/DkxwAIfJ2.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/OJscNS3T.js +0 -1
- package/build/client/_app/immutable/chunks/OJscNS3T.js.br +0 -0
- package/build/client/_app/immutable/chunks/OJscNS3T.js.gz +0 -0
- package/build/client/_app/immutable/chunks/U9p9CtKG2.js +0 -2
- package/build/client/_app/immutable/chunks/U9p9CtKG2.js.br +0 -0
- package/build/client/_app/immutable/chunks/U9p9CtKG2.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/entry/app.Cd4S3giu.js +0 -2
- package/build/client/_app/immutable/entry/app.Cd4S3giu.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Cd4S3giu.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.C3xXQVkq.js +0 -1
- package/build/client/_app/immutable/entry/start.C3xXQVkq.js.br +0 -0
- package/build/client/_app/immutable/entry/start.C3xXQVkq.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.dIOlQ-0y.js +0 -4
- package/build/client/_app/immutable/nodes/0.dIOlQ-0y.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.dIOlQ-0y.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.Dyte3Ggf.js.br +0 -2
- package/build/client/_app/immutable/nodes/1.Dyte3Ggf.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.ivxAosDg.js +0 -2
- package/build/client/_app/immutable/nodes/10.ivxAosDg.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.ivxAosDg.js.gz +0 -0
- package/build/client/_app/immutable/nodes/11.wvMfJKC2.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.wvMfJKC2.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.CmPPom9Z.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.CmPPom9Z.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.D-iCGCEx.js +0 -1
- package/build/client/_app/immutable/nodes/3.D-iCGCEx.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.D-iCGCEx.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.DbfAvO8Z.js +0 -3
- package/build/client/_app/immutable/nodes/4.DbfAvO8Z.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.DbfAvO8Z.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.CC5Q7lVw.js +0 -42
- package/build/client/_app/immutable/nodes/5.CC5Q7lVw.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.CC5Q7lVw.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.CHIjlzpO.js +0 -1
- package/build/client/_app/immutable/nodes/6.CHIjlzpO.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.CHIjlzpO.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.Ejs18ZUc.js +0 -5
- package/build/client/_app/immutable/nodes/7.Ejs18ZUc.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.Ejs18ZUc.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.B-HweAc8.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.B-HweAc8.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.CKPeM6tx.js +0 -5
- package/build/client/_app/immutable/nodes/9.CKPeM6tx.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.CKPeM6tx.js.gz +0 -0
- package/build/server/chunks/0-Co8kcANG.js +0 -15
- package/build/server/chunks/0-Co8kcANG.js.map +0 -1
- package/build/server/chunks/1-BSUItTig.js +0 -9
- package/build/server/chunks/10-BygvxrZp.js +0 -9
- package/build/server/chunks/10-BygvxrZp.js.map +0 -1
- package/build/server/chunks/11-DRx0tRx2.js +0 -9
- package/build/server/chunks/11-DRx0tRx2.js.map +0 -1
- package/build/server/chunks/2-BQT3m1vc.js +0 -9
- package/build/server/chunks/2-BQT3m1vc.js.map +0 -1
- package/build/server/chunks/3-DPZ9BquJ.js +0 -16
- package/build/server/chunks/3-DPZ9BquJ.js.map +0 -1
- package/build/server/chunks/4-DHo47YX6.js +0 -16
- package/build/server/chunks/4-DHo47YX6.js.map +0 -1
- package/build/server/chunks/5-Cp9evBAG.js +0 -9
- package/build/server/chunks/5-Cp9evBAG.js.map +0 -1
- package/build/server/chunks/6-DiBq3bOV.js +0 -9
- package/build/server/chunks/6-DiBq3bOV.js.map +0 -1
- package/build/server/chunks/7-C4hmS0dG.js +0 -9
- package/build/server/chunks/8-CFFuDzBC.js +0 -9
- package/build/server/chunks/8-CFFuDzBC.js.map +0 -1
- package/build/server/chunks/9-nhhKZJrs.js +0 -9
- package/build/server/chunks/9-nhhKZJrs.js.map +0 -1
- package/build/server/chunks/BehaviorGraph-m5kYj5HH.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/ProjectsIndex-DUVJ3hyL.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/TransitionCatalog-B8zHs-2E.js.map +0 -1
- package/build/server/chunks/_layout.svelte-CLTmk0xU.js.map +0 -1
- package/build/server/chunks/_page.svelte-B1nG3PKn.js +0 -29
- package/build/server/chunks/_page.svelte-B1s7jxaQ.js.map +0 -1
- package/build/server/chunks/_page.svelte-BW_nbAAH.js.map +0 -1
- package/build/server/chunks/_page.svelte-Caq7J0jU.js.map +0 -1
- package/build/server/chunks/_page.svelte-Cham-dsM.js +0 -29
- package/build/server/chunks/_page.svelte-Dhwjwph_.js.map +0 -1
- package/build/server/chunks/_page.svelte-NVT2dzpG.js.map +0 -1
- package/build/server/chunks/_page.svelte-Z_kK2lHY.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-BpRIU_zP.js.map +0 -1
- package/build/server/chunks/featureStore.svelte-DIYgPBVm.js.map +0 -1
- 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/identityStore.svelte-IIvW2_3b.js +0 -59
- package/build/server/chunks/identityStore.svelte-IIvW2_3b.js.map +0 -1
- package/build/server/chunks/projectFeaturesStore.svelte-2o-72_vr.js.map +0 -1
- package/build/server/chunks/projectsStore.svelte-QDz5PchX.js.map +0 -1
- package/build/server/chunks/reconcile-B5xqb6-s.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/{11.nv0I59TU.css → 12.nv0I59TU.css} +0 -0
- /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
|
+
};
|
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
|
|
@@ -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[]`,
|
|
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`, `
|
|
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
|