@ultrst-armada/krnl 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/README.md +67 -65
  2. package/package.json +13 -9
  3. package/packages/cli/dist/bin/krnl.cjs +1535 -9508
  4. package/packages/cli/dist/bin/krnl.js +55 -1915
  5. package/packages/cli/dist/chunk-6SHSECXR.js +1628 -0
  6. package/packages/cli/dist/index.cjs +1244 -7373
  7. package/packages/cli/dist/index.d.cts +45 -2
  8. package/packages/cli/dist/index.d.ts +45 -2
  9. package/packages/cli/dist/index.js +5 -20
  10. package/packages/cli/package.json +17 -10
  11. package/packages/core/dist/index.cjs +3039 -141
  12. package/packages/core/dist/index.d.cts +633 -27
  13. package/packages/core/dist/index.d.ts +633 -27
  14. package/packages/core/dist/index.js +3028 -139
  15. package/packages/core/package.json +15 -7
  16. package/packages/create-krnl/dist/index.cjs +322 -316
  17. package/packages/create-krnl/dist/index.js +322 -316
  18. package/packages/create-krnl/package.json +5 -3
  19. package/packages/eslint-plugin/dist/index.cjs +17 -55
  20. package/packages/eslint-plugin/dist/index.d.cts +8 -43
  21. package/packages/eslint-plugin/dist/index.d.ts +8 -43
  22. package/packages/eslint-plugin/dist/index.js +17 -55
  23. package/packages/eslint-plugin/package.json +5 -4
  24. package/packages/validate/dist/index.cjs +692 -361
  25. package/packages/validate/dist/index.d.cts +12 -14
  26. package/packages/validate/dist/index.d.ts +12 -14
  27. package/packages/validate/dist/index.js +692 -361
  28. package/packages/validate/package.json +14 -7
  29. package/packages/cli/dist/K_ENT_Entity-PQ5MURQY-ZG6FZXXX.js +0 -13
  30. package/packages/cli/dist/K_LIB_Krnl_Aiko_Client-OPZAVZCW-K4CRQYA5.js +0 -8
  31. package/packages/cli/dist/K_LIB_Krnl_Ep_Tools-ROOE2TQF-LNPXZYOE.js +0 -110
  32. package/packages/cli/dist/K_LIB_Krnl_Frontend_Builder-2ZDUH6PF-3ALZPNX4.js +0 -11
  33. package/packages/cli/dist/K_LIB_Krnl_Frontend_Generator-UYNRNX2X-PJTICYSW.js +0 -11
  34. package/packages/cli/dist/K_LIB_Krnl_Registry_Client-NXV6D2QW-M5TYU55O.js +0 -8
  35. package/packages/cli/dist/K_LIB_Krnl_SubApp_Engine-7HR5HWW2-H6STOXRK.js +0 -20
  36. package/packages/cli/dist/K_LIB_Krnl_SubApp_Registry-7XYGDKJK-XPJXSF7D.js +0 -19
  37. package/packages/cli/dist/K_LIB_Krnl_SubApp_Worker_Host-CQVTGGG7-CUYGTWOW.js +0 -7
  38. package/packages/cli/dist/K_LIB_Krnl_System_App_Adapter-M6FJKLGU-VR6T4N6J.js +0 -17
  39. package/packages/cli/dist/K_LIB_Krnl_System_Base_Functionality_APIs-ZZUZ6ZG5-RLJ4QWDP.js +0 -58
  40. package/packages/cli/dist/K_LIB_Krnl_System_Magnetic_Loader-XBQO2KXF-BOQGUASC.js +0 -22
  41. package/packages/cli/dist/K_LIB_Krnl_System_Unified_Http_Adapter-RCEGP3OG-XJI7KIT5.js +0 -8
  42. package/packages/cli/dist/K_LIB_Krnl_Telemetry-77FRZ3KV-K5VCWAFW.js +0 -9
  43. package/packages/cli/dist/chunk-3TRM6CYL.js +0 -152
  44. package/packages/cli/dist/chunk-5JDK35TG.js +0 -3872
  45. package/packages/cli/dist/chunk-63PTK33I.js +0 -997
  46. package/packages/cli/dist/chunk-6NIKAMUZ.js +0 -82
  47. package/packages/cli/dist/chunk-BOXWWXQG.js +0 -400
  48. package/packages/cli/dist/chunk-EEKLK7QJ.js +0 -565
  49. package/packages/cli/dist/chunk-EG7T2IAD.js +0 -107
  50. package/packages/cli/dist/chunk-F5EHXE2O.js +0 -1036
  51. package/packages/cli/dist/chunk-F65ANSQG.js +0 -269
  52. package/packages/cli/dist/chunk-FDNCADFE.js +0 -71
  53. package/packages/cli/dist/chunk-GDLRMDAN.js +0 -127
  54. package/packages/cli/dist/chunk-HWMTCMOS.js +0 -656
  55. package/packages/cli/dist/chunk-I74QIQOD.js +0 -5536
  56. package/packages/cli/dist/chunk-JTLSTO25.js +0 -71
  57. package/packages/cli/dist/chunk-JULBBJ27.js +0 -1033
  58. package/packages/cli/dist/chunk-OHVMVRBP.js +0 -117
  59. package/packages/cli/dist/chunk-P2PCLEKX.js +0 -666
  60. package/packages/cli/dist/chunk-PJQIUOX2.js +0 -7767
  61. package/packages/cli/dist/chunk-PPOF3DJW.js +0 -471
  62. package/packages/cli/dist/chunk-Q45257P6.js +0 -173
  63. package/packages/cli/dist/chunk-QNROWGBI.js +0 -1036
  64. package/packages/cli/dist/chunk-RJNYUXZD.js +0 -977
  65. package/packages/cli/dist/chunk-SRTOPJ5W.js +0 -104
  66. package/packages/cli/dist/chunk-TCEX3MPS.js +0 -702
  67. package/packages/cli/dist/chunk-TNOAJO2J.js +0 -675
  68. package/packages/cli/dist/chunk-UR2SUCSF.js +0 -701
  69. package/packages/cli/dist/chunk-X5LOIFM7.js +0 -68
  70. package/packages/cli/dist/chunk-XIRFOO3H.js +0 -589
  71. package/packages/cli/dist/chunk-ZAAV3JXQ.js +0 -809
  72. package/packages/core/dist/K_ENT_Entity-4MB7CU4A.js +0 -12
  73. package/packages/core/dist/K_ENT_Entity-DEJGIDGH.js +0 -12
  74. package/packages/core/dist/K_ENT_Entity-FXZO5UZ2.js +0 -12
  75. package/packages/core/dist/K_ENT_Entity-HDSCXC5F.js +0 -12
  76. package/packages/core/dist/K_ENT_Entity-JILABHLW.js +0 -12
  77. package/packages/core/dist/K_ENT_Entity-PQ5MURQY.js +0 -13
  78. package/packages/core/dist/K_ENT_Entity-ROAKDIHW.js +0 -12
  79. package/packages/core/dist/K_ENT_Entity-TBVFSKDV.js +0 -12
  80. package/packages/core/dist/K_ENT_Entity-ZFLKG3JO.js +0 -12
  81. package/packages/core/dist/K_LIB_Krnl_Aiko_Client-OPZAVZCW.js +0 -8
  82. package/packages/core/dist/K_LIB_Krnl_Ep_Tools-ROOE2TQF.js +0 -110
  83. package/packages/core/dist/K_LIB_Krnl_Frontend_Builder-2ZDUH6PF.js +0 -9
  84. package/packages/core/dist/K_LIB_Krnl_Frontend_Generator-UYNRNX2X.js +0 -9
  85. package/packages/core/dist/K_LIB_Krnl_Registry_Client-NXV6D2QW.js +0 -8
  86. package/packages/core/dist/K_LIB_Krnl_SubApp_Engine-7HR5HWW2.js +0 -20
  87. package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-4C6GBQAG.js +0 -18
  88. package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-6V23A6F6.js +0 -18
  89. package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-7XYGDKJK.js +0 -19
  90. package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-DYLLC5G2.js +0 -18
  91. package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-F4FOFAUP.js +0 -18
  92. package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-FBOXXMI3.js +0 -18
  93. package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-Q73BWLNP.js +0 -18
  94. package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-QM2C4MVA.js +0 -18
  95. package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-QUGI6SMP.js +0 -18
  96. package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-RGMTBHNP.js +0 -18
  97. package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-RWR7UNDW.js +0 -18
  98. package/packages/core/dist/K_LIB_Krnl_SubApp_Worker_Host-CQVTGGG7.js +0 -7
  99. package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-32MFJJ5Z.js +0 -17
  100. package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-4J4CEWRY.js +0 -17
  101. package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-A366YHF2.js +0 -17
  102. package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-LK4LYJHI.js +0 -17
  103. package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-M6FJKLGU.js +0 -17
  104. package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-NW3K63II.js +0 -17
  105. package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-QDHTI5ZV.js +0 -17
  106. package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-VHCT6VIW.js +0 -17
  107. package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-WBRKF24R.js +0 -17
  108. package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-XKYQYT6Q.js +0 -17
  109. package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-Z2PWZYDZ.js +0 -17
  110. package/packages/core/dist/K_LIB_Krnl_System_Base_Functionality_APIs-ZZUZ6ZG5.js +0 -58
  111. package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-2EZU7QF4.js +0 -21
  112. package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-6G3AQNAV.js +0 -21
  113. package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-B2NZMQUG.js +0 -21
  114. package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-C2RABMZP.js +0 -21
  115. package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-HHE3NZ4F.js +0 -21
  116. package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-LHFGR6WK.js +0 -21
  117. package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-M74BLM3N.js +0 -21
  118. package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-PT6ZA6EA.js +0 -21
  119. package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-SP52V3CX.js +0 -21
  120. package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-XBQO2KXF.js +0 -22
  121. package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-YNSEUHJJ.js +0 -21
  122. package/packages/core/dist/K_LIB_Krnl_System_Unified_Http_Adapter-M6SBHIVA.js +0 -8
  123. package/packages/core/dist/K_LIB_Krnl_System_Unified_Http_Adapter-RCEGP3OG.js +0 -8
  124. package/packages/core/dist/K_LIB_Krnl_Telemetry-77FRZ3KV.js +0 -9
  125. package/packages/core/dist/chunk-33L2J7V7.js +0 -82
  126. package/packages/core/dist/chunk-3ES4K2ZP.js +0 -817
  127. package/packages/core/dist/chunk-3SMHVVLL.js +0 -82
  128. package/packages/core/dist/chunk-3UEZ7JQA.js +0 -4877
  129. package/packages/core/dist/chunk-3XIE6KBD.js +0 -4877
  130. package/packages/core/dist/chunk-46ZLCML6.js +0 -107
  131. package/packages/core/dist/chunk-4UEL3DWJ.js +0 -107
  132. package/packages/core/dist/chunk-54GWZ5PC.js +0 -82
  133. package/packages/core/dist/chunk-6QCYRS5L.js +0 -127
  134. package/packages/core/dist/chunk-6ULMHNXR.js +0 -104
  135. package/packages/core/dist/chunk-7WUETJEV.js +0 -117
  136. package/packages/core/dist/chunk-A5KRAYDB.js +0 -107
  137. package/packages/core/dist/chunk-ANEAZ3PO.js +0 -107
  138. package/packages/core/dist/chunk-BE76RL6F.js +0 -82
  139. package/packages/core/dist/chunk-CIARVYDO.js +0 -107
  140. package/packages/core/dist/chunk-CR2ANE62.js +0 -107
  141. package/packages/core/dist/chunk-DI27MOR7.js +0 -173
  142. package/packages/core/dist/chunk-E6RLFHM5.js +0 -596
  143. package/packages/core/dist/chunk-EELAPMNV.js +0 -4877
  144. package/packages/core/dist/chunk-ENZ2RQVJ.js +0 -107
  145. package/packages/core/dist/chunk-F2U6CX4F.js +0 -4877
  146. package/packages/core/dist/chunk-FKG64OHL.js +0 -82
  147. package/packages/core/dist/chunk-FYAZJYM5.js +0 -772
  148. package/packages/core/dist/chunk-G4NP4RDQ.js +0 -82
  149. package/packages/core/dist/chunk-GADIRLRS.js +0 -473
  150. package/packages/core/dist/chunk-GR6CSLQJ.js +0 -772
  151. package/packages/core/dist/chunk-HDS7AT6O.js +0 -772
  152. package/packages/core/dist/chunk-HIMEZUU2.js +0 -71
  153. package/packages/core/dist/chunk-IB4UHG5I.js +0 -596
  154. package/packages/core/dist/chunk-J7ZYNVRS.js +0 -772
  155. package/packages/core/dist/chunk-JVLZU4K7.js +0 -604
  156. package/packages/core/dist/chunk-JYXXI7Q3.js +0 -82
  157. package/packages/core/dist/chunk-K54K2KZW.js +0 -192
  158. package/packages/core/dist/chunk-K6VHLBNH.js +0 -3316
  159. package/packages/core/dist/chunk-KCBP7ZYA.js +0 -596
  160. package/packages/core/dist/chunk-KFQGP6VL.js +0 -33
  161. package/packages/core/dist/chunk-KIUEUI7K.js +0 -82
  162. package/packages/core/dist/chunk-LB67NIZP.js +0 -949
  163. package/packages/core/dist/chunk-LDTYFUNW.js +0 -596
  164. package/packages/core/dist/chunk-MLVWARD4.js +0 -596
  165. package/packages/core/dist/chunk-MPYVXHKO.js +0 -2777
  166. package/packages/core/dist/chunk-MRQ3MITU.js +0 -772
  167. package/packages/core/dist/chunk-MVUN7I7O.js +0 -107
  168. package/packages/core/dist/chunk-NDDOIRW7.js +0 -596
  169. package/packages/core/dist/chunk-O3KDB5MH.js +0 -3330
  170. package/packages/core/dist/chunk-OEINUDSE.js +0 -400
  171. package/packages/core/dist/chunk-OPDENPT4.js +0 -4877
  172. package/packages/core/dist/chunk-P6XEM2LA.js +0 -429
  173. package/packages/core/dist/chunk-QKMRSQV4.js +0 -82
  174. package/packages/core/dist/chunk-R6CCWALL.js +0 -4877
  175. package/packages/core/dist/chunk-RAMMOO73.js +0 -774
  176. package/packages/core/dist/chunk-S3FTZFG6.js +0 -772
  177. package/packages/core/dist/chunk-T2ZVN434.js +0 -4877
  178. package/packages/core/dist/chunk-TFHLDMIA.js +0 -107
  179. package/packages/core/dist/chunk-TI3QUCIJ.js +0 -107
  180. package/packages/core/dist/chunk-TR2BAIGI.js +0 -107
  181. package/packages/core/dist/chunk-UGVVJKC6.js +0 -4877
  182. package/packages/core/dist/chunk-V2DX7YIU.js +0 -984
  183. package/packages/core/dist/chunk-W4IHYUYD.js +0 -772
  184. package/packages/core/dist/chunk-W6WBG5OY.js +0 -4877
  185. package/packages/core/dist/chunk-WN3M7O7H.js +0 -3312
  186. package/packages/core/dist/chunk-WR3NCU7U.js +0 -4877
  187. package/packages/core/dist/chunk-XC6B6L27.js +0 -82
  188. package/packages/core/dist/chunk-XNSE64ZY.js +0 -3316
  189. package/packages/core/dist/chunk-XROES2WN.js +0 -634
  190. package/packages/core/dist/chunk-XSCKNRCZ.js +0 -5020
  191. package/packages/core/dist/chunk-XVABPAUZ.js +0 -82
  192. package/packages/core/dist/chunk-YOBCB5C5.js +0 -596
  193. package/packages/core/dist/chunk-YUK6Q563.js +0 -666
  194. package/packages/core/dist/chunk-YXGL3ZEU.js +0 -1030
  195. package/packages/core/dist/chunk-ZINJ5OUX.js +0 -596
  196. package/packages/core/dist/chunk-ZPFD4BIQ.js +0 -604
  197. package/packages/core/dist/chunk-ZQZBFG6F.js +0 -4826
  198. package/packages/core/dist/chunk-ZZFRJGXM.js +0 -4877
  199. package/packages/create-krnl/dist/K_ENT_Entity-PQ5MURQY-R2OH4VXE.js +0 -14
  200. package/packages/create-krnl/dist/K_LIB_Krnl_Aiko_Client-OPZAVZCW-AZM5HF4M.js +0 -9
  201. package/packages/create-krnl/dist/K_LIB_Krnl_Ep_Tools-ROOE2TQF-X5N6SV2S.js +0 -111
  202. package/packages/create-krnl/dist/K_LIB_Krnl_Frontend_Builder-2ZDUH6PF-5PFHF4JU.js +0 -12
  203. package/packages/create-krnl/dist/K_LIB_Krnl_Frontend_Generator-UYNRNX2X-ED33OQPH.js +0 -12
  204. package/packages/create-krnl/dist/K_LIB_Krnl_Registry_Client-NXV6D2QW-YGQLVR4P.js +0 -9
  205. package/packages/create-krnl/dist/K_LIB_Krnl_SubApp_Engine-7HR5HWW2-VM7CTU2L.js +0 -21
  206. package/packages/create-krnl/dist/K_LIB_Krnl_SubApp_Registry-7XYGDKJK-Y2GQFJ7I.js +0 -21
  207. package/packages/create-krnl/dist/K_LIB_Krnl_SubApp_Worker_Host-CQVTGGG7-L3JQWO54.js +0 -8
  208. package/packages/create-krnl/dist/K_LIB_Krnl_System_App_Adapter-M6FJKLGU-KQARASPR.js +0 -19
  209. package/packages/create-krnl/dist/K_LIB_Krnl_System_Base_Functionality_APIs-ZZUZ6ZG5-OF3IGLVL.js +0 -59
  210. package/packages/create-krnl/dist/K_LIB_Krnl_System_Magnetic_Loader-XBQO2KXF-JOLHKOEX.js +0 -24
  211. package/packages/create-krnl/dist/K_LIB_Krnl_System_Unified_Http_Adapter-RCEGP3OG-L46LSHKQ.js +0 -10
  212. package/packages/create-krnl/dist/K_LIB_Krnl_Telemetry-77FRZ3KV-4JUPRR3X.js +0 -10
  213. package/packages/create-krnl/dist/chunk-3TRM6CYL.js +0 -152
  214. package/packages/create-krnl/dist/chunk-3URCB3QS.js +0 -127
  215. package/packages/create-krnl/dist/chunk-5JDK35TG.js +0 -3872
  216. package/packages/create-krnl/dist/chunk-A2XAXDOW.js +0 -812
  217. package/packages/create-krnl/dist/chunk-AN6TMQHG.js +0 -1033
  218. package/packages/create-krnl/dist/chunk-BOXWWXQG.js +0 -400
  219. package/packages/create-krnl/dist/chunk-BPTBREBG.js +0 -38
  220. package/packages/create-krnl/dist/chunk-FDNCADFE.js +0 -71
  221. package/packages/create-krnl/dist/chunk-JTLSTO25.js +0 -71
  222. package/packages/create-krnl/dist/chunk-M3NCUIPL.js +0 -107
  223. package/packages/create-krnl/dist/chunk-N2EONSOC.js +0 -7769
  224. package/packages/create-krnl/dist/chunk-OHVMVRBP.js +0 -117
  225. package/packages/create-krnl/dist/chunk-Q45257P6.js +0 -173
  226. package/packages/create-krnl/dist/chunk-QGM4M3NI.js +0 -37
  227. package/packages/create-krnl/dist/chunk-RJNYUXZD.js +0 -977
  228. package/packages/create-krnl/dist/chunk-SRTOPJ5W.js +0 -104
  229. package/packages/create-krnl/dist/chunk-UPBIGEC3.js +0 -666
  230. package/packages/create-krnl/dist/chunk-V2DB7UD7.js +0 -82
  231. package/packages/create-krnl/dist/chunk-WMHLIUI6.js +0 -3644
  232. package/packages/create-krnl/dist/chunk-XIRFOO3H.js +0 -589
  233. package/packages/create-krnl/dist/chunk-Y2CEEVZP.js +0 -5536
  234. package/packages/create-krnl/dist/main-DXUMPBND.js +0 -2217
  235. package/packages/create-krnl/dist/wrapper-SDF2VKX3.js +0 -31
@@ -35,361 +35,386 @@ __export(index_exports, {
35
35
  module.exports = __toCommonJS(index_exports);
36
36
 
37
37
  // src/KrnlValidatorEngine.ts
38
- var fs = __toESM(require("fs"), 1);
39
- var path = __toESM(require("path"), 1);
40
- var import_ts_morph = require("ts-morph");
41
- var KrnlValidatorEngine = class {
42
- project;
43
- projectRoot;
44
- maxFileLineLimit;
45
- maxMainLogicLimit;
46
- maxHelperLineLimit;
47
- constructor(optionsOrRoot) {
48
- const options = typeof optionsOrRoot === "string" ? { projectRoot: optionsOrRoot } : optionsOrRoot;
49
- this.projectRoot = path.resolve(options.projectRoot || process.cwd());
50
- this.maxFileLineLimit = options.maxFileLineLimit ?? 200;
51
- this.maxMainLogicLimit = options.maxMainLogicLimit ?? 20;
52
- this.maxHelperLineLimit = options.maxHelperLineLimit ?? 30;
53
- const tsConfigPath = path.join(this.projectRoot, "tsconfig.json");
54
- if (fs.existsSync(tsConfigPath)) {
55
- this.project = new import_ts_morph.Project({ tsConfigFilePath: tsConfigPath, skipAddingFilesFromTsConfig: true });
56
- } else {
57
- this.project = new import_ts_morph.Project({ compilerOptions: {
58
- target: 99
59
- /* ESNext */
60
- } });
61
- }
62
- }
63
- /**
64
- * Scans and validates all source files in the project.
65
- */
66
- validateAll() {
67
- const files = this.collectSourceFiles(this.projectRoot);
68
- const errors = [];
69
- const warnings = [];
70
- this.validateWorkspaceLayout(errors);
71
- for (const f of files) {
72
- const sf = this.project.addSourceFileAtPath(f);
73
- const fileReport = this.validateSourceFile(sf);
74
- errors.push(...fileReport.errors);
75
- warnings.push(...fileReport.warnings);
76
- }
77
- return {
78
- valid: errors.length === 0,
79
- totalFiles: files.length,
80
- errors,
81
- warnings
82
- };
38
+ var fs2 = __toESM(require("fs"), 1);
39
+ var path3 = __toESM(require("path"), 1);
40
+ var import_ts_morph5 = require("ts-morph");
41
+
42
+ // src/rules/fileLimits.ts
43
+ function checkFileLimits(sf, options) {
44
+ const errors = [];
45
+ const warnings = [];
46
+ const filePath = sf.getFilePath();
47
+ const sourceText = sf.getFullText();
48
+ const lines = sourceText.split("\n");
49
+ if (lines.length > options.maxFileLineLimit) {
50
+ errors.push({
51
+ ruleId: "krnl/file-line-limit",
52
+ filePath,
53
+ message: `File exceeds maximum length of ${options.maxFileLineLimit} lines (currently ${lines.length} lines). Decompose into sub-components, custom hooks, quad-units, or concept libraries.`,
54
+ severity: "error"
55
+ });
83
56
  }
84
- /**
85
- * Validates a single SourceFile.
86
- */
87
- validateSourceFile(sf) {
88
- const errors = [];
89
- const warnings = [];
90
- const filePath = sf.getFilePath();
91
- const sourceText = sf.getText();
92
- const baseName = path.basename(filePath);
93
- if (baseName.includes("_pb.") || baseName.endsWith(".d.ts")) {
94
- return { errors, warnings };
95
- }
96
- const lines = sourceText.split("\n");
97
- if (lines.length > this.maxFileLineLimit) {
57
+ for (const decl of sf.getImportDeclarations()) {
58
+ const moduleSpec = decl.getModuleSpecifierValue();
59
+ if (moduleSpec.startsWith(".") && !moduleSpec.endsWith(".js") && !moduleSpec.endsWith(".json") && !moduleSpec.endsWith(".css") && !moduleSpec.endsWith(".svg") && !moduleSpec.endsWith(".png")) {
98
60
  errors.push({
99
- ruleId: "krnl/file-line-limit",
61
+ ruleId: "krnl/import-suffix",
100
62
  filePath,
101
- message: `File exceeds maximum length of ${this.maxFileLineLimit} lines (currently ${lines.length} lines). Decompose into sub-components, custom hooks, quad-units, or concept libraries.`,
63
+ line: decl.getStartLineNumber(),
64
+ message: `Relative import '${moduleSpec}' must end with '.js' for NodeNext module resolution.`,
102
65
  severity: "error"
103
66
  });
104
67
  }
105
- for (const decl of sf.getImportDeclarations()) {
106
- const moduleSpec = decl.getModuleSpecifierValue();
107
- if (moduleSpec.startsWith(".") && !moduleSpec.endsWith(".js") && !moduleSpec.endsWith(".json") && !moduleSpec.endsWith(".css") && !moduleSpec.endsWith(".svg") && !moduleSpec.endsWith(".png")) {
108
- const line = decl.getStartLineNumber();
68
+ }
69
+ const isHelper = filePath.includes("helper_functions") || filePath.includes("/helpers/") || filePath.includes("\\helpers\\");
70
+ if (isHelper) {
71
+ for (const fn of sf.getFunctions()) {
72
+ const fnLines = fn.getText().split("\n").length;
73
+ if (fnLines > options.maxHelperLineLimit && !sourceText.includes("Concepts.")) {
109
74
  errors.push({
110
- ruleId: "krnl/import-suffix",
75
+ ruleId: "krnl/helper-line-limit",
111
76
  filePath,
112
- line,
113
- message: `Relative import '${moduleSpec}' must end with '.js' for NodeNext module resolution.`,
77
+ line: fn.getStartLineNumber(),
78
+ message: `Helper function '${fn.getName() || "anonymous"}' exceeds ${options.maxHelperLineLimit} lines (${fnLines} lines). Must delegate to a root libraries/{Domain}Concepts.ts library.`,
114
79
  severity: "error"
115
80
  });
116
81
  }
117
82
  }
118
- const isUiTopLevel = /^(App|main|index|_app|root)\.(tsx|jsx)$/i.test(baseName);
119
- const isBackendTopLevel = /^(server|app)\.(ts|js)$/i.test(baseName) && (!filePath.includes("/components/") && !filePath.includes("/entities/") && !filePath.includes("/libraries/"));
120
- if (isUiTopLevel) {
121
- const jsxElements = sf.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxOpeningElement);
122
- const jsxSelfClosing = sf.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxSelfClosingElement);
123
- const allJsxTags = [...jsxElements, ...jsxSelfClosing];
124
- for (const jsx of allJsxTags) {
125
- const tagName = jsx.getTagNameNode().getText();
126
- if (/^[a-z]/.test(tagName)) {
127
- errors.push({
128
- ruleId: "krnl/top-level-purity",
129
- filePath,
130
- line: jsx.getStartLineNumber(),
131
- message: `Top-level file '${baseName}' violates Top-Level Purity Law. Raw JSX/HTML element '<${tagName}>' is strictly forbidden. Top-level files must ONLY import and compose React components.`,
132
- severity: "error"
133
- });
134
- }
135
- }
136
- const calls2 = sf.getDescendantsOfKind(import_ts_morph.SyntaxKind.CallExpression);
137
- for (const call of calls2) {
138
- const exprText = call.getExpression().getText();
139
- if (["useState", "useEffect", "useRef", "useMemo", "useCallback", "useReducer", "useContext", "useLayoutEffect"].includes(exprText) || /^use[A-Z]/.test(exprText) && exprText !== "use") {
140
- errors.push({
141
- ruleId: "krnl/top-level-purity",
142
- filePath,
143
- line: call.getStartLineNumber(),
144
- message: `Top-level file '${baseName}' violates Top-Level Purity Law. React hook '${exprText}' is forbidden in top-level files. Encapsulate state and effects inside dedicated component files.`,
145
- severity: "error"
146
- });
147
- }
148
- }
83
+ }
84
+ const isMainLogic = filePath.endsWith("logic.ts") || filePath.endsWith("logic.js");
85
+ if (isMainLogic) {
86
+ const substantiveLines = lines.filter((l) => {
87
+ const trimmed = l.trim();
88
+ return trimmed.length > 0 && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !trimmed.startsWith("*");
89
+ });
90
+ if (substantiveLines.length > options.maxMainLogicLimit && !sourceText.includes("helpers") && !sourceText.includes("Concepts") && !sourceText.includes("state")) {
91
+ errors.push({
92
+ ruleId: "krnl/main-delegation",
93
+ filePath,
94
+ message: `Main logic function has ${substantiveLines.length} substantive lines without delegating to Layer 1 helper functions or Layer 0 libraries.`,
95
+ severity: "error"
96
+ });
149
97
  }
150
- if (isBackendTopLevel) {
151
- const calls2 = sf.getDescendantsOfKind(import_ts_morph.SyntaxKind.CallExpression);
152
- for (const call of calls2) {
153
- const exprText = call.getExpression().getText();
154
- if (/^(app|router|server)\.(get|post|put|delete|patch|options|head)$/.test(exprText)) {
155
- errors.push({
156
- ruleId: "krnl/top-level-purity",
157
- filePath,
158
- line: call.getStartLineNumber(),
159
- message: `Backend entry file '${baseName}' violates Entry Purity Law. Inline route definition '${exprText}' is forbidden. Delegate to dedicated route/controller modules.`,
160
- severity: "error"
161
- });
162
- }
98
+ }
99
+ return { errors, warnings };
100
+ }
101
+
102
+ // src/rules/componentRules.ts
103
+ var path = __toESM(require("path"), 1);
104
+ var import_ts_morph = require("ts-morph");
105
+ function checkComponentRules(sf) {
106
+ const errors = [];
107
+ const warnings = [];
108
+ const filePath = sf.getFilePath();
109
+ const baseName = path.basename(filePath);
110
+ if (filePath.endsWith(".tsx") || filePath.endsWith(".jsx")) {
111
+ const componentNames = [];
112
+ for (const fn of sf.getFunctions()) {
113
+ const name = fn.getName();
114
+ if (name && /^[A-Z]/.test(name)) {
115
+ const hasJsx = fn.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxElement).length > 0 || fn.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxSelfClosingElement).length > 0 || fn.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxFragment).length > 0;
116
+ if (hasJsx) componentNames.push(name);
163
117
  }
164
118
  }
165
- if (filePath.endsWith(".tsx") || filePath.endsWith(".jsx")) {
166
- const componentNames = [];
167
- for (const fn of sf.getFunctions()) {
168
- const name = fn.getName();
169
- if (name && /^[A-Z]/.test(name)) {
170
- const hasJsx = fn.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxElement).length > 0 || fn.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxSelfClosingElement).length > 0 || fn.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxFragment).length > 0;
171
- if (hasJsx) {
172
- componentNames.push(name);
173
- }
174
- }
175
- }
176
- for (const stmt of sf.getVariableStatements()) {
177
- for (const decl of stmt.getDeclarations()) {
178
- const name = decl.getName();
179
- if (/^[A-Z]/.test(name)) {
180
- const typeText = decl.getTypeNode()?.getText() || "";
181
- const isFcType = typeText.includes("FC") || typeText.includes("FunctionComponent") || typeText.includes("ComponentType");
182
- const init = decl.getInitializer();
183
- if (init) {
184
- const hasJsx = init.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxElement).length > 0 || init.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxSelfClosingElement).length > 0 || init.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxFragment).length > 0;
185
- if (isFcType || hasJsx) {
186
- if (!componentNames.includes(name)) {
187
- componentNames.push(name);
188
- }
189
- }
119
+ for (const stmt of sf.getVariableStatements()) {
120
+ for (const decl of stmt.getDeclarations()) {
121
+ const name = decl.getName();
122
+ if (/^[A-Z]/.test(name)) {
123
+ const typeText = decl.getTypeNode()?.getText() || "";
124
+ const isFcType = typeText.includes("FC") || typeText.includes("FunctionComponent") || typeText.includes("ComponentType");
125
+ const init = decl.getInitializer();
126
+ if (init) {
127
+ const hasJsx = init.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxElement).length > 0 || init.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxSelfClosingElement).length > 0 || init.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxFragment).length > 0;
128
+ if (isFcType || hasJsx) {
129
+ if (!componentNames.includes(name)) componentNames.push(name);
190
130
  }
191
131
  }
192
132
  }
193
133
  }
194
- for (const cls of sf.getClasses()) {
195
- const name = cls.getName();
196
- const ext = cls.getExtends()?.getText() || "";
197
- if (name && (ext.includes("Component") || ext.includes("PureComponent"))) {
198
- if (!componentNames.includes(name)) {
199
- componentNames.push(name);
200
- }
201
- }
134
+ }
135
+ for (const cls of sf.getClasses()) {
136
+ const name = cls.getName();
137
+ const ext = cls.getExtends()?.getText() || "";
138
+ if (name && (ext.includes("Component") || ext.includes("PureComponent"))) {
139
+ if (!componentNames.includes(name)) componentNames.push(name);
202
140
  }
203
- if (componentNames.length > 1) {
141
+ }
142
+ if (componentNames.length > 1) {
143
+ errors.push({
144
+ ruleId: "krnl/one-component-per-file",
145
+ filePath,
146
+ message: `File '${baseName}' defines multiple React components (${componentNames.join(
147
+ ", "
148
+ )}). Krnl strictly enforces ONE component per file. Decompose into sub-component files.`,
149
+ severity: "error"
150
+ });
151
+ }
152
+ }
153
+ const isHelper = filePath.includes("helper_functions") || filePath.includes("/helpers/") || filePath.includes("\\helpers\\");
154
+ if (isHelper) {
155
+ for (const decl of sf.getImportDeclarations()) {
156
+ const spec = decl.getModuleSpecifierValue();
157
+ if (["fs", "node:fs", "http", "node:http", "ws"].includes(spec)) {
204
158
  errors.push({
205
- ruleId: "krnl/one-component-per-file",
159
+ ruleId: "krnl/helper-purity",
206
160
  filePath,
207
- message: `File '${baseName}' defines multiple React components (${componentNames.join(", ")}). Krnl strictly enforces ONE component per file. Decompose into sub-component files.`,
161
+ line: decl.getStartLineNumber(),
162
+ message: `Helper functions (Layer 1) cannot directly import I/O modules ('${spec}'). Delegate to Layer 0 libraries or ServiceFacade context.`,
208
163
  severity: "error"
209
164
  });
210
165
  }
211
166
  }
212
- const isHelper = filePath.includes("helper_functions") || filePath.includes("/helpers/") || filePath.includes("\\helpers\\");
213
- const isMainLogic = filePath.endsWith("logic.ts") || filePath.endsWith("logic.js");
214
- const isRootConcept = filePath.includes("libraries/") || filePath.includes("Concepts.ts");
215
- if (isHelper) {
216
- for (const decl of sf.getImportDeclarations()) {
217
- const spec = decl.getModuleSpecifierValue();
218
- if (["fs", "node:fs", "http", "node:http", "ws"].includes(spec)) {
219
- errors.push({
220
- ruleId: "krnl/helper-purity",
221
- filePath,
222
- line: decl.getStartLineNumber(),
223
- message: `Helper functions (Layer 1) cannot directly import I/O modules ('${spec}'). Delegate to Layer 0 libraries or Entity context.`,
224
- severity: "error"
225
- });
226
- }
227
- }
228
- for (const fn of sf.getFunctions()) {
229
- const fnLines = fn.getText().split("\n").length;
230
- if (fnLines > this.maxHelperLineLimit && !sourceText.includes("Concepts.")) {
231
- errors.push({
232
- ruleId: "krnl/helper-line-limit",
233
- filePath,
234
- line: fn.getStartLineNumber(),
235
- message: `Helper function '${fn.getName() || "anonymous"}' exceeds ${this.maxHelperLineLimit} lines (${fnLines} lines). Must delegate to a root libraries/{Domain}Concepts.ts library.`,
236
- severity: "error"
237
- });
238
- }
239
- }
240
- }
241
- if (isMainLogic) {
242
- const substantiveLines = lines.filter((l) => {
243
- const trimmed = l.trim();
244
- return trimmed.length > 0 && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !trimmed.startsWith("*");
167
+ }
168
+ return { errors, warnings };
169
+ }
170
+
171
+ // src/rules/orchestrationRules.ts
172
+ var import_ts_morph2 = require("ts-morph");
173
+ function checkOrchestrationRules(sf) {
174
+ const errors = [];
175
+ const warnings = [];
176
+ const filePath = sf.getFilePath();
177
+ const sourceText = sf.getText();
178
+ const calls = sf.getDescendantsOfKind(import_ts_morph2.SyntaxKind.CallExpression);
179
+ for (const call of calls) {
180
+ const exprText = call.getExpression().getText();
181
+ if (exprText === "setInterval" || exprText === "window.setInterval") {
182
+ errors.push({
183
+ ruleId: "krnl/no-polling",
184
+ filePath,
185
+ line: call.getStartLineNumber(),
186
+ message: `Prohibited use of 'setInterval'. Krnl applications must use reactive event streams or triggers.`,
187
+ severity: "error"
245
188
  });
246
- if (substantiveLines.length > this.maxMainLogicLimit && !sourceText.includes("helpers") && !sourceText.includes("Concepts") && !sourceText.includes("state")) {
189
+ }
190
+ }
191
+ if (sourceText.includes("main = async") || sourceText.includes("export const main = async")) {
192
+ const match = sourceText.match(/main\s*=\s*async\s*\([^,]+,\s*\{([^}]*)\}\s*\)/);
193
+ if (match) {
194
+ const destructured = match[1];
195
+ if (/\bsystem\b/.test(destructured)) {
247
196
  errors.push({
248
- ruleId: "krnl/main-delegation",
197
+ ruleId: "krnl/context-destructuring",
249
198
  filePath,
250
- message: `Main logic function has ${substantiveLines.length} substantive lines without delegating to Layer 1 helper functions or Layer 0 libraries.`,
199
+ message: `Functionality context parameter destructures 'system'. Functionality passes { state, orchestration } or service context.`,
251
200
  severity: "error"
252
201
  });
253
202
  }
254
203
  }
255
- if (sourceText.includes("main = async") || sourceText.includes("export const main = async")) {
256
- const match = sourceText.match(/main\s*=\s*async\s*\([^,]+,\s*\{([^}]*)\}\s*\)/);
257
- if (match) {
258
- const destructured = match[1];
259
- if (/\bsystem\b/.test(destructured) && !/\bentity\b/.test(destructured)) {
260
- errors.push({
261
- ruleId: "krnl/context-destructuring",
262
- filePath,
263
- message: `Functionality context parameter destructures 'system'. Functionality passes { state, entity }. Always destructure 'entity'.`,
264
- severity: "error"
265
- });
266
- }
267
- }
268
- }
269
- const calls = sf.getDescendantsOfKind(import_ts_morph.SyntaxKind.CallExpression);
270
- for (const call of calls) {
271
- const exprText = call.getExpression().getText();
272
- if (exprText === "setInterval" || exprText === "window.setInterval") {
204
+ }
205
+ const isOrchestrationClass = sf.getClasses().some((c) => {
206
+ const ext = c.getExtends();
207
+ return ext && (ext.getText().includes("FunctionalityOrchestration") || ext.getText().includes("Orchestration") || ext.getText().includes("krnlOrchestrationBase"));
208
+ });
209
+ if (isOrchestrationClass) {
210
+ for (const decl of sf.getImportDeclarations()) {
211
+ const spec = decl.getModuleSpecifierValue();
212
+ if (spec.includes("libraries/") || spec.includes("Concepts")) {
273
213
  errors.push({
274
- ruleId: "krnl/no-polling",
214
+ ruleId: "krnl/orchestration-no-libraries",
275
215
  filePath,
276
- line: call.getStartLineNumber(),
277
- message: `Prohibited use of 'setInterval'. Krnl applications must use reactive event streams (entity.emitEvent / entity.on).`,
216
+ line: decl.getStartLineNumber(),
217
+ message: `FunctionalityOrchestration class violates Library Calling Invariant. FunctionalityOrchestrations must not call or import libraries directly ('${spec}'). Only functionalities are permitted to call shared libraries.`,
278
218
  severity: "error"
279
219
  });
280
220
  }
281
221
  }
282
- const isEntityClass = sf.getClasses().some((c) => {
283
- const ext = c.getExtends();
284
- return ext && (ext.getText().includes("Entity") || ext.getText().includes("krnlEntityBase"));
285
- });
286
- if (isEntityClass) {
287
- for (const decl of sf.getImportDeclarations()) {
288
- const spec = decl.getModuleSpecifierValue();
289
- if (spec.includes("libraries/") || spec.includes("Concepts")) {
222
+ for (const cls of sf.getClasses()) {
223
+ const ext = cls.getExtends();
224
+ if (ext && (ext.getText().includes("FunctionalityOrchestration") || ext.getText().includes("Orchestration") || ext.getText().includes("krnlOrchestrationBase"))) {
225
+ const loops = [
226
+ ...cls.getDescendantsOfKind(import_ts_morph2.SyntaxKind.ForStatement),
227
+ ...cls.getDescendantsOfKind(import_ts_morph2.SyntaxKind.ForOfStatement),
228
+ ...cls.getDescendantsOfKind(import_ts_morph2.SyntaxKind.ForInStatement),
229
+ ...cls.getDescendantsOfKind(import_ts_morph2.SyntaxKind.WhileStatement),
230
+ ...cls.getDescendantsOfKind(import_ts_morph2.SyntaxKind.DoStatement)
231
+ ];
232
+ for (const loop of loops) {
290
233
  errors.push({
291
- ruleId: "krnl/entity-no-libraries",
234
+ ruleId: "krnl/orchestration-purity",
292
235
  filePath,
293
- line: decl.getStartLineNumber(),
294
- message: `Entity class violates Library Calling Invariant. Entities must not call or import libraries directly ('${spec}'). Only functionalities in 'src/functionalities/' are permitted to call shared libraries.`,
236
+ line: loop.getStartLineNumber(),
237
+ message: `FunctionalityOrchestration '${cls.getName() || "Anonymous"}' violates Orchestration Purity Law. Loops and procedural algorithms are prohibited inside orchestrations. Move logic to a functionality or a global library function.`,
295
238
  severity: "error"
296
239
  });
297
240
  }
298
- }
299
- let loadAllLine = -1;
300
- const addLocalLines = [];
301
- for (const call of calls) {
302
- const txt = call.getText();
303
- if (txt.includes("MagneticLoader.loadAll") || txt.includes("KrnlMagneticLoader.loadAll")) {
304
- loadAllLine = call.getStartLineNumber();
305
- } else if (txt.startsWith("this.addLocal(")) {
306
- const hasUiSpec = txt.includes("uiSpec");
307
- const idMatch = txt.match(/id\s*:\s*["']([^"']+)["']/);
308
- addLocalLines.push({
309
- line: call.getStartLineNumber(),
310
- hasUiSpec,
311
- id: idMatch ? idMatch[1] : "unknown"
312
- });
313
- }
314
- }
315
- if (loadAllLine !== -1) {
316
- for (const al of addLocalLines) {
317
- if (al.hasUiSpec && al.line > loadAllLine) {
241
+ const allowedMethods = /* @__PURE__ */ new Set([
242
+ "flow",
243
+ "getFlow",
244
+ "listFlows",
245
+ "clearFlows",
246
+ "thenFunctionality",
247
+ "parallel",
248
+ "branch",
249
+ "fanOut",
250
+ "thenFunctionalityOrchestration",
251
+ "getSteps",
252
+ "assertServiceBoundary"
253
+ ]);
254
+ for (const method of cls.getMethods()) {
255
+ const methodName = method.getName();
256
+ if (!allowedMethods.has(methodName)) {
318
257
  errors.push({
319
- ruleId: "krnl/boot-order",
258
+ ruleId: "krnl/orchestration-purity",
320
259
  filePath,
321
- line: al.line,
322
- message: `addLocal('${al.id}') with uiSpec at line ${al.line} appears AFTER loadAll() at line ${loadAllLine}. All addLocal() with UI must precede loadAll().`,
260
+ line: method.getStartLineNumber(),
261
+ message: `FunctionalityOrchestration '${cls.getName() || "Anonymous"}' defines custom method '${methodName}'. FunctionalityOrchestrations are purely declarative compositors. Define capabilities as functionalities or global library functions.`,
323
262
  severity: "error"
324
263
  });
325
264
  }
326
265
  }
327
266
  }
328
- for (const cls of sf.getClasses()) {
329
- const ext = cls.getExtends();
330
- if (ext && (ext.getText().includes("Entity") || ext.getText().includes("krnlEntityBase"))) {
331
- const loops = [
332
- ...cls.getDescendantsOfKind(import_ts_morph.SyntaxKind.ForStatement),
333
- ...cls.getDescendantsOfKind(import_ts_morph.SyntaxKind.ForOfStatement),
334
- ...cls.getDescendantsOfKind(import_ts_morph.SyntaxKind.ForInStatement),
335
- ...cls.getDescendantsOfKind(import_ts_morph.SyntaxKind.WhileStatement),
336
- ...cls.getDescendantsOfKind(import_ts_morph.SyntaxKind.DoStatement)
337
- ];
338
- for (const loop of loops) {
267
+ }
268
+ for (const call of calls) {
269
+ const callText = call.getText();
270
+ if (callText.startsWith("this.flow(") || callText.startsWith("orchestration.flow(")) {
271
+ let currentExpr = call;
272
+ const chainCalls = [];
273
+ while (currentExpr && import_ts_morph2.Node.isCallExpression(currentExpr)) {
274
+ const propAccess = currentExpr.getExpression();
275
+ if (import_ts_morph2.Node.isPropertyAccessExpression(propAccess)) {
276
+ const methodName = propAccess.getName();
277
+ const args = currentExpr.getArguments();
278
+ const argText = args.length > 0 ? args[0].getText() : void 0;
279
+ chainCalls.unshift({ name: methodName, node: currentExpr, argText });
280
+ currentExpr = propAccess.getExpression();
281
+ } else {
282
+ break;
283
+ }
284
+ }
285
+ let chainId = "orchestration";
286
+ for (const step of chainCalls) {
287
+ if (step.name === "flow") {
288
+ chainId = step.argText ? step.argText.replace(/['"]/g, "") : "orchestration";
289
+ } else if (step.name === "thenFunction") {
339
290
  errors.push({
340
- ruleId: "krnl/entity-purity",
291
+ ruleId: "krnl/orchestration-no-direct-library-calls",
341
292
  filePath,
342
- line: loop.getStartLineNumber(),
343
- message: `Entity '${cls.getName() || "Anonymous"}' violates Entity Purity Law. Loops and procedural algorithms are prohibited inside entities. Move logic to a functionality or a global library function.`,
293
+ line: step.node.getStartLineNumber(),
294
+ message: `FunctionalityOrchestration flow '${chainId}' violates Orchestration Purity Law. Orchestrations cannot chain direct library functions via thenFunction(). Orchestrations must only sequence functionalities (thenFunctionality) and peer functionality orchestrations (thenFunctionalityOrchestration).`,
295
+ severity: "error"
296
+ });
297
+ } else if (step.name === "thenService") {
298
+ errors.push({
299
+ ruleId: "krnl/orchestration-no-external-services",
300
+ filePath,
301
+ line: step.node.getStartLineNumber(),
302
+ message: `FunctionalityOrchestration flow '${chainId}' violates Plane Isolation Law L1. A service-level FunctionalityOrchestration cannot compose external services. Use Skipo ServiceOrchestration at the application layer instead.`,
344
303
  severity: "error"
345
304
  });
346
305
  }
347
- for (const method of cls.getMethods()) {
348
- const methodName = method.getName();
349
- if (!["boot", "init", "dispose"].includes(methodName)) {
306
+ }
307
+ }
308
+ }
309
+ }
310
+ return { errors, warnings };
311
+ }
312
+
313
+ // src/rules/workspaceRules.ts
314
+ var fs = __toESM(require("fs"), 1);
315
+ var path2 = __toESM(require("path"), 1);
316
+ var import_ts_morph3 = require("ts-morph");
317
+ function checkTopLevelPurity(sf) {
318
+ const errors = [];
319
+ const warnings = [];
320
+ const filePath = sf.getFilePath();
321
+ const baseName = path2.basename(filePath);
322
+ const isUiTopLevel = /^(App|main|index|_app|root)\.(tsx|jsx)$/i.test(baseName);
323
+ const isBackendTopLevel = /^(server|app|index)\.(ts|js)$/i.test(baseName) && !filePath.includes("/components/") && !filePath.includes("/orchestrations/") && !filePath.includes("/services/") && !filePath.includes("/libraries/");
324
+ if (isUiTopLevel) {
325
+ const jsxElements = sf.getDescendantsOfKind(import_ts_morph3.SyntaxKind.JsxOpeningElement);
326
+ const jsxSelfClosing = sf.getDescendantsOfKind(import_ts_morph3.SyntaxKind.JsxSelfClosingElement);
327
+ const allJsxTags = [...jsxElements, ...jsxSelfClosing];
328
+ for (const jsx of allJsxTags) {
329
+ const tagName = jsx.getTagNameNode().getText();
330
+ if (/^[a-z]/.test(tagName)) {
331
+ errors.push({
332
+ ruleId: "krnl/top-level-purity",
333
+ filePath,
334
+ line: jsx.getStartLineNumber(),
335
+ message: `Top-level file '${baseName}' violates Top-Level Purity Law. Raw JSX/HTML element '<${tagName}>' is strictly forbidden. Top-level files must ONLY import and compose React components.`,
336
+ severity: "error"
337
+ });
338
+ }
339
+ }
340
+ const calls = sf.getDescendantsOfKind(import_ts_morph3.SyntaxKind.CallExpression);
341
+ for (const call of calls) {
342
+ const exprText = call.getExpression().getText();
343
+ if ([
344
+ "useState",
345
+ "useEffect",
346
+ "useRef",
347
+ "useMemo",
348
+ "useCallback",
349
+ "useReducer",
350
+ "useContext",
351
+ "useLayoutEffect"
352
+ ].includes(exprText) || /^use[A-Z]/.test(exprText) && exprText !== "use") {
353
+ errors.push({
354
+ ruleId: "krnl/top-level-purity",
355
+ filePath,
356
+ line: call.getStartLineNumber(),
357
+ message: `Top-level file '${baseName}' violates Top-Level Purity Law. React hook '${exprText}' is forbidden in top-level files. Encapsulate state and effects inside dedicated component files.`,
358
+ severity: "error"
359
+ });
360
+ }
361
+ }
362
+ }
363
+ if (isBackendTopLevel) {
364
+ const calls = sf.getDescendantsOfKind(import_ts_morph3.SyntaxKind.CallExpression);
365
+ for (const call of calls) {
366
+ const exprText = call.getExpression().getText();
367
+ if (/^(app|router|server)\.(get|post|put|delete|patch|options|head)$/.test(exprText)) {
368
+ errors.push({
369
+ ruleId: "krnl/top-level-purity",
370
+ filePath,
371
+ line: call.getStartLineNumber(),
372
+ message: `Backend entry file '${baseName}' violates Entry Purity Law. Inline route definition '${exprText}' is forbidden. Delegate to dedicated route/controller modules.`,
373
+ severity: "error"
374
+ });
375
+ }
376
+ }
377
+ }
378
+ return { errors, warnings };
379
+ }
380
+ function checkWorkspaceLayout(projectRoot, errors) {
381
+ const krnlDir = path2.join(projectRoot, "krnl");
382
+ const srcDir = path2.join(projectRoot, "src");
383
+ const targetDir = fs.existsSync(krnlDir) ? krnlDir : fs.existsSync(srcDir) ? srcDir : null;
384
+ if (!targetDir) return;
385
+ const backendDir = path2.join(targetDir, "backend");
386
+ const frontendDir = path2.join(targetDir, "frontend");
387
+ if (fs.existsSync(backendDir)) {
388
+ const bServices = path2.join(backendDir, "services");
389
+ if (fs.existsSync(bServices)) {
390
+ for (const sEntry of fs.readdirSync(bServices, { withFileTypes: true })) {
391
+ if (!sEntry.isDirectory()) continue;
392
+ const sDir = path2.join(bServices, sEntry.name);
393
+ const sLibs = path2.join(sDir, "libraries");
394
+ if (fs.existsSync(sLibs)) {
395
+ for (const entry of fs.readdirSync(sLibs, { withFileTypes: true })) {
396
+ if (!entry.isDirectory()) continue;
397
+ const libPath = path2.join(sLibs, entry.name);
398
+ if (!fs.existsSync(path2.join(libPath, "manifest.json"))) {
350
399
  errors.push({
351
- ruleId: "krnl/entity-purity",
352
- filePath,
353
- line: method.getStartLineNumber(),
354
- message: `Entity '${cls.getName() || "Anonymous"}' defines custom method '${methodName}'. Entities are purely declarative compositors/orchestrators. Define capabilities as functionalities or global library functions.`,
400
+ ruleId: "krnl/concept-manifest-required",
401
+ filePath: libPath,
402
+ message: `Service-owned concept library "${sEntry.name}/${entry.name}" is missing a manifest.json file.`,
355
403
  severity: "error"
356
404
  });
357
405
  }
358
406
  }
359
407
  }
360
- }
361
- for (const call of calls) {
362
- const callText = call.getText();
363
- if (callText.startsWith("this.orchestration(") || callText.startsWith("this.flow(")) {
364
- let currentExpr = call;
365
- const chainCalls = [];
366
- while (currentExpr && import_ts_morph.Node.isCallExpression(currentExpr)) {
367
- const propAccess = currentExpr.getExpression();
368
- if (import_ts_morph.Node.isPropertyAccessExpression(propAccess)) {
369
- const methodName = propAccess.getName();
370
- const args = currentExpr.getArguments();
371
- const argText = args.length > 0 ? args[0].getText() : void 0;
372
- chainCalls.unshift({ name: methodName, node: currentExpr, argText });
373
- currentExpr = propAccess.getExpression();
374
- } else {
375
- break;
376
- }
377
- }
378
- let consecutiveFunctions = 0;
379
- let chainId = "orchestration";
380
- for (const step of chainCalls) {
381
- if (step.name === "orchestration" || step.name === "flow") {
382
- chainId = step.argText ? step.argText.replace(/['"]/g, "") : "orchestration";
383
- } else if (step.name === "thenFunctionality" || step.name === "then") {
384
- consecutiveFunctions = 0;
385
- } else if (step.name === "thenEntityOrchestration" || step.name === "thenEntity") {
386
- consecutiveFunctions = 0;
387
- } else if (step.name === "thenFunction") {
408
+ const sFuncs = path2.join(sDir, "functionalities");
409
+ if (fs.existsSync(sFuncs)) {
410
+ for (const entry of fs.readdirSync(sFuncs, { withFileTypes: true })) {
411
+ if (!entry.isDirectory()) continue;
412
+ const funcPath = path2.join(sFuncs, entry.name);
413
+ if (!fs.existsSync(path2.join(funcPath, "manifest.json"))) {
388
414
  errors.push({
389
- ruleId: "krnl/entity-no-direct-library-calls",
390
- filePath,
391
- line: step.node.getStartLineNumber(),
392
- message: `Orchestration chain '${chainId}' violates Entity Purity Law. Entities cannot chain direct library functions via thenFunction(). Entities must only orchestrate functionalities (thenFunctionality) and orchestrations from other entities (thenEntityOrchestration).`,
415
+ ruleId: "krnl/functionality-manifest-required",
416
+ filePath: funcPath,
417
+ message: `Service-owned functionality "${sEntry.name}/${entry.name}" is missing a manifest.json file.`,
393
418
  severity: "error"
394
419
  });
395
420
  }
@@ -397,93 +422,399 @@ var KrnlValidatorEngine = class {
397
422
  }
398
423
  }
399
424
  }
400
- return { errors, warnings };
401
- }
402
- /**
403
- * Validates workspace layout invariants for symmetric Krnl architecture.
404
- */
405
- validateWorkspaceLayout(errors) {
406
- const krnlDir = path.join(this.projectRoot, "krnl");
407
- const srcDir = path.join(this.projectRoot, "src");
408
- const targetDir = fs.existsSync(krnlDir) ? krnlDir : fs.existsSync(srcDir) ? srcDir : null;
409
- if (!targetDir) return;
410
- const backendDir = path.join(targetDir, "backend");
411
- const frontendDir = path.join(targetDir, "frontend");
412
- if (fs.existsSync(backendDir)) {
413
- const bLibs = path.join(backendDir, "libraries");
414
- if (fs.existsSync(bLibs)) {
415
- for (const entry of fs.readdirSync(bLibs, { withFileTypes: true })) {
416
- if (!entry.isDirectory()) continue;
417
- const libPath = path.join(bLibs, entry.name);
418
- const manifestPath = path.join(libPath, "manifest.json");
419
- if (!fs.existsSync(manifestPath)) {
420
- errors.push({
421
- ruleId: "krnl/concept-manifest-required",
422
- filePath: libPath,
423
- message: `Backend concept library "${entry.name}" is missing a manifest.json file.`,
424
- severity: "error"
425
- });
426
- }
425
+ const bLibs = path2.join(backendDir, "libraries");
426
+ if (fs.existsSync(bLibs)) {
427
+ for (const entry of fs.readdirSync(bLibs, { withFileTypes: true })) {
428
+ if (!entry.isDirectory()) continue;
429
+ const libPath = path2.join(bLibs, entry.name);
430
+ if (!fs.existsSync(path2.join(libPath, "manifest.json"))) {
431
+ errors.push({
432
+ ruleId: "krnl/concept-manifest-required",
433
+ filePath: libPath,
434
+ message: `Backend concept library "${entry.name}" is missing a manifest.json file.`,
435
+ severity: "error"
436
+ });
427
437
  }
428
438
  }
429
- const bFuncs = path.join(backendDir, "functionalities");
430
- if (fs.existsSync(bFuncs)) {
431
- for (const entry of fs.readdirSync(bFuncs, { withFileTypes: true })) {
432
- if (!entry.isDirectory()) continue;
433
- const funcPath = path.join(bFuncs, entry.name);
434
- const manifestPath = path.join(funcPath, "manifest.json");
435
- if (!fs.existsSync(manifestPath)) {
436
- errors.push({
437
- ruleId: "krnl/functionality-manifest-required",
438
- filePath: funcPath,
439
- message: `Backend functionality "${entry.name}" is missing a manifest.json file.`,
440
- severity: "error"
441
- });
442
- }
439
+ }
440
+ const bFuncs = path2.join(backendDir, "functionalities");
441
+ if (fs.existsSync(bFuncs)) {
442
+ for (const entry of fs.readdirSync(bFuncs, { withFileTypes: true })) {
443
+ if (!entry.isDirectory()) continue;
444
+ const funcPath = path2.join(bFuncs, entry.name);
445
+ if (!fs.existsSync(path2.join(funcPath, "manifest.json"))) {
446
+ errors.push({
447
+ ruleId: "krnl/functionality-manifest-required",
448
+ filePath: funcPath,
449
+ message: `Backend functionality "${entry.name}" is missing a manifest.json file.`,
450
+ severity: "error"
451
+ });
443
452
  }
444
453
  }
445
454
  }
446
- if (fs.existsSync(frontendDir)) {
447
- const fLibs = path.join(frontendDir, "libraries");
448
- if (fs.existsSync(fLibs)) {
449
- for (const entry of fs.readdirSync(fLibs, { withFileTypes: true })) {
450
- if (!entry.isDirectory()) continue;
451
- const libPath = path.join(fLibs, entry.name);
452
- const manifestPath = path.join(libPath, "manifest.json");
453
- if (!fs.existsSync(manifestPath)) {
454
- errors.push({
455
- ruleId: "krnl/frontend-concept-manifest-required",
456
- filePath: libPath,
457
- message: `Frontend concept library "${entry.name}" is missing a manifest.json file.`,
458
- severity: "error"
459
- });
460
- }
455
+ }
456
+ if (fs.existsSync(frontendDir)) {
457
+ const fLibs = path2.join(frontendDir, "libraries");
458
+ if (fs.existsSync(fLibs)) {
459
+ for (const entry of fs.readdirSync(fLibs, { withFileTypes: true })) {
460
+ if (!entry.isDirectory()) continue;
461
+ const libPath = path2.join(fLibs, entry.name);
462
+ if (!fs.existsSync(path2.join(libPath, "manifest.json"))) {
463
+ errors.push({
464
+ ruleId: "krnl/frontend-concept-manifest-required",
465
+ filePath: libPath,
466
+ message: `Frontend concept library "${entry.name}" is missing a manifest.json file.`,
467
+ severity: "error"
468
+ });
469
+ }
470
+ }
471
+ }
472
+ const fFuncs = path2.join(frontendDir, "functionalities");
473
+ if (fs.existsSync(fFuncs)) {
474
+ for (const entry of fs.readdirSync(fFuncs, { withFileTypes: true })) {
475
+ if (!entry.isDirectory()) continue;
476
+ const funcPath = path2.join(fFuncs, entry.name);
477
+ if (!fs.existsSync(path2.join(funcPath, "manifest.json"))) {
478
+ errors.push({
479
+ ruleId: "krnl/frontend-functionality-manifest-required",
480
+ filePath: funcPath,
481
+ message: `Frontend functionality "${entry.name}" is missing a manifest.json file.`,
482
+ severity: "error"
483
+ });
461
484
  }
462
485
  }
463
- const fFuncs = path.join(frontendDir, "functionalities");
464
- if (fs.existsSync(fFuncs)) {
465
- for (const entry of fs.readdirSync(fFuncs, { withFileTypes: true })) {
466
- if (!entry.isDirectory()) continue;
467
- const funcPath = path.join(fFuncs, entry.name);
468
- const manifestPath = path.join(funcPath, "manifest.json");
469
- if (!fs.existsSync(manifestPath)) {
486
+ }
487
+ }
488
+ }
489
+
490
+ // src/rules/serviceBoundaryRules.ts
491
+ function checkServiceBoundaries(sf) {
492
+ const errors = [];
493
+ const warnings = [];
494
+ const filePath = sf.getFilePath().replace(/\\/g, "/");
495
+ const serviceMatch = filePath.match(/\/services\/([^/]+)\//);
496
+ if (!serviceMatch) {
497
+ return { errors, warnings };
498
+ }
499
+ const currentService = serviceMatch[1];
500
+ const imports = sf.getImportDeclarations();
501
+ for (const imp of imports) {
502
+ const spec = imp.getModuleSpecifierValue();
503
+ const crossServiceLibMatch = spec.match(/(?:^|\/|\.\.\/)services\/([^/]+)\/libraries\//) || spec.match(/\.\.\/(?:(?:\.\.\/)+)?([^/]+)\/libraries\//);
504
+ if (crossServiceLibMatch) {
505
+ const targetService = crossServiceLibMatch[1];
506
+ if (targetService !== currentService && targetService !== "." && targetService !== "..") {
507
+ errors.push({
508
+ ruleId: "krnl/no-cross-service-library-imports",
509
+ filePath,
510
+ line: imp.getStartLineNumber(),
511
+ message: `Cross-service library import forbidden: '${spec}'. Service '${currentService}' cannot import '${targetService}' libraries directly via filesystem. Access libraries through the '${targetService}' ServiceFacade (e.g. ${targetService}Facade.libraries).`,
512
+ severity: "error"
513
+ });
514
+ }
515
+ }
516
+ }
517
+ return { errors, warnings };
518
+ }
519
+
520
+ // src/rules/scopedLibraryRules.ts
521
+ var import_ts_morph4 = require("ts-morph");
522
+ var PRIMITIVE_AND_BUILTIN_TYPES = /* @__PURE__ */ new Set([
523
+ "string",
524
+ "number",
525
+ "boolean",
526
+ "symbol",
527
+ "bigint",
528
+ "void",
529
+ "undefined",
530
+ "null",
531
+ "never",
532
+ "unknown",
533
+ "any",
534
+ "object",
535
+ "Record",
536
+ "Array",
537
+ "ReadonlyArray",
538
+ "Map",
539
+ "Set",
540
+ "WeakMap",
541
+ "WeakSet",
542
+ "Promise",
543
+ "Date",
544
+ "RegExp",
545
+ "Error",
546
+ "Uint8Array",
547
+ "Int8Array",
548
+ "Uint16Array",
549
+ "Int16Array",
550
+ "Uint32Array",
551
+ "Int32Array",
552
+ "Float32Array",
553
+ "Float64Array",
554
+ "ArrayBuffer",
555
+ "Buffer",
556
+ "Iterable",
557
+ "AsyncIterable",
558
+ "Iterator",
559
+ "AsyncIterator",
560
+ "Partial",
561
+ "Required",
562
+ "Readonly",
563
+ "Pick",
564
+ "Omit",
565
+ "Exclude",
566
+ "Extract",
567
+ "NonNullable",
568
+ "Parameters",
569
+ "ConstructorParameters",
570
+ "ReturnType",
571
+ "InstanceType"
572
+ ]);
573
+ function detectServiceContext(filePath) {
574
+ const normalized = filePath.replace(/\\/g, "/");
575
+ const match = normalized.match(/(?:^|\/)services\/([^/]+)\/libraries\/([^/]+)/);
576
+ if (match) {
577
+ return { serviceName: match[1], libraryName: match[2] };
578
+ }
579
+ return null;
580
+ }
581
+ function containsIdentifier(name, target) {
582
+ return name.toLowerCase().includes(target.toLowerCase());
583
+ }
584
+ function isCustomContextualType(typeName, serviceName, localTypes) {
585
+ if (PRIMITIVE_AND_BUILTIN_TYPES.has(typeName)) return false;
586
+ if (localTypes.has(typeName)) return true;
587
+ if (containsIdentifier(typeName, serviceName)) return true;
588
+ if (/^[A-Z][a-zA-Z0-9]+$/.test(typeName)) return true;
589
+ return false;
590
+ }
591
+ function hasContextualTypeReference(node, serviceName, localTypes) {
592
+ const typeRefs = node.getDescendantsOfKind(import_ts_morph4.SyntaxKind.TypeReference);
593
+ for (const ref of typeRefs) {
594
+ const text = ref.getTypeName().getText().trim();
595
+ if (isCustomContextualType(text, serviceName, localTypes)) {
596
+ return true;
597
+ }
598
+ }
599
+ return false;
600
+ }
601
+ function checkScopedLibraryRules(sf) {
602
+ const errors = [];
603
+ const warnings = [];
604
+ const promotableAssets = [];
605
+ const filePath = sf.getFilePath().replace(/\\/g, "/");
606
+ const context = detectServiceContext(filePath);
607
+ if (!context) {
608
+ return { errors, warnings, promotableAssets };
609
+ }
610
+ const { serviceName, libraryName } = context;
611
+ const localTypes = /* @__PURE__ */ new Set();
612
+ sf.getInterfaces().forEach((i) => localTypes.add(i.getName()));
613
+ sf.getTypeAliases().forEach((t) => localTypes.add(t.getName()));
614
+ sf.getClasses().forEach((c) => {
615
+ const n = c.getName();
616
+ if (n) localTypes.add(n);
617
+ });
618
+ sf.getEnums().forEach((e) => localTypes.add(e.getName()));
619
+ const functions = sf.getFunctions();
620
+ for (const fn of functions) {
621
+ const fnName = fn.getName();
622
+ if (!fnName) continue;
623
+ const isContextual = hasContextualTypeReference(fn, serviceName, localTypes);
624
+ const hasServiceName = containsIdentifier(fnName, serviceName);
625
+ if (isContextual) {
626
+ if (!hasServiceName) {
627
+ errors.push({
628
+ ruleId: "krnl/service-library-asset-naming",
629
+ filePath,
630
+ line: fn.getStartLineNumber(),
631
+ message: `Service library asset '${fnName}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}'). Expected name containing '${serviceName}' (e.g. '${serviceName.toLowerCase()}${fnName[0].toUpperCase()}${fnName.slice(1)}'), or eliminate contextual custom type dependencies to make it a generic promotable utility.`,
632
+ severity: "error"
633
+ });
634
+ }
635
+ } else {
636
+ promotableAssets.push({
637
+ name: fnName,
638
+ kind: "function",
639
+ filePath,
640
+ scope: "service",
641
+ scopeName: serviceName,
642
+ target: "GutTS"
643
+ });
644
+ }
645
+ }
646
+ for (const stmt of sf.getVariableStatements()) {
647
+ for (const decl of stmt.getDeclarations()) {
648
+ const varName = decl.getName();
649
+ const init = decl.getInitializer();
650
+ const isFunction = init && (init.getKind() === import_ts_morph4.SyntaxKind.ArrowFunction || init.getKind() === import_ts_morph4.SyntaxKind.FunctionExpression);
651
+ if (isFunction) {
652
+ const isContextual = hasContextualTypeReference(decl, serviceName, localTypes);
653
+ const hasServiceName = containsIdentifier(varName, serviceName);
654
+ if (isContextual) {
655
+ if (!hasServiceName) {
470
656
  errors.push({
471
- ruleId: "krnl/frontend-functionality-manifest-required",
472
- filePath: funcPath,
473
- message: `Frontend functionality "${entry.name}" is missing a manifest.json file.`,
657
+ ruleId: "krnl/service-library-asset-naming",
658
+ filePath,
659
+ line: decl.getStartLineNumber(),
660
+ message: `Service library asset '${varName}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}'). Expected name containing '${serviceName}', or eliminate contextual custom type dependencies to make it a generic promotable utility.`,
474
661
  severity: "error"
475
662
  });
476
663
  }
664
+ } else {
665
+ promotableAssets.push({
666
+ name: varName,
667
+ kind: "function",
668
+ filePath,
669
+ scope: "service",
670
+ scopeName: serviceName,
671
+ target: "GutTS"
672
+ });
673
+ }
674
+ } else {
675
+ const isContextual = hasContextualTypeReference(decl, serviceName, localTypes);
676
+ const hasServiceName = containsIdentifier(varName, serviceName);
677
+ if (isContextual && !hasServiceName) {
678
+ errors.push({
679
+ ruleId: "krnl/service-library-asset-naming",
680
+ filePath,
681
+ line: decl.getStartLineNumber(),
682
+ message: `Service library asset '${varName}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}').`,
683
+ severity: "error"
684
+ });
477
685
  }
478
686
  }
479
687
  }
480
688
  }
689
+ for (const iface of sf.getInterfaces()) {
690
+ const name = iface.getName();
691
+ const hasServiceName = containsIdentifier(name, serviceName);
692
+ const hasProps = iface.getProperties().length > 0;
693
+ if (hasProps && !hasServiceName) {
694
+ errors.push({
695
+ ruleId: "krnl/service-library-asset-naming",
696
+ filePath,
697
+ line: iface.getStartLineNumber(),
698
+ message: `Service library interface '${name}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}'). Expected name like '${serviceName}${name}'.`,
699
+ severity: "error"
700
+ });
701
+ }
702
+ }
703
+ for (const t of sf.getTypeAliases()) {
704
+ const name = t.getName();
705
+ const hasServiceName = containsIdentifier(name, serviceName);
706
+ const isContextual = hasContextualTypeReference(t, serviceName, localTypes);
707
+ if (isContextual && !hasServiceName) {
708
+ errors.push({
709
+ ruleId: "krnl/service-library-asset-naming",
710
+ filePath,
711
+ line: t.getStartLineNumber(),
712
+ message: `Service library type alias '${name}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}'). Expected name like '${serviceName}${name}'.`,
713
+ severity: "error"
714
+ });
715
+ }
716
+ }
717
+ for (const cls of sf.getClasses()) {
718
+ const name = cls.getName();
719
+ if (!name) continue;
720
+ const hasServiceName = containsIdentifier(name, serviceName);
721
+ if (!hasServiceName) {
722
+ errors.push({
723
+ ruleId: "krnl/service-library-asset-naming",
724
+ filePath,
725
+ line: cls.getStartLineNumber(),
726
+ message: `Service library class '${name}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}'). Expected name like '${serviceName}${name}'.`,
727
+ severity: "error"
728
+ });
729
+ }
730
+ }
731
+ return { errors, warnings, promotableAssets };
732
+ }
733
+
734
+ // src/KrnlValidatorEngine.ts
735
+ var KrnlValidatorEngine = class {
736
+ project;
737
+ projectRoot;
738
+ limitOptions;
739
+ constructor(optionsOrRoot) {
740
+ const options = typeof optionsOrRoot === "string" ? { projectRoot: optionsOrRoot } : optionsOrRoot;
741
+ this.projectRoot = path3.resolve(options.projectRoot || process.cwd());
742
+ this.limitOptions = {
743
+ maxFileLineLimit: options.maxFileLineLimit ?? 200,
744
+ maxMainLogicLimit: options.maxMainLogicLimit ?? 20,
745
+ maxHelperLineLimit: options.maxHelperLineLimit ?? 30
746
+ };
747
+ const tsConfigPath = path3.join(this.projectRoot, "tsconfig.json");
748
+ if (fs2.existsSync(tsConfigPath)) {
749
+ this.project = new import_ts_morph5.Project({ tsConfigFilePath: tsConfigPath, skipAddingFilesFromTsConfig: true });
750
+ } else {
751
+ this.project = new import_ts_morph5.Project({ compilerOptions: {
752
+ target: 99
753
+ /* ESNext */
754
+ } });
755
+ }
756
+ }
757
+ validateAll() {
758
+ const files = this.collectSourceFiles(this.projectRoot);
759
+ const errors = [];
760
+ const warnings = [];
761
+ const promotableAssets = [];
762
+ checkWorkspaceLayout(this.projectRoot, errors);
763
+ for (const f of files) {
764
+ const sf = this.project.addSourceFileAtPath(f);
765
+ const fileReport = this.validateSourceFile(sf);
766
+ errors.push(...fileReport.errors);
767
+ warnings.push(...fileReport.warnings);
768
+ if (fileReport.promotableAssets) {
769
+ promotableAssets.push(...fileReport.promotableAssets);
770
+ }
771
+ }
772
+ return {
773
+ valid: errors.length === 0,
774
+ totalFiles: files.length,
775
+ errors,
776
+ warnings,
777
+ promotableAssets
778
+ };
779
+ }
780
+ validateSourceFile(sf) {
781
+ const filePath = sf.getFilePath();
782
+ const baseName = path3.basename(filePath);
783
+ if (baseName.includes("_pb.") || baseName.endsWith(".d.ts")) {
784
+ return { errors: [], warnings: [], promotableAssets: [] };
785
+ }
786
+ const limits = checkFileLimits(sf, this.limitOptions);
787
+ const purity = checkTopLevelPurity(sf);
788
+ const components = checkComponentRules(sf);
789
+ const orchestration = checkOrchestrationRules(sf);
790
+ const boundaries = checkServiceBoundaries(sf);
791
+ const scopedLibraries = checkScopedLibraryRules(sf);
792
+ return {
793
+ errors: [
794
+ ...limits.errors,
795
+ ...purity.errors,
796
+ ...components.errors,
797
+ ...orchestration.errors,
798
+ ...boundaries.errors,
799
+ ...scopedLibraries.errors
800
+ ],
801
+ warnings: [
802
+ ...limits.warnings,
803
+ ...purity.warnings,
804
+ ...components.warnings,
805
+ ...orchestration.warnings,
806
+ ...boundaries.warnings,
807
+ ...scopedLibraries.warnings
808
+ ],
809
+ promotableAssets: scopedLibraries.promotableAssets
810
+ };
811
+ }
481
812
  collectSourceFiles(dir, collected = []) {
482
- if (!fs.existsSync(dir)) return collected;
483
- const entries = fs.readdirSync(dir, { withFileTypes: true });
813
+ if (!fs2.existsSync(dir)) return collected;
814
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
484
815
  for (const entry of entries) {
485
816
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") continue;
486
- const full = path.join(dir, entry.name);
817
+ const full = path3.join(dir, entry.name);
487
818
  if (entry.isDirectory()) {
488
819
  this.collectSourceFiles(full, collected);
489
820
  } else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js") || entry.name.endsWith(".tsx") || entry.name.endsWith(".jsx"))) {