@a-company/paradigm 5.11.0 → 5.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (408) hide show
  1. package/dist/accept-orchestration-IUAWQZUN.js +18 -0
  2. package/dist/add-P76GEMGF.js +8 -0
  3. package/dist/agent-UUTYOFTH.js +33 -0
  4. package/dist/agent-loader-EPXURMO7.js +2 -0
  5. package/dist/agent-loader-PYGPX6D2.js +2 -0
  6. package/dist/agent-state-KSQ3S7OB.js +2 -0
  7. package/dist/agents-suggest-HYTFMQD3.js +10 -0
  8. package/dist/aggregate-W66DM3GA.js +10 -0
  9. package/dist/ambient-HYZR42NX.js +35 -0
  10. package/dist/assess-UFPYEJKP.js +9 -0
  11. package/dist/auto-RHJXOZFL.js +14 -0
  12. package/dist/beacon-5QVYV5DF.js +13 -0
  13. package/dist/calibration-OLJYB5HN.js +7 -0
  14. package/dist/check-THVGY4R5.js +14 -0
  15. package/dist/chunk-22ISTMKI.js +31 -0
  16. package/dist/chunk-2QO33NYK.js +3 -0
  17. package/dist/chunk-33LKBMVK.js +134 -0
  18. package/dist/chunk-4QADCWPU.js +7 -0
  19. package/dist/chunk-4TXOVRWD.js +3 -0
  20. package/dist/chunk-4UJ4NIEQ.js +4 -0
  21. package/dist/chunk-4ZGGWZ32.js +3 -0
  22. package/dist/chunk-5TAVYPOV.js +2 -0
  23. package/dist/chunk-6EX37L4Q.js +8 -0
  24. package/dist/chunk-AD5TAD2A.js +5 -0
  25. package/dist/chunk-AGVAHVUA.js +2 -0
  26. package/dist/chunk-AO7ZSRME.js +13 -0
  27. package/dist/chunk-BFD3GFRK.js +2 -0
  28. package/dist/chunk-D34YFK4M.js +6 -0
  29. package/dist/chunk-DVZWCXB6.js +2 -0
  30. package/dist/chunk-EKZDFEJW.js +2 -0
  31. package/dist/chunk-ET5XJTSX.js +2 -0
  32. package/dist/chunk-FYDRENK7.js +3 -0
  33. package/dist/chunk-HMQ5BHP2.js +743 -0
  34. package/dist/chunk-HXKWL3VK.js +29 -0
  35. package/dist/chunk-IZSBGW6E.js +2 -0
  36. package/dist/chunk-J32OPJEX.js +2 -0
  37. package/dist/chunk-JBDMCRPP.js +7 -0
  38. package/dist/chunk-JIXHEBGK.js +7 -0
  39. package/dist/chunk-JNSJVCTU.js +2 -0
  40. package/dist/chunk-JQKKVAAN.js +2 -0
  41. package/dist/chunk-KLBH26PA.js +429 -0
  42. package/dist/chunk-L6K5HNDL.js +24 -0
  43. package/dist/chunk-LKAT7IAK.js +2 -0
  44. package/dist/chunk-M4UMM6DC.js +5 -0
  45. package/dist/chunk-NKYNHSA5.js +424 -0
  46. package/dist/chunk-NW6OKHE6.js +5 -0
  47. package/dist/chunk-NXRVR37G.js +60 -0
  48. package/dist/chunk-ODVKPZZ4.js +2 -0
  49. package/dist/chunk-PUBB7LIT.js +5 -0
  50. package/dist/chunk-Q2J542ST.js +2 -0
  51. package/dist/chunk-QGZRM6ZB.js +2 -0
  52. package/dist/chunk-QNZEG7IT.js +13 -0
  53. package/dist/chunk-QT2LKB3P.js +7 -0
  54. package/dist/chunk-RVRARWSY.js +9 -0
  55. package/dist/chunk-T6IDXUUA.js +2 -0
  56. package/dist/chunk-TYWB5IQJ.js +3 -0
  57. package/dist/chunk-UIKLE3WD.js +2 -0
  58. package/dist/chunk-V7K6CQVX.js +111 -0
  59. package/dist/chunk-VCKKJDLP.js +8 -0
  60. package/dist/chunk-VG7FN2TU.js +4 -0
  61. package/dist/chunk-W5IWDW4Y.js +16 -0
  62. package/dist/chunk-W7C6FFMO.js +8 -0
  63. package/dist/chunk-WESTEMIM.js +10 -0
  64. package/dist/chunk-WR6D3SC6.js +5 -0
  65. package/dist/chunk-WS2N27RX.js +3 -0
  66. package/dist/chunk-XMAV5AG6.js +2 -0
  67. package/dist/chunk-XROULIQN.js +2 -0
  68. package/dist/chunk-XUFYOXOU.js +3 -0
  69. package/dist/chunk-Y4XFVDZC.js +3 -0
  70. package/dist/chunk-Y6KXTQBG.js +2 -0
  71. package/dist/{chunk-GTR2TBIJ.js → chunk-Z2UZUCY6.js} +237 -1047
  72. package/dist/chunk-Z34K6GY2.js +8 -0
  73. package/dist/claude-4LR3LJQZ.js +13 -0
  74. package/dist/claude-cli-UP6HGH7C.js +6 -0
  75. package/dist/claude-code-RLJ4GX77.js +11 -0
  76. package/dist/claude-code-teams-R37HJY3Y.js +29 -0
  77. package/dist/commands-LMUD5L6R.js +455 -0
  78. package/dist/compliance-GZ7UAOG3.js +6 -0
  79. package/dist/conductor-Y5IXELTL.js +4 -0
  80. package/dist/config-schema-HR7LDEQ6.js +2 -0
  81. package/dist/constellation-CG7C4WFE.js +13 -0
  82. package/dist/context-audit-RSSRX6XC.js +6 -0
  83. package/dist/cost-IDNVMAEV.js +10 -0
  84. package/dist/cost-PK4KIF7R.js +2 -0
  85. package/dist/cursor-cli-QKF7Z6M2.js +4 -0
  86. package/dist/cursorrules-U5O4G5T4.js +14 -0
  87. package/dist/decision-loader-2XPZE4EZ.js +2 -0
  88. package/dist/delete-P5VULXR4.js +14 -0
  89. package/dist/diff-RTFUKJHF.js +9 -0
  90. package/dist/discipline-H7LDI6NT.js +2 -0
  91. package/dist/dist-3ZCH25SG.js +2 -0
  92. package/dist/dist-KGRCLBJP-2QAPFYNF.js +39 -0
  93. package/dist/dist-R3RWD35F.js +2 -0
  94. package/dist/dist-VGFSP3XM.js +2 -0
  95. package/dist/dist-VXCZWVVJ.js +2 -0
  96. package/dist/dist-W3XCATBJ.js +2 -0
  97. package/dist/docs-EDQ2STFK.js +2 -0
  98. package/dist/docs-RXPN6CK7.js +12 -0
  99. package/dist/doctor-2T2QL6VM.js +2 -0
  100. package/dist/drift-ILZE5BFJ.js +13 -0
  101. package/dist/echo-UPTQUEDU.js +46 -0
  102. package/dist/edit-GUU3HBVW.js +9 -0
  103. package/dist/event-Y3VXC2RV.js +3 -0
  104. package/dist/explain-files-3GPZUETV.js +4 -0
  105. package/dist/export-CV5KCTPS.js +2 -0
  106. package/dist/flow-S3RQ4YPY.js +11 -0
  107. package/dist/global-C44FW4G2.js +13 -0
  108. package/dist/graduate-3BBSC27A.js +5 -0
  109. package/dist/graph-CNDE5TAT.js +2 -0
  110. package/dist/graph-server-COZR5C3Z.js +14 -0
  111. package/dist/habits-4J2KRYUL.js +42 -0
  112. package/dist/history-UW454SDP.js +12 -0
  113. package/dist/hooks-XH52VGOU.js +2 -0
  114. package/dist/index.js +15 -1039
  115. package/dist/init-24MAQJFM.js +2 -0
  116. package/dist/integrity-UYDOOJDP.js +7 -0
  117. package/dist/integrity-checker-DHGMZQDG.js +2 -0
  118. package/dist/journal-loader-GLH7XFTK.js +2 -0
  119. package/dist/lint-IGKE6UPS.js +26 -0
  120. package/dist/list-5IUGP3ZB.js +7 -0
  121. package/dist/list-YKIQNKGB.js +6 -0
  122. package/dist/lore-loader-RVQI5GXL.js +2 -0
  123. package/dist/lore-loader-XY5MZRR2.js +2 -0
  124. package/dist/lore-server-FC2GMDLT.js +14 -0
  125. package/dist/manual-RXSPSFLL.js +20 -0
  126. package/dist/mcp.js +93 -20529
  127. package/dist/migrate-X5OMAFAQ.js +59 -0
  128. package/dist/migrate-assessments-GEI5WMI2.js +4 -0
  129. package/dist/model-discovery-HMB3YI4L.js +2 -0
  130. package/dist/nomination-engine-XF7TWPAP.js +2 -0
  131. package/dist/notebook-PE3JSYZI.js +11 -0
  132. package/dist/notebook-loader-CENTDDUJ.js +2 -0
  133. package/dist/orchestrate-35HBQ3O3.js +8 -0
  134. package/dist/peers-P2KXU7ZK.js +5 -0
  135. package/dist/persona-STQWZH5P.js +29 -0
  136. package/dist/pipeline-MZUITRVN.js +4 -0
  137. package/dist/platform-server-2KXHGHFV.js +25 -0
  138. package/dist/plugin-update-checker-M7PW434O.js +2 -0
  139. package/dist/portal-check-3JVNLOEP.js +8 -0
  140. package/dist/portal-compliance-2UG4VKWH.js +2 -0
  141. package/dist/probe-5L5BQDGE.js +6 -0
  142. package/dist/project-type-SURTOIG7.js +2 -0
  143. package/dist/promote-NJQDZBZA.js +8 -0
  144. package/dist/providers-4PXMWA7V.js +8 -0
  145. package/dist/quiz-FE5UGAY2.js +10 -0
  146. package/dist/record-YXPB34MY.js +6 -0
  147. package/dist/reindex-PGDQSM42.js +2 -0
  148. package/dist/remember-MJRNTXYS.js +14 -0
  149. package/dist/retag-N5XF3KXP.js +6 -0
  150. package/dist/review-6UAH6V3R.js +11 -0
  151. package/dist/review-77QI6VOC.js +6 -0
  152. package/dist/ripple-ZGDITCGB.js +10 -0
  153. package/dist/roster-FLRZ5J42.js +2 -0
  154. package/dist/sentinel-HYAZ3CO5.js +19 -0
  155. package/dist/sentinel-bridge-VR357PKL.js +2 -0
  156. package/dist/sentinel-mcp.js +38 -3808
  157. package/dist/sentinel.js +1 -34
  158. package/dist/serve-JE6UF5P2.js +8 -0
  159. package/dist/serve-L52ZUTU6.js +10 -0
  160. package/dist/serve-OY6XYL7F.js +12 -0
  161. package/dist/server-2MNROHF6.js +7 -0
  162. package/dist/server-4YNUIK4W.js +8 -0
  163. package/dist/session-tracker-SKOMBDOW.js +2 -0
  164. package/dist/session-work-log-3MNUDEZ6.js +2 -0
  165. package/dist/session-work-log-J2H5OZBR.js +2 -0
  166. package/dist/setup-3F5IK7MO.js +31 -0
  167. package/dist/setup-KPIMRZ4Q.js +2 -0
  168. package/dist/shift-6GCNH666.js +11 -0
  169. package/dist/show-BOAVWZPZ.js +7 -0
  170. package/dist/show-PJ5LFLIL.js +5 -0
  171. package/dist/snapshot-L2G56RPL.js +8 -0
  172. package/dist/spawn-UH5RENSE.js +12 -0
  173. package/dist/status-77M3SDIF.js +8 -0
  174. package/dist/status-A37ECYNJ.js +6 -0
  175. package/dist/summary-ZJLQ6KHB.js +7 -0
  176. package/dist/sweep-HU74OPVW.js +17 -0
  177. package/dist/switch-CTW4PDGI.js +17 -0
  178. package/dist/symphony-3QMBGCZY.js +2 -0
  179. package/dist/symphony-QI63XL62.js +53 -0
  180. package/dist/symphony-loader-XACVV2E3.js +2 -0
  181. package/dist/symphony-peers-U4KHMKGI.js +2 -0
  182. package/dist/symphony-peers-X5NGWXFP.js +2 -0
  183. package/dist/symphony-relay-5GY5JIPT.js +3 -0
  184. package/dist/sync-QRDSFETO.js +2 -0
  185. package/dist/sync-llms-HL5PPW3M.js +15 -0
  186. package/dist/task-loader-NZFDTUQ5.js +2 -0
  187. package/dist/team-WGERKGNP.js +2 -0
  188. package/dist/test-BQJMS4Y2.js +111 -0
  189. package/dist/thread-HFXK65D4.js +41 -0
  190. package/dist/timeline-K3ZFKJ3R.js +6 -0
  191. package/dist/triage-FCWOZASE.js +18 -0
  192. package/dist/tutorial-UC6YQMNN.js +305 -0
  193. package/dist/university-content/courses/.purpose +74 -5
  194. package/dist/university-content/plsat/.purpose +3 -2
  195. package/dist/university-ui/assets/{index-BjewBB6s.js → index-CGFJczb1.js} +2 -2
  196. package/dist/university-ui/assets/{index-BjewBB6s.js.map → index-CGFJczb1.js.map} +1 -1
  197. package/dist/university-ui/index.html +1 -1
  198. package/dist/upgrade-B4IOLZYK.js +53 -0
  199. package/dist/validate-C6SMKGYD.js +9 -0
  200. package/dist/validate-LSCDOLBO.js +13 -0
  201. package/dist/validate-VZXTJHGO.js +6 -0
  202. package/dist/watch-LRM5XD46.js +8 -0
  203. package/dist/watch-PZCCUP6K.js +9 -0
  204. package/dist/wisdom-XZ3QKPNP.js +7 -0
  205. package/dist/work-log-loader-DL5GZ2BQ.js +2 -0
  206. package/dist/workspace-2ODL5WLY.js +2 -0
  207. package/package.json +1 -1
  208. package/platform-ui/dist/assets/AmbientSection-DqQ2mfCO.js +1 -0
  209. package/platform-ui/dist/assets/{CanvasSection-DwPTRdIN.js → CanvasSection-DLW0s-Bu.js} +1 -1
  210. package/platform-ui/dist/assets/{DocsSection-BJc_ws4I.js → DocsSection-BQ9Hi51g.js} +1 -1
  211. package/platform-ui/dist/assets/{GitSection-DhqBo1xc.js → GitSection-QQeUX6o3.js} +1 -1
  212. package/platform-ui/dist/assets/{GraphSection-D9fhVnZ0.js → GraphSection-0c9C-w7K.js} +2 -2
  213. package/platform-ui/dist/assets/{GraphSection-BlgXTl53.css → GraphSection-Bbs2a8sC.css} +1 -1
  214. package/platform-ui/dist/assets/LoreSection--t56kCj2.js +1 -0
  215. package/platform-ui/dist/assets/LoreSection-qnmm3o4y.css +1 -0
  216. package/platform-ui/dist/assets/SentinelSection-C4OoME9U.js +1 -0
  217. package/platform-ui/dist/assets/{SymphonySection-BRoBaUSS.js → SymphonySection-B-rvsLxq.js} +1 -1
  218. package/platform-ui/dist/assets/TeamSection-CBFmNEEo.js +1 -0
  219. package/platform-ui/dist/assets/index-Bxp0TVaf.css +1 -0
  220. package/platform-ui/dist/assets/index-DPpOdAtC.js +57 -0
  221. package/platform-ui/dist/index.html +2 -2
  222. package/dist/accept-orchestration-UQLM7PTQ.js +0 -189
  223. package/dist/add-FZRKEGH4.js +0 -81
  224. package/dist/agent-WERIO2XV.js +0 -523
  225. package/dist/agent-loader-TFIANSF4.js +0 -44
  226. package/dist/agent-state-S5DAWPTF.js +0 -24
  227. package/dist/agents-suggest-DNSYJ6IA.js +0 -83
  228. package/dist/aggregate-H57K7PNV.js +0 -88
  229. package/dist/assess-4WVXZLZQ.js +0 -68
  230. package/dist/auto-QFS5NHQU.js +0 -504
  231. package/dist/beacon-KXZXYQHX.js +0 -251
  232. package/dist/calibration-V46G7JTY.js +0 -135
  233. package/dist/check-OWAIWV23.js +0 -175
  234. package/dist/chunk-2IO7JAG2.js +0 -148
  235. package/dist/chunk-2T6BTYBN.js +0 -712
  236. package/dist/chunk-36TKPM5Z.js +0 -400
  237. package/dist/chunk-45MUDW6E.js +0 -804
  238. package/dist/chunk-4BLYIB7J.js +0 -5701
  239. package/dist/chunk-4L3UTYQX.js +0 -677
  240. package/dist/chunk-4NCFWYGG.js +0 -110
  241. package/dist/chunk-54LTTQBH.js +0 -138
  242. package/dist/chunk-5EWAQHFY.js +0 -269
  243. package/dist/chunk-5JGJACDU.js +0 -37
  244. package/dist/chunk-5OUOLN6M.js +0 -659
  245. package/dist/chunk-5VKJBNJL.js +0 -444
  246. package/dist/chunk-6N3JTACN.js +0 -2260
  247. package/dist/chunk-6QC3YGB6.js +0 -114
  248. package/dist/chunk-7N7GSU6K.js +0 -34
  249. package/dist/chunk-ABVQGRF7.js +0 -268
  250. package/dist/chunk-CL7JSK52.js +0 -129
  251. package/dist/chunk-CSD7IHSN.js +0 -152
  252. package/dist/chunk-EDOAWN7J.js +0 -717
  253. package/dist/chunk-EKGMAM62.js +0 -525
  254. package/dist/chunk-EZ3GOCYC.js +0 -132
  255. package/dist/chunk-F3BCHPYT.js +0 -143
  256. package/dist/chunk-FKJUBQU3.js +0 -3081
  257. package/dist/chunk-GT5QGC2H.js +0 -253
  258. package/dist/chunk-GZDFVP2N.js +0 -540
  259. package/dist/chunk-IRKUEJVW.js +0 -405
  260. package/dist/chunk-J2JEQRT3.js +0 -164
  261. package/dist/chunk-JASGXLK3.js +0 -679
  262. package/dist/chunk-KVDYJLTC.js +0 -121
  263. package/dist/chunk-L27I3CPZ.js +0 -357
  264. package/dist/chunk-LHLIAYQ3.js +0 -185
  265. package/dist/chunk-MCMOGQMU.js +0 -145
  266. package/dist/chunk-NQKQG45G.js +0 -688
  267. package/dist/chunk-PBHIFAL4.js +0 -259
  268. package/dist/chunk-PDX44BCA.js +0 -11
  269. package/dist/chunk-PMXRGPRQ.js +0 -305
  270. package/dist/chunk-RAB5IKPR.js +0 -487
  271. package/dist/chunk-RJE5G7WO.js +0 -590
  272. package/dist/chunk-RTHA3XRE.js +0 -880
  273. package/dist/chunk-S2HO5MLR.js +0 -621
  274. package/dist/chunk-S3ORKP3V.js +0 -716
  275. package/dist/chunk-TAIJOFOE.js +0 -124
  276. package/dist/chunk-TXESEO7Y.js +0 -245
  277. package/dist/chunk-UPLDI7CN.js +0 -1334
  278. package/dist/chunk-VL67H5IC.js +0 -506
  279. package/dist/chunk-VPPK3SY4.js +0 -1136
  280. package/dist/chunk-YMDLDELF.js +0 -314
  281. package/dist/chunk-YO6DVTL7.js +0 -99
  282. package/dist/chunk-YRZ5RPEB.js +0 -1561
  283. package/dist/chunk-ZDHLG5VP.js +0 -5676
  284. package/dist/chunk-ZGUAAVMA.js +0 -756
  285. package/dist/chunk-ZSYVKSY6.js +0 -2602
  286. package/dist/claude-FRRWJSTJ.js +0 -362
  287. package/dist/claude-cli-XJLK2X4L.js +0 -276
  288. package/dist/claude-code-HTBA4XRB.js +0 -126
  289. package/dist/claude-code-teams-T4SP24MD.js +0 -199
  290. package/dist/commands-5N4ILTPH.js +0 -5859
  291. package/dist/conductor-CQVGTEQN.js +0 -161
  292. package/dist/config-schema-EA4XALGG.js +0 -154
  293. package/dist/constellation-A26CCGQS.js +0 -225
  294. package/dist/context-audit-RLO3ETRP.js +0 -682
  295. package/dist/cost-BGM32XJU.js +0 -93
  296. package/dist/cost-VI46A4XL.js +0 -174
  297. package/dist/cursor-cli-JVEZGHWQ.js +0 -269
  298. package/dist/cursorrules-HLIKJJZT.js +0 -84
  299. package/dist/decision-loader-WWCLIQPJ.js +0 -20
  300. package/dist/delete-KBRPQLPC.js +0 -56
  301. package/dist/diff-D4X53HAC.js +0 -126
  302. package/dist/discipline-FA4OZXIS.js +0 -24
  303. package/dist/dist-34NA5RS5.js +0 -74
  304. package/dist/dist-5QE2BB2B-5S3T6Y3T.js +0 -6919
  305. package/dist/dist-77JDTVAY.js +0 -62
  306. package/dist/dist-OGTSAZ55.js +0 -1358
  307. package/dist/dist-QK4SQAK7.js +0 -64
  308. package/dist/dist-TA6LSC2Q.js +0 -20
  309. package/dist/docs-PBZB7LYP.js +0 -89
  310. package/dist/docs-QIYKO3BR.js +0 -155
  311. package/dist/doctor-ULBOHEIC.js +0 -11
  312. package/dist/drift-R5NRKFHI.js +0 -251
  313. package/dist/echo-O2LY7CC2.js +0 -248
  314. package/dist/edit-R2HNLMOG.js +0 -63
  315. package/dist/event-25OJKDCE.js +0 -31
  316. package/dist/export-IWVL7XLF.js +0 -38
  317. package/dist/flow-CRRVV3O3.js +0 -185
  318. package/dist/global-3NG5JXUB.js +0 -136
  319. package/dist/graduate-USAWGBJM.js +0 -160
  320. package/dist/graph-VHUMAAS6.js +0 -12
  321. package/dist/graph-server-YL22VBBN.js +0 -116
  322. package/dist/habits-OL5NGPXO.js +0 -1405
  323. package/dist/history-WOWC573W.js +0 -277
  324. package/dist/hooks-HFWSCGPV.js +0 -12
  325. package/dist/integrity-IHO4FZTS.js +0 -194
  326. package/dist/integrity-checker-PSKJA5SB.js +0 -12
  327. package/dist/journal-loader-5EYSBFFY.js +0 -18
  328. package/dist/lint-K6CJGGPH.js +0 -456
  329. package/dist/list-4YK7QKFF.js +0 -57
  330. package/dist/list-ENR7Q4CR.js +0 -56
  331. package/dist/lore-loader-7NO6N6FT.js +0 -26
  332. package/dist/lore-server-UNJY5KC3.js +0 -118
  333. package/dist/manual-G6FISID5.js +0 -204
  334. package/dist/migrate-LS45DNEV.js +0 -889
  335. package/dist/migrate-assessments-RGH4O6IX.js +0 -97
  336. package/dist/model-discovery-D2H3VBGC.js +0 -8
  337. package/dist/nomination-engine-RV5CNO5B.js +0 -42
  338. package/dist/notebook-YWIYGEHV.js +0 -155
  339. package/dist/orchestrate-JLILBBJE.js +0 -324
  340. package/dist/peers-DEOUIZM6.js +0 -82
  341. package/dist/persona-UHAHIVST.js +0 -390
  342. package/dist/pipeline-L4HCSBGN.js +0 -263
  343. package/dist/platform-server-H5YO3DQD.js +0 -1475
  344. package/dist/plugin-update-checker-KRRSGXMV.js +0 -12
  345. package/dist/portal-check-NPYGII2D.js +0 -42
  346. package/dist/portal-compliance-J7DGAPFX.js +0 -18
  347. package/dist/probe-MHL5HQZ2.js +0 -167
  348. package/dist/promote-F6ZYZZAL.js +0 -182
  349. package/dist/providers-GK7PB2OL.js +0 -104
  350. package/dist/quiz-M66SC7F7.js +0 -99
  351. package/dist/record-RA4WR2BO.js +0 -49
  352. package/dist/reindex-5LTD53ZC.js +0 -16
  353. package/dist/remember-HBWJ655S.js +0 -77
  354. package/dist/retag-3OLCVDEQ.js +0 -62
  355. package/dist/review-27ATYTD2.js +0 -33
  356. package/dist/review-57QMURZV.js +0 -334
  357. package/dist/ripple-JPBXP5I3.js +0 -215
  358. package/dist/sentinel-4XIG4STA.js +0 -63
  359. package/dist/sentinel-bridge-MDUXTQRL.js +0 -109
  360. package/dist/serve-CAH3PHE7.js +0 -33
  361. package/dist/serve-INL7SNBK.js +0 -36
  362. package/dist/serve-KBSE36PL.js +0 -49
  363. package/dist/server-54SKYFFY.js +0 -1647
  364. package/dist/server-XUOIO7E6.js +0 -338
  365. package/dist/session-tracker-C4BMD5WG.js +0 -13
  366. package/dist/session-work-log-MZ47OAPB.js +0 -20
  367. package/dist/setup-EDS27WUR.js +0 -25
  368. package/dist/setup-KO5AFC4K.js +0 -296
  369. package/dist/shift-D2JOHHBF.js +0 -668
  370. package/dist/show-5PV5KFJE.js +0 -176
  371. package/dist/show-NQKYX6WQ.js +0 -82
  372. package/dist/snapshot-BK4RBPCG.js +0 -62
  373. package/dist/spawn-RCHNXDHE.js +0 -196
  374. package/dist/status-WGIAQODY.js +0 -71
  375. package/dist/summary-NIRABMF5.js +0 -140
  376. package/dist/sweep-QMHNSIY5.js +0 -934
  377. package/dist/switch-6EJPZDIA.js +0 -232
  378. package/dist/symphony-4OCY36AI.js +0 -791
  379. package/dist/symphony-B75X2MME.js +0 -326
  380. package/dist/symphony-loader-UZGON56V.js +0 -90
  381. package/dist/symphony-peers-2ZQYLRNI.js +0 -34
  382. package/dist/symphony-peers-OL7F6M5S.js +0 -121
  383. package/dist/symphony-relay-UJYUXN65.js +0 -710
  384. package/dist/sync-VEHUH4OA.js +0 -11
  385. package/dist/sync-llms-YHCFIE6X.js +0 -166
  386. package/dist/task-loader-LDYWQSLM.js +0 -20
  387. package/dist/team-O5MIIFMA.js +0 -34
  388. package/dist/test-566CP5KC.js +0 -1017
  389. package/dist/thread-N754I4D5.js +0 -274
  390. package/dist/timeline-M3CICQFE.js +0 -112
  391. package/dist/triage-HHYGT3HY.js +0 -671
  392. package/dist/tutorial-KD22SUNO.js +0 -666
  393. package/dist/upgrade-H5PF32BW.js +0 -551
  394. package/dist/validate-CNKEKO6A.js +0 -134
  395. package/dist/validate-MB5ULIHS.js +0 -39
  396. package/dist/validate-QH3LADM6.js +0 -64
  397. package/dist/watch-2TKP5PVL.js +0 -199
  398. package/dist/watch-ZF4ML6CD.js +0 -111
  399. package/dist/wisdom-AATMGNFA.js +0 -319
  400. package/dist/work-log-loader-5L45XNYZ.js +0 -14
  401. package/dist/workspace-6E6OSRNU.js +0 -21
  402. package/platform-ui/dist/assets/AmbientSection-WtHfNedO.js +0 -1
  403. package/platform-ui/dist/assets/LoreSection-C3EixkjW.css +0 -1
  404. package/platform-ui/dist/assets/LoreSection-CwDDHrz9.js +0 -1
  405. package/platform-ui/dist/assets/SentinelSection-Cl7e5oZ6.js +0 -1
  406. package/platform-ui/dist/assets/TeamSection-CqSIMrKz.js +0 -1
  407. package/platform-ui/dist/assets/index-CfpZFjea.css +0 -1
  408. package/platform-ui/dist/assets/index-F0KL9xrN.js +0 -57
@@ -1,2602 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- SentinelStorage
4
- } from "./chunk-FKJUBQU3.js";
5
-
6
- // ../sentinel/dist/chunk-VQ3SIN7S.js
7
- import { v4 as uuidv4 } from "uuid";
8
- var DEFAULTS = {
9
- url: "http://localhost:3838",
10
- batchSize: 50,
11
- flushIntervalMs: 5e3,
12
- maxBufferSize: 1e3,
13
- maxRetries: 3,
14
- retryBackoffMs: 1e3
15
- };
16
- var SentinelClient = class {
17
- url;
18
- service;
19
- version;
20
- environment;
21
- token;
22
- batchSize;
23
- maxBufferSize;
24
- maxRetries;
25
- retryBackoffMs;
26
- onDrop;
27
- onError;
28
- sessionId;
29
- logBuffer = [];
30
- metricsBuffer = [];
31
- flushTimer = null;
32
- closed = false;
33
- beforeUnloadHandler = null;
34
- constructor(options) {
35
- this.url = (options.url ?? DEFAULTS.url).replace(/\/+$/, "");
36
- this.service = options.service;
37
- this.version = options.version;
38
- this.environment = options.environment;
39
- this.token = options.token;
40
- this.batchSize = options.batchSize ?? DEFAULTS.batchSize;
41
- this.maxBufferSize = options.maxBufferSize ?? DEFAULTS.maxBufferSize;
42
- this.maxRetries = options.maxRetries ?? DEFAULTS.maxRetries;
43
- this.retryBackoffMs = options.retryBackoffMs ?? DEFAULTS.retryBackoffMs;
44
- this.onDrop = options.onDrop;
45
- this.onError = options.onError;
46
- this.sessionId = uuidv4();
47
- const intervalMs = options.flushIntervalMs ?? DEFAULTS.flushIntervalMs;
48
- this.flushTimer = setInterval(() => {
49
- this.flush().catch((err) => {
50
- this.handleError(err);
51
- });
52
- }, intervalMs);
53
- if (this.flushTimer && typeof this.flushTimer === "object" && "unref" in this.flushTimer) {
54
- this.flushTimer.unref();
55
- }
56
- if (typeof globalThis !== "undefined" && typeof globalThis.addEventListener === "function") {
57
- this.beforeUnloadHandler = () => {
58
- this.flushSync();
59
- };
60
- globalThis.addEventListener("beforeunload", this.beforeUnloadHandler);
61
- }
62
- this.registerService();
63
- }
64
- // ── Logging Methods ──────────────────────────────────────────────
65
- /** Log a debug-level message */
66
- debug(symbol, message, data) {
67
- this.log("debug", symbol, message, data);
68
- }
69
- /** Log an info-level message */
70
- info(symbol, message, data) {
71
- this.log("info", symbol, message, data);
72
- }
73
- /** Log a warn-level message */
74
- warn(symbol, message, data) {
75
- this.log("warn", symbol, message, data);
76
- }
77
- /** Log an error-level message */
78
- error(symbol, message, data) {
79
- this.log("error", symbol, message, data);
80
- }
81
- /** Log a message at the specified level */
82
- log(level, symbol, message, data) {
83
- if (this.closed) return;
84
- const entry = {
85
- level,
86
- symbol,
87
- message,
88
- service: this.service,
89
- sessionId: this.sessionId,
90
- environment: this.environment,
91
- data
92
- };
93
- this.pushToLogBuffer(entry);
94
- }
95
- // ── Metrics Methods ──────────────────────────────────────────────
96
- /** Record a counter metric (increments) */
97
- counter(name, value, tags) {
98
- this.metric({ name, type: "counter", value: value ?? 1, tags });
99
- }
100
- /** Record a gauge metric (current value) */
101
- gauge(name, value, tags) {
102
- this.metric({ name, type: "gauge", value, tags });
103
- }
104
- /** Record a histogram metric (distribution) */
105
- histogram(name, value, tags) {
106
- this.metric({ name, type: "histogram", value, tags });
107
- }
108
- /** Record a metric of any type */
109
- metric(input) {
110
- if (this.closed) return;
111
- const entry = {
112
- ...input,
113
- service: this.service,
114
- environment: this.environment
115
- };
116
- this.pushToMetricsBuffer(entry);
117
- }
118
- // ── State Push ───────────────────────────────────────────────────
119
- /** Push an application state snapshot to the server */
120
- async pushState(state, activeFlows, activeGates) {
121
- if (this.closed) return;
122
- await this.post("/api/state", {
123
- service: this.service,
124
- sessionId: this.sessionId,
125
- state,
126
- activeFlows,
127
- activeGates
128
- });
129
- }
130
- // ── Tracing ──────────────────────────────────────────────────────
131
- /** Start a trace span. Call end() on the returned SpanContext when the operation completes. */
132
- startSpan(symbol, operation, parentSpanId) {
133
- const traceId = parentSpanId ? parentSpanId.split("-")[0] || uuidv4() : uuidv4();
134
- const spanId = uuidv4();
135
- const startTime = (/* @__PURE__ */ new Date()).toISOString();
136
- const startMs = Date.now();
137
- const self = this;
138
- return {
139
- traceId,
140
- spanId,
141
- async end(status = "ok") {
142
- const endTime = (/* @__PURE__ */ new Date()).toISOString();
143
- const durationMs = Date.now() - startMs;
144
- const span = {
145
- traceId,
146
- spanId,
147
- parentSpanId,
148
- service: self.service,
149
- symbol,
150
- operation,
151
- startTime,
152
- endTime,
153
- durationMs,
154
- status
155
- };
156
- await self.post("/api/traces", span);
157
- }
158
- };
159
- }
160
- // ── Buffer Management ────────────────────────────────────────────
161
- /** Flush all buffered logs and metrics to the server */
162
- async flush() {
163
- const logEntries = this.drainLogBuffer();
164
- const metricEntries = this.drainMetricsBuffer();
165
- const promises = [];
166
- if (logEntries.length > 0) {
167
- promises.push(this.sendLogs(logEntries));
168
- }
169
- if (metricEntries.length > 0) {
170
- promises.push(this.sendMetrics(metricEntries));
171
- }
172
- await Promise.allSettled(promises);
173
- }
174
- // ── Lifecycle ────────────────────────────────────────────────────
175
- /** Flush remaining entries and shut down the client */
176
- async close() {
177
- if (this.closed) return;
178
- this.closed = true;
179
- if (this.flushTimer !== null) {
180
- clearInterval(this.flushTimer);
181
- this.flushTimer = null;
182
- }
183
- if (this.beforeUnloadHandler && typeof globalThis !== "undefined" && typeof globalThis.removeEventListener === "function") {
184
- globalThis.removeEventListener("beforeunload", this.beforeUnloadHandler);
185
- this.beforeUnloadHandler = null;
186
- }
187
- try {
188
- await this.flush();
189
- } catch {
190
- }
191
- }
192
- /** Get the session ID assigned to this client instance */
193
- getSessionId() {
194
- return this.sessionId;
195
- }
196
- /**
197
- * Synchronous best-effort flush using sendBeacon (browser) or sync XHR fallback.
198
- * Used in beforeunload where async is unreliable.
199
- */
200
- flushSync() {
201
- const logEntries = this.drainLogBuffer();
202
- const metricEntries = this.drainMetricsBuffer();
203
- const sendBeacon = typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function" ? navigator.sendBeacon.bind(navigator) : void 0;
204
- if (sendBeacon) {
205
- if (logEntries.length > 0) {
206
- sendBeacon(`${this.url}/api/logs`, JSON.stringify({ entries: logEntries }));
207
- }
208
- if (metricEntries.length > 0) {
209
- sendBeacon(`${this.url}/api/metrics`, JSON.stringify({ entries: metricEntries }));
210
- }
211
- }
212
- }
213
- // ═══════════════════════════════════════════════════════════════════
214
- // PRIVATE METHODS
215
- // ═══════════════════════════════════════════════════════════════════
216
- /** Register this service with the Sentinel server (fire-and-forget) */
217
- registerService() {
218
- const registration = {
219
- name: this.service,
220
- version: this.version,
221
- pid: typeof process !== "undefined" ? process.pid : void 0,
222
- environment: this.environment
223
- };
224
- this.post("/api/services", registration).catch(() => {
225
- });
226
- }
227
- /** Push a log entry into the ring buffer, enforcing maxBufferSize */
228
- pushToLogBuffer(entry) {
229
- if (this.logBuffer.length >= this.maxBufferSize) {
230
- const dropCount = Math.max(1, Math.floor(this.maxBufferSize * 0.1));
231
- this.logBuffer.splice(0, dropCount);
232
- if (this.onDrop) {
233
- this.onDrop(dropCount);
234
- }
235
- }
236
- this.logBuffer.push(entry);
237
- if (this.logBuffer.length >= this.batchSize) {
238
- this.flush().catch((err) => {
239
- this.handleError(err);
240
- });
241
- }
242
- }
243
- /** Push a metric entry into the ring buffer, enforcing maxBufferSize */
244
- pushToMetricsBuffer(entry) {
245
- if (this.metricsBuffer.length >= this.maxBufferSize) {
246
- const dropCount = Math.max(1, Math.floor(this.maxBufferSize * 0.1));
247
- this.metricsBuffer.splice(0, dropCount);
248
- if (this.onDrop) {
249
- this.onDrop(dropCount);
250
- }
251
- }
252
- this.metricsBuffer.push(entry);
253
- if (this.metricsBuffer.length >= this.batchSize) {
254
- this.flush().catch((err) => {
255
- this.handleError(err);
256
- });
257
- }
258
- }
259
- /** Drain and return all entries from the log buffer */
260
- drainLogBuffer() {
261
- const entries = this.logBuffer;
262
- this.logBuffer = [];
263
- return entries;
264
- }
265
- /** Drain and return all entries from the metrics buffer */
266
- drainMetricsBuffer() {
267
- const entries = this.metricsBuffer;
268
- this.metricsBuffer = [];
269
- return entries;
270
- }
271
- /** Send log entries to the server with retry */
272
- async sendLogs(entries) {
273
- try {
274
- await this.post("/api/logs", { entries });
275
- } catch (err) {
276
- const capacity = this.maxBufferSize - this.logBuffer.length;
277
- if (capacity > 0) {
278
- const toRestore = entries.slice(0, capacity);
279
- this.logBuffer.unshift(...toRestore);
280
- const dropped = entries.length - toRestore.length;
281
- if (dropped > 0 && this.onDrop) {
282
- this.onDrop(dropped);
283
- }
284
- } else if (this.onDrop) {
285
- this.onDrop(entries.length);
286
- }
287
- throw err;
288
- }
289
- }
290
- /** Send metric entries to the server with retry */
291
- async sendMetrics(entries) {
292
- try {
293
- await this.post("/api/metrics", { entries });
294
- } catch (err) {
295
- const capacity = this.maxBufferSize - this.metricsBuffer.length;
296
- if (capacity > 0) {
297
- const toRestore = entries.slice(0, capacity);
298
- this.metricsBuffer.unshift(...toRestore);
299
- const dropped = entries.length - toRestore.length;
300
- if (dropped > 0 && this.onDrop) {
301
- this.onDrop(dropped);
302
- }
303
- } else if (this.onDrop) {
304
- this.onDrop(entries.length);
305
- }
306
- throw err;
307
- }
308
- }
309
- /**
310
- * POST JSON to the Sentinel server with exponential backoff retry.
311
- * Retries on network errors and 5xx responses. Does NOT retry on 4xx.
312
- */
313
- async post(path4, body) {
314
- const fetchFn = this.getFetch();
315
- if (!fetchFn) {
316
- return void 0;
317
- }
318
- const url = `${this.url}${path4}`;
319
- const headers = {
320
- "Content-Type": "application/json"
321
- };
322
- if (this.token) {
323
- headers["Authorization"] = `Bearer ${this.token}`;
324
- }
325
- let lastError;
326
- for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
327
- try {
328
- const response = await fetchFn(url, {
329
- method: "POST",
330
- headers,
331
- body: JSON.stringify(body)
332
- });
333
- if (response.status >= 400 && response.status < 500) {
334
- const text = await response.text().catch(() => "");
335
- const err = new Error(`Sentinel server returned ${response.status}: ${text}`);
336
- this.handleError(err);
337
- return void 0;
338
- }
339
- if (response.status >= 500) {
340
- const text = await response.text().catch(() => "");
341
- lastError = new Error(`Sentinel server returned ${response.status}: ${text}`);
342
- if (attempt < this.maxRetries) {
343
- await this.backoff(attempt);
344
- continue;
345
- }
346
- this.handleError(lastError);
347
- throw lastError;
348
- }
349
- const contentType = response.headers.get("content-type") || "";
350
- if (contentType.includes("application/json")) {
351
- return await response.json();
352
- }
353
- return void 0;
354
- } catch (err) {
355
- lastError = err instanceof Error ? err : new Error(String(err));
356
- if (attempt < this.maxRetries) {
357
- await this.backoff(attempt);
358
- continue;
359
- }
360
- this.handleError(lastError);
361
- throw lastError;
362
- }
363
- }
364
- if (lastError) throw lastError;
365
- return void 0;
366
- }
367
- /** Get the fetch function, falling back to globalThis.fetch */
368
- getFetch() {
369
- if (typeof globalThis !== "undefined" && typeof globalThis.fetch === "function") {
370
- return globalThis.fetch;
371
- }
372
- return void 0;
373
- }
374
- /** Wait with exponential backoff */
375
- backoff(attempt) {
376
- const delayMs = this.retryBackoffMs * Math.pow(2, attempt);
377
- const jitter = Math.floor(Math.random() * delayMs * 0.25);
378
- return new Promise((resolve) => setTimeout(resolve, delayMs + jitter));
379
- }
380
- /** Handle an error, calling the onError callback if provided */
381
- handleError(err) {
382
- if (this.onError) {
383
- const error = err instanceof Error ? err : new Error(String(err));
384
- this.onError(error);
385
- }
386
- }
387
- };
388
- function createSentinelClient(options) {
389
- return new SentinelClient(options);
390
- }
391
- var SentinelTransport = class {
392
- client;
393
- constructor(client) {
394
- this.client = client;
395
- }
396
- send(entry) {
397
- this.client.log(
398
- entry.level,
399
- entry.symbol,
400
- entry.message,
401
- {
402
- ...entry.data,
403
- symbolType: entry.symbolType,
404
- correlationId: entry.correlationId
405
- }
406
- );
407
- }
408
- };
409
- function createSentinelTransport(clientOrOptions) {
410
- const client = clientOrOptions instanceof SentinelClient ? clientOrOptions : new SentinelClient(clientOrOptions);
411
- return new SentinelTransport(client);
412
- }
413
- function enableSentinel(logger, clientOrOptions) {
414
- const transport = createSentinelTransport(clientOrOptions);
415
- logger.addTransport(transport);
416
- return transport;
417
- }
418
-
419
- // ../sentinel/dist/index.js
420
- import * as path from "path";
421
- import * as fs from "fs";
422
- import { fileURLToPath } from "url";
423
- import * as fs2 from "fs";
424
- import * as path2 from "path";
425
- import * as fs3 from "fs";
426
- import * as path3 from "path";
427
- import * as fs4 from "fs";
428
- var DEFAULT_CONFIG = {
429
- minScore: 30,
430
- maxResults: 5,
431
- boostConfidence: true
432
- };
433
- var PatternMatcher = class {
434
- constructor(storage) {
435
- this.storage = storage;
436
- }
437
- /**
438
- * Match an incident against all patterns and return ranked results
439
- */
440
- match(incident, config = {}) {
441
- const { minScore, maxResults, boostConfidence } = {
442
- ...DEFAULT_CONFIG,
443
- ...config
444
- };
445
- const patterns = this.storage.getAllPatterns({ includePrivate: true });
446
- const matches = [];
447
- for (const pattern of patterns) {
448
- if (!this.matchEnvironment(pattern, incident)) {
449
- continue;
450
- }
451
- const { score, matchedCriteria } = this.scoreMatch(pattern, incident);
452
- if (score >= minScore) {
453
- let confidence = score;
454
- if (boostConfidence) {
455
- const confidenceFactor = pattern.confidence.score / 100;
456
- confidence = score * (0.5 + 0.5 * confidenceFactor);
457
- }
458
- matches.push({
459
- pattern,
460
- score,
461
- matchedCriteria,
462
- confidence: Math.round(confidence)
463
- });
464
- this.storage.updatePatternConfidence(pattern.id, "matched");
465
- }
466
- }
467
- return matches.sort((a, b) => b.confidence - a.confidence).slice(0, maxResults);
468
- }
469
- /**
470
- * Test a pattern against historical incidents
471
- */
472
- testPattern(pattern, limit = 100) {
473
- const incidents = this.storage.getRecentIncidents({ limit });
474
- const wouldMatch = [];
475
- let totalScore = 0;
476
- for (const incident of incidents) {
477
- if (!this.matchEnvironment(pattern, incident)) {
478
- continue;
479
- }
480
- const { score } = this.scoreMatch(pattern, incident);
481
- if (score >= 30) {
482
- wouldMatch.push(incident);
483
- totalScore += score;
484
- }
485
- }
486
- return {
487
- wouldMatch,
488
- matchCount: wouldMatch.length,
489
- avgScore: wouldMatch.length > 0 ? Math.round(totalScore / wouldMatch.length) : 0
490
- };
491
- }
492
- /**
493
- * Score how well a pattern matches an incident
494
- */
495
- scoreMatch(pattern, incident) {
496
- let score = 0;
497
- const matchedCriteria = {
498
- symbols: [],
499
- errorKeywords: [],
500
- missingSignals: []
501
- };
502
- const symbolScore = this.matchSymbols(
503
- pattern.pattern.symbols,
504
- incident.symbols,
505
- matchedCriteria.symbols
506
- );
507
- score += Math.min(symbolScore, 50);
508
- const errorScore = this.matchErrorText(
509
- pattern,
510
- incident,
511
- matchedCriteria.errorKeywords
512
- );
513
- score += Math.min(errorScore, 25);
514
- const signalScore = this.matchMissingSignals(
515
- pattern,
516
- incident,
517
- matchedCriteria.missingSignals
518
- );
519
- score += Math.min(signalScore, 25);
520
- score = Math.min(score, 100);
521
- return { score, matchedCriteria };
522
- }
523
- /**
524
- * Match symbols between pattern and incident
525
- */
526
- matchSymbols(patternSymbols, incidentSymbols, matched) {
527
- let score = 0;
528
- const symbolTypes = [
529
- "feature",
530
- "component",
531
- "flow",
532
- "gate",
533
- "signal",
534
- "state",
535
- "integration"
536
- ];
537
- for (const type of symbolTypes) {
538
- const patternValue = patternSymbols[type];
539
- const incidentValue = incidentSymbols[type];
540
- if (!patternValue || !incidentValue) {
541
- continue;
542
- }
543
- if (typeof patternValue === "string") {
544
- if (this.matchSingleSymbol(patternValue, incidentValue)) {
545
- score += patternValue.includes("*") ? 5 : 10;
546
- matched.push(type);
547
- }
548
- } else if (Array.isArray(patternValue)) {
549
- for (const pv of patternValue) {
550
- if (this.matchSingleSymbol(pv, incidentValue)) {
551
- score += 7;
552
- matched.push(type);
553
- break;
554
- }
555
- }
556
- }
557
- }
558
- return score;
559
- }
560
- /**
561
- * Match a single symbol value (supports wildcards)
562
- */
563
- matchSingleSymbol(pattern, value) {
564
- if (pattern === "*") {
565
- return true;
566
- }
567
- if (pattern.endsWith("*")) {
568
- const prefix = pattern.slice(0, -1);
569
- return value.startsWith(prefix);
570
- }
571
- if (pattern.startsWith("*")) {
572
- const suffix = pattern.slice(1);
573
- return value.endsWith(suffix);
574
- }
575
- if (pattern.includes("*")) {
576
- const regex = new RegExp(
577
- "^" + pattern.replace(/\*/g, ".*") + "$"
578
- );
579
- return regex.test(value);
580
- }
581
- return pattern === value;
582
- }
583
- /**
584
- * Match error text keywords and regex
585
- */
586
- matchErrorText(pattern, incident, matched) {
587
- let score = 0;
588
- const errorMessage = incident.error.message.toLowerCase();
589
- const errorType = incident.error.type?.toLowerCase();
590
- if (pattern.pattern.errorContains) {
591
- for (const keyword of pattern.pattern.errorContains) {
592
- if (errorMessage.includes(keyword.toLowerCase())) {
593
- score += 5;
594
- matched.push(keyword);
595
- }
596
- }
597
- }
598
- if (pattern.pattern.errorMatches) {
599
- try {
600
- const regex = new RegExp(pattern.pattern.errorMatches, "i");
601
- if (regex.test(incident.error.message)) {
602
- score += 10;
603
- matched.push(`regex:${pattern.pattern.errorMatches}`);
604
- }
605
- } catch {
606
- }
607
- }
608
- if (pattern.pattern.errorType && errorType) {
609
- for (const type of pattern.pattern.errorType) {
610
- if (errorType.includes(type.toLowerCase())) {
611
- score += 5;
612
- matched.push(`type:${type}`);
613
- }
614
- }
615
- }
616
- return score;
617
- }
618
- /**
619
- * Match missing signals from flow position
620
- */
621
- matchMissingSignals(pattern, incident, matched) {
622
- if (!pattern.pattern.missingSignals || !incident.flowPosition?.missing) {
623
- return 0;
624
- }
625
- let score = 0;
626
- for (const expectedSignal of pattern.pattern.missingSignals) {
627
- for (const missingSignal of incident.flowPosition.missing) {
628
- if (this.matchSingleSymbol(expectedSignal, missingSignal)) {
629
- score += 12;
630
- matched.push(missingSignal);
631
- break;
632
- }
633
- }
634
- }
635
- return score;
636
- }
637
- /**
638
- * Check if pattern's environment filter matches incident
639
- */
640
- matchEnvironment(pattern, incident) {
641
- if (!pattern.pattern.environment || pattern.pattern.environment.length === 0) {
642
- return true;
643
- }
644
- return pattern.pattern.environment.includes(incident.environment);
645
- }
646
- };
647
- var __filename = fileURLToPath(import.meta.url);
648
- var __dirname = path.dirname(__filename);
649
- function loadUniversalPatterns() {
650
- const filePath = path.join(__dirname, "universal-patterns.json");
651
- const content = fs.readFileSync(filePath, "utf-8");
652
- return JSON.parse(content);
653
- }
654
- function loadParadigmPatterns() {
655
- const filePath = path.join(__dirname, "paradigm-patterns.json");
656
- const content = fs.readFileSync(filePath, "utf-8");
657
- return JSON.parse(content);
658
- }
659
- function loadAllSeedPatterns() {
660
- const universal = loadUniversalPatterns();
661
- const paradigm = loadParadigmPatterns();
662
- return {
663
- version: "1.0.0",
664
- exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
665
- patterns: [...universal.patterns, ...paradigm.patterns]
666
- };
667
- }
668
- function ensurePrefix(id, prefix) {
669
- return id.startsWith(prefix) ? id : `${prefix}${id}`;
670
- }
671
- var FlowTracker = class {
672
- flowId;
673
- sentinel;
674
- actual = [];
675
- expected = [];
676
- completed = false;
677
- constructor(flowId, sentinel) {
678
- this.flowId = ensurePrefix(flowId, "$");
679
- this.sentinel = sentinel;
680
- }
681
- /** Declare which signals/gates are expected in this flow */
682
- expect(...symbols) {
683
- this.expected.push(...symbols);
684
- return this;
685
- }
686
- /** Record a generic step in the flow */
687
- step(symbol) {
688
- this.actual.push(symbol);
689
- return this;
690
- }
691
- /** Record a gate check result */
692
- gate(id, passed) {
693
- const gateId = ensurePrefix(id, "^");
694
- this.actual.push(gateId);
695
- if (!passed) {
696
- this.fail(new Error(`Gate ${gateId} failed`));
697
- }
698
- return this;
699
- }
700
- /** Record a signal emission */
701
- signal(id, _data) {
702
- this.actual.push(ensurePrefix(id, "!"));
703
- return this;
704
- }
705
- /** Mark the flow as successfully completed */
706
- complete() {
707
- this.completed = true;
708
- }
709
- /** Capture an error with full flow position context */
710
- fail(error) {
711
- if (this.completed) return;
712
- this.completed = true;
713
- const missing = this.expected.filter((s) => !this.actual.includes(s));
714
- const failedAt = this.actual.length > 0 ? this.actual[this.actual.length - 1] : void 0;
715
- const flowPosition = {
716
- flowId: this.flowId,
717
- expected: this.expected,
718
- actual: this.actual,
719
- missing,
720
- failedAt
721
- };
722
- this.sentinel.capture(error, { flow: this.flowId }, flowPosition);
723
- }
724
- };
725
- var Sentinel = class {
726
- storage;
727
- matcher;
728
- config;
729
- ready = false;
730
- readyPromise = null;
731
- seeded = false;
732
- constructor(config) {
733
- this.config = config;
734
- this.storage = new SentinelStorage(config.dbPath);
735
- this.matcher = new PatternMatcher(this.storage);
736
- }
737
- /** Explicitly initialize storage. Optional — auto-called on first capture. */
738
- async init() {
739
- if (this.ready) return;
740
- if (this.readyPromise) return this.readyPromise;
741
- this.readyPromise = this.doInit();
742
- return this.readyPromise;
743
- }
744
- async doInit() {
745
- await this.storage.ensureReady();
746
- if (!this.seeded) {
747
- try {
748
- const { patterns } = loadAllSeedPatterns();
749
- for (const pattern of patterns) {
750
- try {
751
- this.storage.addPattern(pattern);
752
- } catch {
753
- }
754
- }
755
- } catch {
756
- }
757
- this.seeded = true;
758
- }
759
- this.ready = true;
760
- }
761
- ensureReady() {
762
- if (!this.ready) {
763
- if (!this.readyPromise) {
764
- this.readyPromise = this.doInit();
765
- }
766
- }
767
- }
768
- // ── Symbol Context ──────────────────────────────────────────────
769
- /**
770
- * Create a component context for scoped error capture.
771
- *
772
- * @param id - Component symbol (e.g. '#checkout' or 'checkout')
773
- * @returns ComponentContext with capture() and wrap() methods
774
- */
775
- component(id) {
776
- const componentId = ensurePrefix(id, "#");
777
- const self = this;
778
- return {
779
- id: componentId,
780
- capture(error, extra) {
781
- return self.capture(error, { component: componentId, ...extra });
782
- },
783
- wrap(fn) {
784
- const wrapped = ((...args) => {
785
- try {
786
- const result = fn(...args);
787
- if (result && typeof result.catch === "function") {
788
- return result.catch((err) => {
789
- self.capture(err, { component: componentId });
790
- throw err;
791
- });
792
- }
793
- return result;
794
- } catch (err) {
795
- if (err instanceof Error) {
796
- self.capture(err, { component: componentId });
797
- }
798
- throw err;
799
- }
800
- });
801
- return wrapped;
802
- }
803
- };
804
- }
805
- /**
806
- * Record a gate check result.
807
- * If the gate fails, auto-captures an incident.
808
- *
809
- * @param id - Gate symbol (e.g. '^authenticated' or 'authenticated')
810
- * @param passed - Whether the gate passed
811
- */
812
- gate(id, passed) {
813
- if (!passed) {
814
- const gateId = ensurePrefix(id, "^");
815
- this.capture(new Error(`Gate ${gateId} failed`), { gate: gateId });
816
- }
817
- }
818
- /**
819
- * Record a signal emission. Primarily for flow tracking context.
820
- *
821
- * @param id - Signal symbol (e.g. '!payment-authorized' or 'payment-authorized')
822
- */
823
- signal(id, _data) {
824
- void ensurePrefix(id, "!");
825
- }
826
- // ── Flow Tracking ───────────────────────────────────────────────
827
- /**
828
- * Create a flow tracker for monitoring multi-step operations.
829
- *
830
- * @param id - Flow symbol (e.g. '$checkout-flow' or 'checkout-flow')
831
- * @returns FlowTracker instance
832
- */
833
- flow(id) {
834
- return new FlowTracker(id, this);
835
- }
836
- // ── Error Capture ───────────────────────────────────────────────
837
- /**
838
- * Capture an error with symbolic context.
839
- *
840
- * @param error - The error to capture
841
- * @param context - Symbolic context (component, gate, flow, signal)
842
- * @param flowPosition - Optional flow position data
843
- * @returns Incident ID (e.g. 'INC-001')
844
- */
845
- capture(error, context, flowPosition) {
846
- this.ensureReady();
847
- const input = {
848
- error: {
849
- message: error.message,
850
- stack: error.stack,
851
- type: error.constructor.name !== "Error" ? error.constructor.name : void 0
852
- },
853
- symbols: context || {},
854
- environment: this.config.environment || "development",
855
- service: this.config.service,
856
- version: this.config.version,
857
- flowPosition
858
- };
859
- const incidentId = this.storage.recordIncident(input);
860
- const incident = this.storage.getIncident(incidentId);
861
- if (incident && this.config.onCapture) {
862
- this.config.onCapture(incident);
863
- }
864
- return incidentId;
865
- }
866
- /**
867
- * Get pattern matches for a captured incident.
868
- *
869
- * @param incidentId - The incident ID to match
870
- * @returns Array of pattern matches sorted by confidence
871
- */
872
- match(incidentId) {
873
- const incident = this.storage.getIncident(incidentId);
874
- if (!incident) return [];
875
- return this.matcher.match(incident);
876
- }
877
- // ── Framework Integration ───────────────────────────────────────
878
- /**
879
- * Create Express error-handling middleware.
880
- *
881
- * Usage:
882
- * app.use(sentinel.express());
883
- */
884
- express() {
885
- const self = this;
886
- return (err, req, res, next) => {
887
- const context = {};
888
- const routeParts = (req.path || req.url || "").split("/").filter(Boolean);
889
- if (routeParts.length >= 2) {
890
- context.component = `#${routeParts[1]}`;
891
- }
892
- const incidentId = self.capture(err, context);
893
- if (res.setHeader) {
894
- res.setHeader("X-Sentinel-Incident", incidentId);
895
- }
896
- next(err);
897
- };
898
- }
899
- // ── Lifecycle ───────────────────────────────────────────────────
900
- /** Close the database connection. Call when shutting down. */
901
- close() {
902
- this.storage.close();
903
- this.ready = false;
904
- this.readyPromise = null;
905
- }
906
- /** Get the underlying storage instance (for advanced usage). */
907
- getStorage() {
908
- return this.storage;
909
- }
910
- /** Get the underlying pattern matcher (for advanced usage). */
911
- getMatcher() {
912
- return this.matcher;
913
- }
914
- };
915
- var DIR_PATTERNS = [
916
- { dirs: ["services", "src/services"], prefix: "#", type: "components" },
917
- { dirs: ["routes", "src/routes", "api", "src/api"], prefix: "#", type: "components" },
918
- { dirs: ["handlers", "src/handlers"], prefix: "#", type: "components" },
919
- { dirs: ["controllers", "src/controllers"], prefix: "#", type: "components" },
920
- { dirs: ["components", "src/components"], prefix: "#", type: "components" },
921
- { dirs: ["lib", "src/lib"], prefix: "#", type: "components" },
922
- { dirs: ["middleware", "src/middleware"], prefix: "^", type: "gates" },
923
- { dirs: ["guards", "src/guards"], prefix: "^", type: "gates" },
924
- { dirs: ["auth", "src/auth"], prefix: "^", type: "gates" },
925
- { dirs: ["events", "src/events"], prefix: "!", type: "signals" },
926
- { dirs: ["listeners", "src/listeners"], prefix: "!", type: "signals" },
927
- { dirs: ["flows", "src/flows"], prefix: "$", type: "flows" },
928
- { dirs: ["workflows", "src/workflows"], prefix: "$", type: "flows" },
929
- { dirs: ["pipelines", "src/pipelines"], prefix: "$", type: "flows" }
930
- ];
931
- var CODE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".js", ".tsx", ".jsx", ".mjs", ".mts"]);
932
- function detectSymbols(projectDir) {
933
- const result = {
934
- components: [],
935
- gates: [],
936
- flows: [],
937
- signals: [],
938
- routes: {}
939
- };
940
- const purposeSymbols = readPurposeFiles(projectDir);
941
- if (purposeSymbols) {
942
- result.components.push(...purposeSymbols.components);
943
- result.gates.push(...purposeSymbols.gates);
944
- result.flows.push(...purposeSymbols.flows);
945
- result.signals.push(...purposeSymbols.signals);
946
- }
947
- for (const pattern of DIR_PATTERNS) {
948
- for (const dir of pattern.dirs) {
949
- const fullPath = path2.join(projectDir, dir);
950
- if (!fs2.existsSync(fullPath)) continue;
951
- const files = safeReaddir(fullPath);
952
- for (const file of files) {
953
- const ext = path2.extname(file);
954
- if (!CODE_EXTENSIONS.has(ext)) continue;
955
- const name = path2.basename(file, ext);
956
- if (name === "index" || name.endsWith(".test") || name.endsWith(".spec")) continue;
957
- const symbol = `${pattern.prefix}${toKebabCase(name)}`;
958
- if (!result[pattern.type].includes(symbol)) {
959
- result[pattern.type].push(symbol);
960
- }
961
- }
962
- }
963
- }
964
- scanRoutes(projectDir, result);
965
- return result;
966
- }
967
- function generateConfig(projectDir) {
968
- const detected = detectSymbols(projectDir);
969
- return {
970
- version: "1.0",
971
- project: path2.basename(projectDir),
972
- symbols: {
973
- components: detected.components.length > 0 ? detected.components : void 0,
974
- gates: detected.gates.length > 0 ? detected.gates : void 0,
975
- flows: detected.flows.length > 0 ? detected.flows : void 0,
976
- signals: detected.signals.length > 0 ? detected.signals : void 0
977
- },
978
- routes: Object.keys(detected.routes).length > 0 ? detected.routes : void 0
979
- };
980
- }
981
- function readPurposeFiles(projectDir) {
982
- const paradigmDir = path2.join(projectDir, ".paradigm");
983
- if (!fs2.existsSync(paradigmDir)) return null;
984
- const result = {
985
- components: [],
986
- gates: [],
987
- flows: [],
988
- signals: [],
989
- routes: {}
990
- };
991
- const purposeFiles = findFiles(projectDir, ".purpose");
992
- for (const file of purposeFiles) {
993
- try {
994
- const content = fs2.readFileSync(file, "utf-8");
995
- extractPurposeSymbols(content, result);
996
- } catch {
997
- }
998
- }
999
- const hasAny = result.components.length > 0 || result.gates.length > 0 || result.flows.length > 0 || result.signals.length > 0;
1000
- return hasAny ? result : null;
1001
- }
1002
- function extractPurposeSymbols(content, result) {
1003
- const lines = content.split("\n");
1004
- let currentSection = "";
1005
- for (const line of lines) {
1006
- const trimmed = line.trim();
1007
- if (trimmed === "components:" || trimmed === "features:") {
1008
- currentSection = "components";
1009
- continue;
1010
- }
1011
- if (trimmed === "gates:") {
1012
- currentSection = "gates";
1013
- continue;
1014
- }
1015
- if (trimmed === "flows:") {
1016
- currentSection = "flows";
1017
- continue;
1018
- }
1019
- if (trimmed === "signals:") {
1020
- currentSection = "signals";
1021
- continue;
1022
- }
1023
- if (currentSection && /^\s{2}\S/.test(line)) {
1024
- const idMatch = trimmed.match(/^([a-zA-Z][\w-]*):$/);
1025
- if (idMatch) {
1026
- const prefixes = {
1027
- components: "#",
1028
- gates: "^",
1029
- flows: "$",
1030
- signals: "!"
1031
- };
1032
- const prefix = prefixes[currentSection] || "#";
1033
- const symbol = `${prefix}${idMatch[1]}`;
1034
- if (!result[currentSection]?.includes(symbol)) {
1035
- result[currentSection]?.push(symbol);
1036
- }
1037
- }
1038
- }
1039
- if (trimmed && !line.startsWith(" ") && !trimmed.endsWith(":")) {
1040
- currentSection = "";
1041
- }
1042
- }
1043
- }
1044
- function scanRoutes(projectDir, result) {
1045
- const routeDirs = ["routes", "src/routes", "api", "src/api"];
1046
- for (const dir of routeDirs) {
1047
- const fullPath = path2.join(projectDir, dir);
1048
- if (!fs2.existsSync(fullPath)) continue;
1049
- const files = safeReaddir(fullPath);
1050
- for (const file of files) {
1051
- const ext = path2.extname(file);
1052
- if (!CODE_EXTENSIONS.has(ext)) continue;
1053
- const name = path2.basename(file, ext);
1054
- if (name === "index") continue;
1055
- const routePrefix = `/api/${toKebabCase(name)}`;
1056
- const component = `#${toKebabCase(name)}`;
1057
- result.routes[routePrefix] = component;
1058
- }
1059
- }
1060
- }
1061
- function toKebabCase(str) {
1062
- return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[_\s]+/g, "-").replace(/\..*$/, "").toLowerCase();
1063
- }
1064
- function safeReaddir(dir) {
1065
- try {
1066
- return fs2.readdirSync(dir).filter((f) => {
1067
- const fullPath = path2.join(dir, f);
1068
- try {
1069
- return fs2.statSync(fullPath).isFile();
1070
- } catch {
1071
- return false;
1072
- }
1073
- });
1074
- } catch {
1075
- return [];
1076
- }
1077
- }
1078
- function findFiles(dir, filename, maxDepth = 4, depth = 0) {
1079
- if (depth > maxDepth) return [];
1080
- const results = [];
1081
- const skipDirs = /* @__PURE__ */ new Set(["node_modules", "dist", ".git", "coverage", ".next", ".nuxt"]);
1082
- try {
1083
- const entries = fs2.readdirSync(dir, { withFileTypes: true });
1084
- for (const entry of entries) {
1085
- if (entry.isFile() && entry.name === filename) {
1086
- results.push(path2.join(dir, entry.name));
1087
- } else if (entry.isDirectory() && !skipDirs.has(entry.name)) {
1088
- results.push(...findFiles(path2.join(dir, entry.name), filename, maxDepth, depth + 1));
1089
- }
1090
- }
1091
- } catch {
1092
- }
1093
- return results;
1094
- }
1095
- var DEFAULT_SIMILARITY_THRESHOLD = 0.6;
1096
- var DECAY_HALF_LIFE_DAYS = 14;
1097
- var IncidentGrouper = class {
1098
- constructor(storage, config) {
1099
- this.storage = storage;
1100
- this.similarityThreshold = config?.similarityThreshold ?? DEFAULT_SIMILARITY_THRESHOLD;
1101
- this.decayHalfLifeDays = config?.decayHalfLifeDays ?? DECAY_HALF_LIFE_DAYS;
1102
- this.useStackFingerprint = config?.useStackFingerprint ?? true;
1103
- }
1104
- similarityThreshold;
1105
- decayHalfLifeDays;
1106
- useStackFingerprint;
1107
- /**
1108
- * Try to find or create a group for an incident
1109
- * Returns the group ID if grouped, null if no suitable group
1110
- */
1111
- group(incident) {
1112
- const groups = this.storage.getGroups({ limit: 100 });
1113
- for (const group of groups) {
1114
- if (this.shouldJoinGroup(incident, group)) {
1115
- this.storage.addToGroup(group.id, incident.id);
1116
- return group.id;
1117
- }
1118
- }
1119
- const similar = this.findSimilar(incident, 10);
1120
- if (similar.length >= 1) {
1121
- const commonSymbols = this.extractCommonSymbols([incident, ...similar]);
1122
- const commonErrorPatterns = this.extractCommonErrorPatterns([
1123
- incident,
1124
- ...similar
1125
- ]);
1126
- const groupId = this.storage.createGroup({
1127
- incidents: [incident.id, ...similar.map((i) => i.id)],
1128
- commonSymbols,
1129
- commonErrorPatterns,
1130
- firstSeen: this.getEarliestTimestamp([incident, ...similar]),
1131
- lastSeen: incident.timestamp,
1132
- environments: this.getUniqueEnvironments([incident, ...similar])
1133
- });
1134
- return groupId;
1135
- }
1136
- return null;
1137
- }
1138
- /**
1139
- * Find incidents similar to the given one
1140
- */
1141
- findSimilar(incident, limit = 10) {
1142
- const candidates = this.storage.getRecentIncidents({
1143
- limit: 500,
1144
- status: "all"
1145
- });
1146
- const similar = [];
1147
- for (const candidate of candidates) {
1148
- if (candidate.id === incident.id) {
1149
- continue;
1150
- }
1151
- const score = this.calculateSimilarity(incident, candidate);
1152
- if (score >= this.similarityThreshold) {
1153
- similar.push({ incident: candidate, score });
1154
- }
1155
- }
1156
- return similar.sort((a, b) => b.score - a.score).slice(0, limit).map((s) => s.incident);
1157
- }
1158
- /**
1159
- * Analyze ungrouped incidents and create groups automatically
1160
- */
1161
- analyzeAndGroup(options = {}) {
1162
- const minSize = options.minSize || 3;
1163
- const ungrouped = this.storage.getRecentIncidents({
1164
- limit: 1e3
1165
- }).filter((i) => !i.groupId);
1166
- const newGroups = [];
1167
- const processed = /* @__PURE__ */ new Set();
1168
- for (const incident of ungrouped) {
1169
- if (processed.has(incident.id)) {
1170
- continue;
1171
- }
1172
- const similar = ungrouped.filter(
1173
- (other) => other.id !== incident.id && !processed.has(other.id) && this.calculateSimilarity(incident, other) >= this.similarityThreshold
1174
- );
1175
- if (similar.length + 1 >= minSize) {
1176
- const members = [incident, ...similar];
1177
- const commonSymbols = this.extractCommonSymbols(members);
1178
- const commonErrorPatterns = this.extractCommonErrorPatterns(members);
1179
- const groupId = this.storage.createGroup({
1180
- incidents: members.map((m) => m.id),
1181
- commonSymbols,
1182
- commonErrorPatterns,
1183
- firstSeen: this.getEarliestTimestamp(members),
1184
- lastSeen: this.getLatestTimestamp(members),
1185
- environments: this.getUniqueEnvironments(members)
1186
- });
1187
- for (const m of members) {
1188
- processed.add(m.id);
1189
- }
1190
- const group = this.storage.getGroup(groupId);
1191
- if (group) {
1192
- newGroups.push(group);
1193
- }
1194
- }
1195
- }
1196
- return newGroups;
1197
- }
1198
- /**
1199
- * Calculate similarity between two incidents (0-1)
1200
- * Applies time-decay so older incidents contribute less, and optionally
1201
- * uses stack trace fingerprinting for more accurate grouping.
1202
- */
1203
- calculateSimilarity(a, b) {
1204
- let score = 0;
1205
- let maxScore = 0;
1206
- const hasStacks = this.useStackFingerprint && a.error.stack && b.error.stack;
1207
- const symbolWeight = hasStacks ? 0.45 : 0.6;
1208
- const errorWeight = hasStacks ? 0.25 : 0.3;
1209
- const envWeight = 0.1;
1210
- const stackWeight = hasStacks ? 0.2 : 0;
1211
- const symbolTypes = [
1212
- "feature",
1213
- "component",
1214
- "flow",
1215
- "gate",
1216
- "signal",
1217
- "state",
1218
- "integration"
1219
- ];
1220
- for (const type of symbolTypes) {
1221
- const aValue = a.symbols[type];
1222
- const bValue = b.symbols[type];
1223
- if (aValue || bValue) {
1224
- maxScore += symbolWeight / symbolTypes.length;
1225
- if (aValue === bValue) {
1226
- score += symbolWeight / symbolTypes.length;
1227
- }
1228
- }
1229
- }
1230
- const errorSimilarity = this.stringSimilarity(
1231
- a.error.message,
1232
- b.error.message
1233
- );
1234
- score += errorWeight * errorSimilarity;
1235
- maxScore += errorWeight;
1236
- if (a.environment === b.environment) {
1237
- score += envWeight;
1238
- }
1239
- maxScore += envWeight;
1240
- if (hasStacks) {
1241
- const aFingerprint = this.fingerprintStack(a.error.stack);
1242
- const bFingerprint = this.fingerprintStack(b.error.stack);
1243
- const stackSimilarity = this.compareFingerprints(aFingerprint, bFingerprint);
1244
- score += stackWeight * stackSimilarity;
1245
- maxScore += stackWeight;
1246
- }
1247
- const rawScore = maxScore > 0 ? score / maxScore : 0;
1248
- const timeDelta = Math.abs(
1249
- new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
1250
- );
1251
- const daysDelta = timeDelta / (1e3 * 60 * 60 * 24);
1252
- const decayFactor = Math.pow(0.5, daysDelta / this.decayHalfLifeDays);
1253
- return rawScore * decayFactor;
1254
- }
1255
- /**
1256
- * Extract a fingerprint from a stack trace by normalizing frames.
1257
- * Strips line numbers, column numbers, and absolute paths to capture
1258
- * the structural signature of the call stack.
1259
- */
1260
- fingerprintStack(stack) {
1261
- return stack.split("\n").filter((line) => line.trim().startsWith("at ")).slice(0, 10).map((frame) => {
1262
- return frame.trim().replace(/:\d+:\d+\)?$/, "").replace(/\(.*[/\\]/, "(").replace(/^\s*at\s+/, "");
1263
- });
1264
- }
1265
- /**
1266
- * Compare two stack fingerprints (0-1 similarity)
1267
- */
1268
- compareFingerprints(a, b) {
1269
- if (a.length === 0 && b.length === 0) return 1;
1270
- if (a.length === 0 || b.length === 0) return 0;
1271
- let matches = 0;
1272
- const maxLen = Math.max(a.length, b.length);
1273
- for (let i = 0; i < Math.min(a.length, b.length); i++) {
1274
- if (a[i] === b[i]) {
1275
- matches++;
1276
- }
1277
- }
1278
- return matches / maxLen;
1279
- }
1280
- /**
1281
- * Calculate string similarity using Levenshtein distance
1282
- */
1283
- stringSimilarity(a, b) {
1284
- const maxLen = Math.max(a.length, b.length);
1285
- if (maxLen === 0) return 1;
1286
- const distance = this.levenshteinDistance(
1287
- a.toLowerCase(),
1288
- b.toLowerCase()
1289
- );
1290
- return 1 - distance / maxLen;
1291
- }
1292
- /**
1293
- * Levenshtein distance for string comparison
1294
- */
1295
- levenshteinDistance(a, b) {
1296
- if (a.length === 0) return b.length;
1297
- if (b.length === 0) return a.length;
1298
- const matrix = [];
1299
- for (let i = 0; i <= b.length; i++) {
1300
- matrix[i] = [i];
1301
- }
1302
- for (let j = 0; j <= a.length; j++) {
1303
- matrix[0][j] = j;
1304
- }
1305
- for (let i = 1; i <= b.length; i++) {
1306
- for (let j = 1; j <= a.length; j++) {
1307
- const cost = a[j - 1] === b[i - 1] ? 0 : 1;
1308
- matrix[i][j] = Math.min(
1309
- matrix[i - 1][j] + 1,
1310
- matrix[i][j - 1] + 1,
1311
- matrix[i - 1][j - 1] + cost
1312
- );
1313
- }
1314
- }
1315
- return matrix[b.length][a.length];
1316
- }
1317
- /**
1318
- * Check if incident should join existing group
1319
- */
1320
- shouldJoinGroup(incident, group) {
1321
- let matchCount = 0;
1322
- let totalCommon = 0;
1323
- for (const [key, value] of Object.entries(group.commonSymbols)) {
1324
- if (value) {
1325
- totalCommon++;
1326
- const incidentValue = incident.symbols[key];
1327
- if (incidentValue === value) {
1328
- matchCount++;
1329
- }
1330
- }
1331
- }
1332
- if (totalCommon === 0) {
1333
- return false;
1334
- }
1335
- const symbolMatch = matchCount / totalCommon;
1336
- const errorLower = incident.error.message.toLowerCase();
1337
- const errorMatch = group.commonErrorPatterns.some(
1338
- (pattern) => errorLower.includes(pattern.toLowerCase())
1339
- );
1340
- return symbolMatch >= 0.5 || errorMatch;
1341
- }
1342
- /**
1343
- * Extract symbols common to all incidents
1344
- */
1345
- extractCommonSymbols(incidents) {
1346
- if (incidents.length === 0) return {};
1347
- const first = incidents[0].symbols;
1348
- const common = {};
1349
- for (const [key, value] of Object.entries(first)) {
1350
- if (!value) continue;
1351
- const allMatch = incidents.every(
1352
- (i) => i.symbols[key] === value
1353
- );
1354
- if (allMatch) {
1355
- common[key] = value;
1356
- }
1357
- }
1358
- return common;
1359
- }
1360
- /**
1361
- * Extract common error patterns from incidents
1362
- */
1363
- extractCommonErrorPatterns(incidents) {
1364
- if (incidents.length === 0) return [];
1365
- const wordCounts = /* @__PURE__ */ new Map();
1366
- const stopWords = /* @__PURE__ */ new Set([
1367
- "the",
1368
- "a",
1369
- "an",
1370
- "is",
1371
- "are",
1372
- "was",
1373
- "were",
1374
- "in",
1375
- "on",
1376
- "at",
1377
- "to",
1378
- "for",
1379
- "of",
1380
- "with",
1381
- "error",
1382
- "failed",
1383
- "cannot"
1384
- ]);
1385
- for (const incident of incidents) {
1386
- const words = incident.error.message.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !stopWords.has(w));
1387
- const uniqueWords = new Set(words);
1388
- for (const word of uniqueWords) {
1389
- wordCounts.set(word, (wordCounts.get(word) || 0) + 1);
1390
- }
1391
- }
1392
- const threshold = Math.ceil(incidents.length * 0.6);
1393
- const commonPatterns = Array.from(wordCounts.entries()).filter(([, count]) => count >= threshold).map(([word]) => word).slice(0, 5);
1394
- return commonPatterns;
1395
- }
1396
- getEarliestTimestamp(incidents) {
1397
- return incidents.reduce(
1398
- (earliest, i) => i.timestamp < earliest ? i.timestamp : earliest,
1399
- incidents[0].timestamp
1400
- );
1401
- }
1402
- getLatestTimestamp(incidents) {
1403
- return incidents.reduce(
1404
- (latest, i) => i.timestamp > latest ? i.timestamp : latest,
1405
- incidents[0].timestamp
1406
- );
1407
- }
1408
- getUniqueEnvironments(incidents) {
1409
- return [...new Set(incidents.map((i) => i.environment))];
1410
- }
1411
- };
1412
- var TimelineBuilder = class {
1413
- /**
1414
- * Build a timeline from an incident with flow position
1415
- */
1416
- build(incident) {
1417
- if (!incident.flowPosition) {
1418
- return null;
1419
- }
1420
- const events = [];
1421
- const baseTime = new Date(incident.timestamp).getTime();
1422
- events.push({
1423
- timestamp: new Date(baseTime - 5e3).toISOString(),
1424
- symbol: incident.flowPosition.flowId,
1425
- type: "flow-started"
1426
- });
1427
- let eventOffset = 1e3;
1428
- for (const signal of incident.flowPosition.actual) {
1429
- const type = this.inferEventType(signal);
1430
- events.push({
1431
- timestamp: new Date(baseTime - 4e3 + eventOffset).toISOString(),
1432
- symbol: signal,
1433
- type
1434
- });
1435
- eventOffset += Math.random() * 1e3 + 500;
1436
- }
1437
- const failedSymbol = incident.flowPosition.failedAt || incident.flowPosition.missing[0] || incident.symbols.gate || incident.symbols.signal || "unknown";
1438
- events.push({
1439
- timestamp: incident.timestamp,
1440
- symbol: failedSymbol,
1441
- type: "error",
1442
- data: {
1443
- message: incident.error.message,
1444
- missing: incident.flowPosition.missing
1445
- }
1446
- });
1447
- return {
1448
- incidentId: incident.id,
1449
- flowId: incident.flowPosition.flowId,
1450
- events,
1451
- failure: {
1452
- at: incident.timestamp,
1453
- symbol: failedSymbol,
1454
- reason: incident.error.message
1455
- }
1456
- };
1457
- }
1458
- /**
1459
- * Render timeline as ASCII art
1460
- */
1461
- renderAscii(timeline) {
1462
- const lines = [];
1463
- lines.push(`${timeline.flowId} Timeline`);
1464
- lines.push("\u2550".repeat(40));
1465
- lines.push("");
1466
- for (const event of timeline.events) {
1467
- const time = this.formatTime(event.timestamp);
1468
- const icon = this.getEventIcon(event.type);
1469
- const status = this.getEventStatus(event.type);
1470
- let line = `${time} ${icon} ${event.symbol}`;
1471
- if (status) {
1472
- line += ` (${status})`;
1473
- }
1474
- lines.push(line);
1475
- if (event.type === "error" && event.data) {
1476
- lines.push(` \u2514\u2500 ${event.data.message}`);
1477
- if (event.data.missing && Array.isArray(event.data.missing) && event.data.missing.length > 0) {
1478
- lines.push(
1479
- ` \u2514\u2500 Expected: ${event.data.missing.join(", ")}`
1480
- );
1481
- }
1482
- }
1483
- }
1484
- const missing = timeline.events.find((e) => e.type === "error")?.data?.missing;
1485
- if (missing && missing.length > 0) {
1486
- lines.push("");
1487
- lines.push(`Missing signals: ${missing.join(", ")}`);
1488
- }
1489
- return lines.join("\n");
1490
- }
1491
- /**
1492
- * Render timeline as structured data (for MCP/JSON output)
1493
- */
1494
- renderStructured(timeline) {
1495
- return {
1496
- incidentId: timeline.incidentId,
1497
- flow: {
1498
- id: timeline.flowId,
1499
- eventCount: timeline.events.length
1500
- },
1501
- events: timeline.events.map((event) => ({
1502
- time: this.formatTime(event.timestamp),
1503
- symbol: event.symbol,
1504
- type: event.type,
1505
- status: this.getEventStatus(event.type),
1506
- data: event.data
1507
- })),
1508
- failure: {
1509
- at: this.formatTime(timeline.failure.at),
1510
- symbol: timeline.failure.symbol,
1511
- reason: timeline.failure.reason
1512
- }
1513
- };
1514
- }
1515
- /**
1516
- * Infer event type from symbol prefix
1517
- */
1518
- inferEventType(symbol) {
1519
- if (symbol.startsWith("^")) {
1520
- return "gate-passed";
1521
- }
1522
- if (symbol.startsWith("!")) {
1523
- return "signal-emitted";
1524
- }
1525
- if (symbol.startsWith("%")) {
1526
- return "state-changed";
1527
- }
1528
- return "signal-emitted";
1529
- }
1530
- /**
1531
- * Get icon for event type
1532
- */
1533
- getEventIcon(type) {
1534
- switch (type) {
1535
- case "flow-started":
1536
- return "\u25B6";
1537
- case "flow-ended":
1538
- return "\u25A0";
1539
- case "gate-passed":
1540
- return "\u2713";
1541
- case "gate-failed":
1542
- return "\u2717";
1543
- case "signal-emitted":
1544
- return "\u26A1";
1545
- case "state-changed":
1546
- return "\u25C6";
1547
- case "error":
1548
- return "\u2717";
1549
- default:
1550
- return "\u2022";
1551
- }
1552
- }
1553
- /**
1554
- * Get status text for event type
1555
- */
1556
- getEventStatus(type) {
1557
- switch (type) {
1558
- case "gate-passed":
1559
- return "PASSED";
1560
- case "gate-failed":
1561
- return "FAILED";
1562
- case "signal-emitted":
1563
- return "EMITTED";
1564
- case "state-changed":
1565
- return "CHANGED";
1566
- case "error":
1567
- return "ERROR";
1568
- default:
1569
- return "";
1570
- }
1571
- }
1572
- /**
1573
- * Format timestamp for display
1574
- */
1575
- formatTime(timestamp) {
1576
- const date = new Date(timestamp);
1577
- const hours = String(date.getHours()).padStart(2, "0");
1578
- const minutes = String(date.getMinutes()).padStart(2, "0");
1579
- const seconds = String(date.getSeconds()).padStart(2, "0");
1580
- const millis = String(date.getMilliseconds()).padStart(3, "0");
1581
- return `${hours}:${minutes}:${seconds}.${millis}`;
1582
- }
1583
- };
1584
- var StatsCalculator = class {
1585
- constructor(storage) {
1586
- this.storage = storage;
1587
- }
1588
- /**
1589
- * Get comprehensive statistics for a time period
1590
- */
1591
- getStats(periodDays = 7) {
1592
- const end = (/* @__PURE__ */ new Date()).toISOString();
1593
- const start = new Date(
1594
- Date.now() - periodDays * 24 * 60 * 60 * 1e3
1595
- ).toISOString();
1596
- return this.storage.getStats({ start, end });
1597
- }
1598
- /**
1599
- * Get health metrics for a specific symbol
1600
- */
1601
- getSymbolHealth(symbol) {
1602
- return this.storage.getSymbolHealth(symbol);
1603
- }
1604
- /**
1605
- * Get trending issues (symbols with increasing incident rates)
1606
- */
1607
- getTrendingIssues(days = 7) {
1608
- const now = Date.now();
1609
- const halfPeriod = days * 24 * 60 * 60 * 1e3 / 2;
1610
- const firstHalfStart = new Date(now - days * 24 * 60 * 60 * 1e3).toISOString();
1611
- const midpoint = new Date(now - halfPeriod).toISOString();
1612
- const secondHalfEnd = new Date(now).toISOString();
1613
- const firstHalfIncidents = this.storage.getRecentIncidents({
1614
- dateFrom: firstHalfStart,
1615
- dateTo: midpoint,
1616
- limit: 1e3
1617
- });
1618
- const secondHalfIncidents = this.storage.getRecentIncidents({
1619
- dateFrom: midpoint,
1620
- dateTo: secondHalfEnd,
1621
- limit: 1e3
1622
- });
1623
- const firstHalfCounts = this.countSymbols(firstHalfIncidents);
1624
- const secondHalfCounts = this.countSymbols(secondHalfIncidents);
1625
- const trends = [];
1626
- const allSymbols = /* @__PURE__ */ new Set([
1627
- ...firstHalfCounts.keys(),
1628
- ...secondHalfCounts.keys()
1629
- ]);
1630
- for (const symbol of allSymbols) {
1631
- const first = firstHalfCounts.get(symbol) || 0;
1632
- const second = secondHalfCounts.get(symbol) || 0;
1633
- if (first === 0 && second > 0) {
1634
- trends.push({ symbol, trend: second * 100 });
1635
- } else if (first > 0) {
1636
- const change = (second - first) / first * 100;
1637
- trends.push({ symbol, trend: change });
1638
- }
1639
- }
1640
- return trends.filter((t) => t.trend > 0).sort((a, b) => b.trend - a.trend).slice(0, 10);
1641
- }
1642
- /**
1643
- * Get resolution metrics
1644
- */
1645
- getResolutionMetrics() {
1646
- const stats = this.getStats(30);
1647
- return {
1648
- avgTimeToResolve: stats.resolution.avgTimeToResolve,
1649
- resolvedWithPattern: stats.resolution.resolvedWithPattern,
1650
- resolvedManually: stats.resolution.resolvedManually,
1651
- totalResolved: stats.incidents.resolved,
1652
- resolutionRate: stats.resolution.resolutionRate
1653
- };
1654
- }
1655
- /**
1656
- * Get pattern effectiveness metrics
1657
- */
1658
- getPatternEffectiveness() {
1659
- const patterns = this.storage.getAllPatterns({ includePrivate: true });
1660
- return patterns.filter((p) => p.confidence.timesMatched > 0).map((p) => ({
1661
- patternId: p.id,
1662
- name: p.name,
1663
- matches: p.confidence.timesMatched,
1664
- resolutions: p.confidence.timesResolved,
1665
- recurrences: p.confidence.timesRecurred,
1666
- effectiveness: p.confidence.timesMatched > 0 ? Math.round(
1667
- (p.confidence.timesResolved - p.confidence.timesRecurred) / p.confidence.timesMatched * 100
1668
- ) : 0
1669
- })).sort((a, b) => b.effectiveness - a.effectiveness);
1670
- }
1671
- /**
1672
- * Get incident rate by hour of day
1673
- */
1674
- getIncidentsByHour(days = 7) {
1675
- const start = new Date(
1676
- Date.now() - days * 24 * 60 * 60 * 1e3
1677
- ).toISOString();
1678
- const incidents = this.storage.getRecentIncidents({
1679
- dateFrom: start,
1680
- limit: 1e4
1681
- });
1682
- const hourCounts = /* @__PURE__ */ new Map();
1683
- for (let i = 0; i < 24; i++) {
1684
- hourCounts.set(i, 0);
1685
- }
1686
- for (const incident of incidents) {
1687
- const hour = new Date(incident.timestamp).getHours();
1688
- hourCounts.set(hour, (hourCounts.get(hour) || 0) + 1);
1689
- }
1690
- return Array.from(hourCounts.entries()).map(([hour, count]) => ({
1691
- hour,
1692
- count
1693
- }));
1694
- }
1695
- /**
1696
- * Get incident rate by environment
1697
- */
1698
- getIncidentsByEnvironment() {
1699
- const stats = this.getStats(30);
1700
- const total = stats.incidents.total;
1701
- return Object.entries(stats.incidents.byEnvironment).map(([environment, count]) => ({
1702
- environment,
1703
- count,
1704
- percentage: total > 0 ? Math.round(count / total * 100) : 0
1705
- })).sort((a, b) => b.count - a.count);
1706
- }
1707
- /**
1708
- * Get symbol correlation matrix (which symbols fail together)
1709
- */
1710
- getSymbolCorrelation() {
1711
- const incidents = this.storage.getRecentIncidents({ limit: 1e3 });
1712
- const correlations = /* @__PURE__ */ new Map();
1713
- const symbolCounts = /* @__PURE__ */ new Map();
1714
- for (const incident of incidents) {
1715
- const symbols = this.getSymbolsFromIncident(incident);
1716
- for (const symbol of symbols) {
1717
- symbolCounts.set(symbol, (symbolCounts.get(symbol) || 0) + 1);
1718
- }
1719
- for (let i = 0; i < symbols.length; i++) {
1720
- for (let j = i + 1; j < symbols.length; j++) {
1721
- const key = [symbols[i], symbols[j]].sort().join("|");
1722
- correlations.set(key, (correlations.get(key) || 0) + 1);
1723
- }
1724
- }
1725
- }
1726
- const results = [];
1727
- for (const [key, count] of correlations) {
1728
- const [symbol1, symbol2] = key.split("|");
1729
- const count1 = symbolCounts.get(symbol1) || 1;
1730
- const count2 = symbolCounts.get(symbol2) || 1;
1731
- const correlation = count / Math.max(count1, count2);
1732
- if (correlation > 0.3) {
1733
- results.push({
1734
- symbol1,
1735
- symbol2,
1736
- correlation: Math.round(correlation * 100) / 100
1737
- });
1738
- }
1739
- }
1740
- return results.sort((a, b) => b.correlation - a.correlation).slice(0, 20);
1741
- }
1742
- /**
1743
- * Generate a summary dashboard string
1744
- */
1745
- generateDashboard(periodDays = 7) {
1746
- const stats = this.getStats(periodDays);
1747
- const lines = [];
1748
- lines.push("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
1749
- lines.push("\u2551 PARADIGM SENTINEL DASHBOARD \u2551");
1750
- lines.push("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563");
1751
- const todayCount = stats.incidents.byDay[stats.incidents.byDay.length - 1]?.count || 0;
1752
- lines.push(
1753
- `\u2551 Open: ${String(stats.incidents.open).padEnd(4)} \u2502 Investigating: ${String(stats.incidents.total - stats.incidents.open - stats.incidents.resolved).padEnd(3)} \u2502 Resolved: ${String(stats.incidents.resolved).padEnd(4)} \u2502 Today: +${todayCount} \u2551`
1754
- );
1755
- lines.push("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
1756
- lines.push("");
1757
- lines.push("Incidents by Day (last 7 days):");
1758
- lines.push("\u2500".repeat(50));
1759
- const maxDayCount = Math.max(...stats.incidents.byDay.map((d) => d.count), 1);
1760
- for (const day of stats.incidents.byDay.slice(-7)) {
1761
- const barLength = Math.round(day.count / maxDayCount * 30);
1762
- const bar = "\u2588".repeat(barLength);
1763
- lines.push(`${day.date.substring(5)} ${bar} ${day.count}`);
1764
- }
1765
- lines.push("");
1766
- lines.push("Most Affected Symbols:");
1767
- lines.push("\u2500".repeat(50));
1768
- for (const { symbol, count } of stats.symbols.mostIncidents.slice(0, 5)) {
1769
- lines.push(` ${symbol.padEnd(25)} ${count} incidents`);
1770
- }
1771
- lines.push("");
1772
- lines.push("Top Patterns:");
1773
- lines.push("\u2500".repeat(50));
1774
- for (const { patternId, resolvedCount } of stats.patterns.mostEffective.slice(0, 5)) {
1775
- lines.push(` ${patternId.padEnd(25)} ${resolvedCount} resolved`);
1776
- }
1777
- lines.push("");
1778
- lines.push("Resolution Stats:");
1779
- lines.push("\u2500".repeat(50));
1780
- lines.push(` Resolution rate: ${Math.round(stats.resolution.resolutionRate)}%`);
1781
- lines.push(` With pattern: ${stats.resolution.resolvedWithPattern}`);
1782
- lines.push(` Manual: ${stats.resolution.resolvedManually}`);
1783
- return lines.join("\n");
1784
- }
1785
- /**
1786
- * Helper: Count symbols across incidents
1787
- */
1788
- countSymbols(incidents) {
1789
- const counts = /* @__PURE__ */ new Map();
1790
- for (const incident of incidents) {
1791
- for (const [, value] of Object.entries(incident.symbols)) {
1792
- if (value) {
1793
- counts.set(value, (counts.get(value) || 0) + 1);
1794
- }
1795
- }
1796
- }
1797
- return counts;
1798
- }
1799
- /**
1800
- * Helper: Get all symbols from incident
1801
- */
1802
- getSymbolsFromIncident(incident) {
1803
- const symbols = [];
1804
- for (const [, value] of Object.entries(incident.symbols)) {
1805
- if (value) {
1806
- symbols.push(value);
1807
- }
1808
- }
1809
- return symbols;
1810
- }
1811
- };
1812
- var ContextEnricher = class {
1813
- constructor(projectRoot = process.cwd()) {
1814
- this.projectRoot = projectRoot;
1815
- }
1816
- symbolCache = /* @__PURE__ */ new Map();
1817
- purposeCache = /* @__PURE__ */ new Map();
1818
- /**
1819
- * Enrich an incident with symbol context
1820
- */
1821
- enrich(incident) {
1822
- const symbolEnrichments = {};
1823
- for (const [, value] of Object.entries(incident.symbols)) {
1824
- if (value) {
1825
- const enrichment = this.getSymbolContext(value);
1826
- if (enrichment && Object.keys(enrichment).length > 0) {
1827
- symbolEnrichments[value] = enrichment;
1828
- }
1829
- }
1830
- }
1831
- let flowDescription;
1832
- if (incident.symbols.flow) {
1833
- const flowContext = this.getSymbolContext(incident.symbols.flow);
1834
- flowDescription = flowContext?.description;
1835
- }
1836
- return {
1837
- ...incident,
1838
- enriched: {
1839
- symbols: symbolEnrichments,
1840
- flowDescription
1841
- }
1842
- };
1843
- }
1844
- /**
1845
- * Get symbol metadata from index or .purpose files
1846
- */
1847
- getSymbolContext(symbol) {
1848
- const cached = this.symbolCache.get(symbol);
1849
- if (cached) {
1850
- return cached;
1851
- }
1852
- const enrichment = {};
1853
- const indexEntry = this.findInSymbolIndex(symbol);
1854
- if (indexEntry) {
1855
- enrichment.description = indexEntry.description;
1856
- enrichment.definedIn = indexEntry.file;
1857
- enrichment.references = indexEntry.references;
1858
- enrichment.referencedBy = indexEntry.referencedBy;
1859
- }
1860
- const purposeEntry = this.findInPurposeFiles(symbol);
1861
- if (purposeEntry) {
1862
- if (!enrichment.description && purposeEntry.description) {
1863
- enrichment.description = purposeEntry.description;
1864
- }
1865
- if (purposeEntry.references) {
1866
- enrichment.references = [
1867
- .../* @__PURE__ */ new Set([...enrichment.references || [], ...purposeEntry.references])
1868
- ];
1869
- }
1870
- if (purposeEntry.referencedBy) {
1871
- enrichment.referencedBy = [
1872
- .../* @__PURE__ */ new Set([...enrichment.referencedBy || [], ...purposeEntry.referencedBy])
1873
- ];
1874
- }
1875
- }
1876
- this.symbolCache.set(symbol, enrichment);
1877
- return enrichment;
1878
- }
1879
- /**
1880
- * Find symbol in premise index
1881
- */
1882
- findInSymbolIndex(symbol) {
1883
- const indexPath = path3.join(this.projectRoot, ".paradigm", "index.json");
1884
- if (!fs3.existsSync(indexPath)) {
1885
- return null;
1886
- }
1887
- try {
1888
- const indexContent = fs3.readFileSync(indexPath, "utf-8");
1889
- const index = JSON.parse(indexContent);
1890
- if (index.symbols && Array.isArray(index.symbols)) {
1891
- return index.symbols.find(
1892
- (s) => s.id === symbol
1893
- ) || null;
1894
- }
1895
- return null;
1896
- } catch {
1897
- return null;
1898
- }
1899
- }
1900
- /**
1901
- * Find symbol in .purpose files
1902
- */
1903
- findInPurposeFiles(symbol) {
1904
- const searchPaths = this.getSearchPathsForSymbol(symbol);
1905
- for (const searchPath of searchPaths) {
1906
- const fullPath = path3.join(this.projectRoot, searchPath);
1907
- if (!fs3.existsSync(fullPath)) {
1908
- continue;
1909
- }
1910
- const cached = this.purposeCache.get(fullPath);
1911
- if (cached) {
1912
- if (cached.symbol === symbol) {
1913
- return cached;
1914
- }
1915
- continue;
1916
- }
1917
- try {
1918
- const content = fs3.readFileSync(fullPath, "utf-8");
1919
- const purpose = this.parsePurposeFile(content);
1920
- this.purposeCache.set(fullPath, purpose);
1921
- if (purpose.symbol === symbol) {
1922
- return purpose;
1923
- }
1924
- } catch {
1925
- continue;
1926
- }
1927
- }
1928
- return null;
1929
- }
1930
- /**
1931
- * Get potential file paths for a symbol
1932
- */
1933
- getSearchPathsForSymbol(symbol) {
1934
- const paths = [];
1935
- const cleanSymbol = symbol.replace(/^[@#$%^!&~?]/, "");
1936
- const prefixDirs = {
1937
- "@": ["features", "src/features"],
1938
- "#": ["components", "src/components"],
1939
- "$": ["flows", "src/flows"],
1940
- "^": ["middleware", "gates", "src/middleware"],
1941
- "!": ["signals", "events", "src/signals"],
1942
- "%": ["state", "store", "src/state"],
1943
- "&": ["integrations", "services", "src/integrations"]
1944
- };
1945
- const prefix = symbol[0];
1946
- const dirs = prefixDirs[prefix] || [];
1947
- for (const dir of dirs) {
1948
- paths.push(path3.join(dir, cleanSymbol, ".purpose"));
1949
- paths.push(path3.join(dir, `${cleanSymbol}.purpose`));
1950
- }
1951
- paths.push(path3.join(".paradigm", "purposes", `${cleanSymbol}.yaml`));
1952
- paths.push(path3.join(".paradigm", "purposes", `${cleanSymbol}.json`));
1953
- return paths;
1954
- }
1955
- /**
1956
- * Parse a .purpose file
1957
- */
1958
- parsePurposeFile(content) {
1959
- const result = {};
1960
- const lines = content.split("\n");
1961
- for (const line of lines) {
1962
- const trimmed = line.trim();
1963
- if (trimmed.startsWith("symbol:")) {
1964
- result.symbol = trimmed.substring(7).trim();
1965
- } else if (trimmed.startsWith("description:")) {
1966
- result.description = trimmed.substring(12).trim();
1967
- } else if (trimmed.startsWith("purpose:")) {
1968
- result.description = trimmed.substring(8).trim();
1969
- }
1970
- }
1971
- if (!result.description) {
1972
- const firstLine = lines.find((l) => l.trim() && !l.startsWith("#"));
1973
- if (firstLine) {
1974
- result.description = firstLine.trim();
1975
- }
1976
- }
1977
- return result;
1978
- }
1979
- /**
1980
- * Clear caches
1981
- */
1982
- clearCache() {
1983
- this.symbolCache.clear();
1984
- this.purposeCache.clear();
1985
- }
1986
- /**
1987
- * Batch enrich multiple incidents
1988
- */
1989
- enrichBatch(incidents) {
1990
- return incidents.map((i) => this.enrich(i));
1991
- }
1992
- };
1993
- var PatternSuggester = class {
1994
- constructor(storage) {
1995
- this.storage = storage;
1996
- }
1997
- /**
1998
- * Suggest a pattern from a resolved incident
1999
- */
2000
- suggestFromIncident(incident) {
2001
- const baseId = this.generatePatternId(incident);
2002
- const symbols = this.buildSymbolCriteria(incident.symbols);
2003
- const errorKeywords = this.extractErrorKeywords(incident.error.message);
2004
- const pattern = {
2005
- id: baseId,
2006
- name: this.generatePatternName(incident),
2007
- description: `Auto-suggested pattern from incident ${incident.id}`,
2008
- pattern: {
2009
- symbols,
2010
- errorContains: errorKeywords.length > 0 ? errorKeywords : void 0,
2011
- missingSignals: incident.flowPosition?.missing
2012
- },
2013
- resolution: {
2014
- description: incident.resolution?.notes || "Resolution approach TBD",
2015
- strategy: this.inferStrategy([incident]),
2016
- priority: "medium"
2017
- },
2018
- source: "suggested",
2019
- private: false,
2020
- tags: this.generateTags(incident)
2021
- };
2022
- return pattern;
2023
- }
2024
- /**
2025
- * Suggest a pattern from an incident group
2026
- */
2027
- suggestFromGroup(group) {
2028
- const baseId = `group-${group.id.toLowerCase().replace(/[^a-z0-9]/g, "-")}`;
2029
- const symbols = this.buildSymbolCriteria(group.commonSymbols);
2030
- const groupIncidents = group.incidents.slice(0, 20).map((id) => this.storage.getIncident(id)).filter((i) => i != null);
2031
- const pattern = {
2032
- id: baseId,
2033
- name: group.name || `Pattern from group ${group.id}`,
2034
- description: `Auto-suggested pattern from incident group with ${group.count} incidents`,
2035
- pattern: {
2036
- symbols,
2037
- errorContains: group.commonErrorPatterns.length > 0 ? group.commonErrorPatterns : void 0
2038
- },
2039
- resolution: {
2040
- description: "Resolution approach TBD based on grouped incidents",
2041
- strategy: groupIncidents.length > 0 ? this.inferStrategy(groupIncidents) : "fix-code",
2042
- priority: this.getPriorityFromCount(group.count)
2043
- },
2044
- source: "suggested",
2045
- private: false,
2046
- tags: this.generateTagsFromGroup(group)
2047
- };
2048
- return pattern;
2049
- }
2050
- /**
2051
- * Find incidents that could become patterns
2052
- */
2053
- findPatternCandidates(minOccurrences = 3) {
2054
- const incidents = this.storage.getRecentIncidents({
2055
- limit: 1e3,
2056
- status: "resolved"
2057
- });
2058
- const signatureGroups = /* @__PURE__ */ new Map();
2059
- for (const incident of incidents) {
2060
- const signature = this.getSymbolSignature(incident.symbols);
2061
- const existing = signatureGroups.get(signature) || [];
2062
- existing.push(incident);
2063
- signatureGroups.set(signature, existing);
2064
- }
2065
- const candidates = [];
2066
- for (const [, groupIncidents] of signatureGroups) {
2067
- if (groupIncidents.length >= minOccurrences) {
2068
- const hasPattern = this.hasMatchingPattern(groupIncidents[0]);
2069
- if (hasPattern) continue;
2070
- const suggestedPattern = this.suggestFromIncidents(groupIncidents);
2071
- candidates.push({
2072
- incidents: groupIncidents,
2073
- suggestedPattern,
2074
- occurrenceCount: groupIncidents.length
2075
- });
2076
- }
2077
- }
2078
- return candidates.sort((a, b) => b.occurrenceCount - a.occurrenceCount);
2079
- }
2080
- /**
2081
- * Generate pattern from multiple similar incidents
2082
- */
2083
- suggestFromIncidents(incidents) {
2084
- const commonSymbols = this.extractCommonSymbols(incidents);
2085
- const symbols = this.buildSymbolCriteria(commonSymbols);
2086
- const errorKeywords = this.extractCommonErrorKeywords(incidents);
2087
- const missingSignals = this.extractCommonMissingSignals(incidents);
2088
- const baseId = this.generatePatternId(incidents[0]);
2089
- return {
2090
- id: baseId,
2091
- name: this.generatePatternName(incidents[0]),
2092
- description: `Auto-suggested pattern from ${incidents.length} similar incidents`,
2093
- pattern: {
2094
- symbols,
2095
- errorContains: errorKeywords.length > 0 ? errorKeywords : void 0,
2096
- missingSignals: missingSignals.length > 0 ? missingSignals : void 0
2097
- },
2098
- resolution: {
2099
- description: "Resolution approach based on previous resolutions",
2100
- strategy: this.inferStrategy(incidents),
2101
- priority: this.getPriorityFromCount(incidents.length)
2102
- },
2103
- source: "suggested",
2104
- private: false,
2105
- tags: this.generateTagsFromIncidents(incidents)
2106
- };
2107
- }
2108
- /**
2109
- * Build symbol criteria for pattern, adding wildcards where appropriate
2110
- */
2111
- buildSymbolCriteria(symbols) {
2112
- const criteria = {};
2113
- for (const [key, value] of Object.entries(symbols)) {
2114
- if (value) {
2115
- criteria[key] = value;
2116
- }
2117
- }
2118
- return criteria;
2119
- }
2120
- /**
2121
- * Extract keywords from error message
2122
- */
2123
- extractErrorKeywords(message) {
2124
- const stopWords = /* @__PURE__ */ new Set([
2125
- "the",
2126
- "a",
2127
- "an",
2128
- "is",
2129
- "are",
2130
- "was",
2131
- "were",
2132
- "in",
2133
- "on",
2134
- "at",
2135
- "to",
2136
- "for",
2137
- "of",
2138
- "with",
2139
- "and",
2140
- "or",
2141
- "but",
2142
- "not",
2143
- "no",
2144
- "be",
2145
- "been",
2146
- "have",
2147
- "has",
2148
- "had",
2149
- "do",
2150
- "does",
2151
- "did"
2152
- ]);
2153
- const words = message.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !stopWords.has(w));
2154
- const unique = [...new Set(words)];
2155
- return unique.slice(0, 5);
2156
- }
2157
- /**
2158
- * Extract common error keywords from multiple incidents
2159
- */
2160
- extractCommonErrorKeywords(incidents) {
2161
- const wordCounts = /* @__PURE__ */ new Map();
2162
- for (const incident of incidents) {
2163
- const keywords = this.extractErrorKeywords(incident.error.message);
2164
- for (const keyword of keywords) {
2165
- wordCounts.set(keyword, (wordCounts.get(keyword) || 0) + 1);
2166
- }
2167
- }
2168
- const threshold = Math.ceil(incidents.length * 0.5);
2169
- return Array.from(wordCounts.entries()).filter(([, count]) => count >= threshold).map(([word]) => word).slice(0, 5);
2170
- }
2171
- /**
2172
- * Extract symbols common to all incidents
2173
- */
2174
- extractCommonSymbols(incidents) {
2175
- if (incidents.length === 0) return {};
2176
- const first = incidents[0].symbols;
2177
- const common = {};
2178
- for (const [key, value] of Object.entries(first)) {
2179
- if (!value) continue;
2180
- const allMatch = incidents.every(
2181
- (i) => i.symbols[key] === value
2182
- );
2183
- if (allMatch) {
2184
- common[key] = value;
2185
- }
2186
- }
2187
- return common;
2188
- }
2189
- /**
2190
- * Extract missing signals common to multiple incidents
2191
- */
2192
- extractCommonMissingSignals(incidents) {
2193
- const signalCounts = /* @__PURE__ */ new Map();
2194
- for (const incident of incidents) {
2195
- if (!incident.flowPosition?.missing) continue;
2196
- for (const signal of incident.flowPosition.missing) {
2197
- signalCounts.set(signal, (signalCounts.get(signal) || 0) + 1);
2198
- }
2199
- }
2200
- const threshold = Math.ceil(incidents.length * 0.5);
2201
- return Array.from(signalCounts.entries()).filter(([, count]) => count >= threshold).map(([signal]) => signal);
2202
- }
2203
- /**
2204
- * Generate a pattern ID from incident
2205
- */
2206
- generatePatternId(incident) {
2207
- const parts = [];
2208
- if (incident.symbols.gate) {
2209
- parts.push(incident.symbols.gate.replace(/[^a-z0-9]/gi, ""));
2210
- } else if (incident.symbols.feature) {
2211
- parts.push(incident.symbols.feature.replace(/[^a-z0-9]/gi, ""));
2212
- } else if (incident.symbols.component) {
2213
- parts.push(incident.symbols.component.replace(/[^a-z0-9]/gi, ""));
2214
- } else if (incident.symbols.integration) {
2215
- parts.push(incident.symbols.integration.replace(/[^a-z0-9]/gi, ""));
2216
- } else {
2217
- parts.push("unknown");
2218
- }
2219
- const errorType = incident.error.type?.toLowerCase() || "error";
2220
- parts.push(errorType.replace(/[^a-z0-9]/gi, ""));
2221
- parts.push(String(Date.now() % 1e3).padStart(3, "0"));
2222
- return parts.join("-");
2223
- }
2224
- /**
2225
- * Generate a human-readable pattern name
2226
- */
2227
- generatePatternName(incident) {
2228
- const parts = [];
2229
- if (incident.symbols.feature) {
2230
- parts.push(
2231
- incident.symbols.feature.replace("@", "").replace(/-/g, " ")
2232
- );
2233
- }
2234
- if (incident.symbols.gate) {
2235
- parts.push("gate " + incident.symbols.gate.replace("^", ""));
2236
- }
2237
- if (incident.error.type) {
2238
- parts.push(incident.error.type);
2239
- }
2240
- if (parts.length === 0) {
2241
- return "Unnamed Pattern";
2242
- }
2243
- const name = parts.join(" - ");
2244
- return name.charAt(0).toUpperCase() + name.slice(1);
2245
- }
2246
- /**
2247
- * Generate tags from incident
2248
- */
2249
- generateTags(incident) {
2250
- const tags = [];
2251
- if (incident.symbols.feature) {
2252
- tags.push("feature");
2253
- }
2254
- if (incident.symbols.gate) {
2255
- tags.push("gate");
2256
- }
2257
- if (incident.symbols.integration) {
2258
- tags.push("integration");
2259
- tags.push(incident.symbols.integration.replace("&", ""));
2260
- }
2261
- if (incident.error.type) {
2262
- tags.push(incident.error.type.toLowerCase());
2263
- }
2264
- tags.push(incident.environment);
2265
- return [...new Set(tags)].slice(0, 5);
2266
- }
2267
- /**
2268
- * Generate tags from incident group
2269
- */
2270
- generateTagsFromGroup(group) {
2271
- const tags = ["grouped"];
2272
- if (group.commonSymbols.feature) {
2273
- tags.push("feature");
2274
- }
2275
- if (group.commonSymbols.gate) {
2276
- tags.push("gate");
2277
- }
2278
- if (group.commonSymbols.integration) {
2279
- tags.push("integration");
2280
- }
2281
- for (const env of group.environments) {
2282
- tags.push(env);
2283
- }
2284
- return [...new Set(tags)].slice(0, 5);
2285
- }
2286
- /**
2287
- * Generate tags from multiple incidents
2288
- */
2289
- generateTagsFromIncidents(incidents) {
2290
- const tagCounts = /* @__PURE__ */ new Map();
2291
- for (const incident of incidents) {
2292
- const tags = this.generateTags(incident);
2293
- for (const tag of tags) {
2294
- tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);
2295
- }
2296
- }
2297
- return Array.from(tagCounts.entries()).sort((a, b) => b[1] - a[1]).slice(0, 5).map(([tag]) => tag);
2298
- }
2299
- /**
2300
- * Get symbol signature for grouping
2301
- */
2302
- getSymbolSignature(symbols) {
2303
- const parts = [];
2304
- if (symbols.feature) parts.push(`f:${symbols.feature}`);
2305
- if (symbols.component) parts.push(`c:${symbols.component}`);
2306
- if (symbols.flow) parts.push(`fl:${symbols.flow}`);
2307
- if (symbols.gate) parts.push(`g:${symbols.gate}`);
2308
- if (symbols.integration) parts.push(`i:${symbols.integration}`);
2309
- return parts.sort().join("|");
2310
- }
2311
- /**
2312
- * Check if there's already a pattern matching this incident
2313
- */
2314
- hasMatchingPattern(incident) {
2315
- const patterns = this.storage.getAllPatterns({ includePrivate: true });
2316
- for (const pattern of patterns) {
2317
- let matchCount = 0;
2318
- const symbolTypes = [
2319
- "feature",
2320
- "component",
2321
- "flow",
2322
- "gate",
2323
- "signal",
2324
- "integration"
2325
- ];
2326
- for (const type of symbolTypes) {
2327
- const patternValue = pattern.pattern.symbols[type];
2328
- const incidentValue = incident.symbols[type];
2329
- if (patternValue && incidentValue && patternValue === incidentValue) {
2330
- matchCount++;
2331
- }
2332
- }
2333
- if (matchCount >= 2) {
2334
- return true;
2335
- }
2336
- }
2337
- return false;
2338
- }
2339
- /**
2340
- * Infer resolution strategy from incident error patterns and context.
2341
- * Uses keyword heuristics across all incident messages to pick the
2342
- * most likely resolution approach.
2343
- */
2344
- inferStrategy(incidents) {
2345
- const messages = incidents.map((i) => i.error.message.toLowerCase());
2346
- const hasKeyword = (keywords) => messages.some((m) => keywords.some((k) => m.includes(k)));
2347
- if (hasKeyword(["revert", "rollback", "regression", "broke after deploy", "since deploy"])) {
2348
- return "rollback";
2349
- }
2350
- if (hasKeyword(["config", "environment variable", "env var", "missing key", "secret", "credential"])) {
2351
- return "config-change";
2352
- }
2353
- if (hasKeyword(["out of memory", "oom", "heap", "memory limit", "capacity", "too many connections", "pool exhausted"])) {
2354
- return "scale-up";
2355
- }
2356
- if (hasKeyword(["timeout", "network", "econnrefused", "econnreset", "dns", "socket hang up"])) {
2357
- return "retry";
2358
- }
2359
- if (hasKeyword(["unavailable", "service down", "circuit breaker", "fallback", "503", "502"])) {
2360
- return "fallback";
2361
- }
2362
- if (hasKeyword(["validation", "invalid", "required", "constraint", "duplicate", "not found", "404"])) {
2363
- return "fix-data";
2364
- }
2365
- if (hasKeyword(["permission", "forbidden", "403", "401", "unauthorized", "access denied"])) {
2366
- return "escalate";
2367
- }
2368
- const uniqueTypes = new Set(incidents.map((i) => i.error.type).filter(Boolean));
2369
- if (uniqueTypes.size > 2) {
2370
- return "investigate";
2371
- }
2372
- return "fix-code";
2373
- }
2374
- /**
2375
- * Get priority based on occurrence count
2376
- */
2377
- getPriorityFromCount(count) {
2378
- if (count >= 20) return "critical";
2379
- if (count >= 10) return "high";
2380
- if (count >= 5) return "medium";
2381
- return "low";
2382
- }
2383
- };
2384
- var PatternImporter = class {
2385
- /**
2386
- * Validate a pattern export file
2387
- */
2388
- validate(data) {
2389
- const errors = [];
2390
- const warnings = [];
2391
- if (!data || typeof data !== "object") {
2392
- return { valid: false, errors: ["Invalid data: expected object"], warnings: [] };
2393
- }
2394
- const obj = data;
2395
- if (!obj.version) {
2396
- errors.push("Missing version field");
2397
- }
2398
- if (!Array.isArray(obj.patterns)) {
2399
- errors.push("Missing or invalid patterns array");
2400
- return { valid: false, errors, warnings };
2401
- }
2402
- for (let i = 0; i < obj.patterns.length; i++) {
2403
- const pattern = obj.patterns[i];
2404
- const patternErrors = this.validatePattern(pattern, i);
2405
- errors.push(...patternErrors.errors);
2406
- warnings.push(...patternErrors.warnings);
2407
- }
2408
- return {
2409
- valid: errors.length === 0,
2410
- errors,
2411
- warnings
2412
- };
2413
- }
2414
- /**
2415
- * Validate a single pattern
2416
- */
2417
- validatePattern(pattern, index) {
2418
- const errors = [];
2419
- const warnings = [];
2420
- const prefix = `Pattern[${index}]`;
2421
- if (!pattern.id || typeof pattern.id !== "string") {
2422
- errors.push(`${prefix}: Missing or invalid id`);
2423
- } else if (!/^[a-z0-9-]+$/.test(pattern.id)) {
2424
- warnings.push(`${prefix}: ID "${pattern.id}" should be kebab-case`);
2425
- }
2426
- if (!pattern.name || typeof pattern.name !== "string") {
2427
- errors.push(`${prefix}: Missing or invalid name`);
2428
- }
2429
- if (!pattern.pattern || typeof pattern.pattern !== "object") {
2430
- errors.push(`${prefix}: Missing or invalid pattern criteria`);
2431
- } else {
2432
- const criteria = pattern.pattern;
2433
- const hasSymbols = criteria.symbols && typeof criteria.symbols === "object" && Object.keys(criteria.symbols).length > 0;
2434
- const hasErrorContains = Array.isArray(criteria.errorContains) && criteria.errorContains.length > 0;
2435
- const hasErrorMatches = criteria.errorMatches && typeof criteria.errorMatches === "string";
2436
- const hasMissingSignals = Array.isArray(criteria.missingSignals) && criteria.missingSignals.length > 0;
2437
- if (!hasSymbols && !hasErrorContains && !hasErrorMatches && !hasMissingSignals) {
2438
- errors.push(`${prefix}: Pattern must have at least one matching criteria`);
2439
- }
2440
- }
2441
- if (!pattern.resolution || typeof pattern.resolution !== "object") {
2442
- errors.push(`${prefix}: Missing or invalid resolution`);
2443
- } else {
2444
- const resolution = pattern.resolution;
2445
- if (!resolution.description || typeof resolution.description !== "string") {
2446
- errors.push(`${prefix}: Missing resolution description`);
2447
- }
2448
- if (!resolution.strategy || typeof resolution.strategy !== "string") {
2449
- errors.push(`${prefix}: Missing resolution strategy`);
2450
- } else {
2451
- const validStrategies = [
2452
- "retry",
2453
- "fallback",
2454
- "fix-data",
2455
- "fix-code",
2456
- "ignore",
2457
- "escalate"
2458
- ];
2459
- if (!validStrategies.includes(resolution.strategy)) {
2460
- errors.push(`${prefix}: Invalid strategy "${resolution.strategy}"`);
2461
- }
2462
- }
2463
- if (!resolution.priority || typeof resolution.priority !== "string") {
2464
- warnings.push(`${prefix}: Missing priority, will default to medium`);
2465
- } else {
2466
- const validPriorities = ["low", "medium", "high", "critical"];
2467
- if (!validPriorities.includes(resolution.priority)) {
2468
- warnings.push(`${prefix}: Invalid priority "${resolution.priority}"`);
2469
- }
2470
- }
2471
- }
2472
- return { errors, warnings };
2473
- }
2474
- /**
2475
- * Load patterns from a JSON file
2476
- */
2477
- loadFromFile(filePath) {
2478
- if (!fs4.existsSync(filePath)) {
2479
- throw new Error(`File not found: ${filePath}`);
2480
- }
2481
- const content = fs4.readFileSync(filePath, "utf-8");
2482
- const data = JSON.parse(content);
2483
- const validation = this.validate(data);
2484
- if (!validation.valid) {
2485
- throw new Error(`Invalid pattern file: ${validation.errors.join(", ")}`);
2486
- }
2487
- return this.normalizeExport(data);
2488
- }
2489
- /**
2490
- * Load patterns from a URL
2491
- */
2492
- async loadFromUrl(url) {
2493
- const response = await fetch(url);
2494
- if (!response.ok) {
2495
- throw new Error(`Failed to fetch patterns: ${response.statusText}`);
2496
- }
2497
- const data = await response.json();
2498
- const validation = this.validate(data);
2499
- if (!validation.valid) {
2500
- throw new Error(`Invalid pattern data: ${validation.errors.join(", ")}`);
2501
- }
2502
- return this.normalizeExport(data);
2503
- }
2504
- /**
2505
- * Normalize raw data to PatternExport
2506
- */
2507
- normalizeExport(data) {
2508
- const patterns = data.patterns.map(
2509
- (p) => this.normalizePattern(p)
2510
- );
2511
- return {
2512
- version: data.version || "1.0.0",
2513
- exportedAt: data.exportedAt || (/* @__PURE__ */ new Date()).toISOString(),
2514
- patterns
2515
- };
2516
- }
2517
- /**
2518
- * Normalize a raw pattern object
2519
- */
2520
- normalizePattern(data) {
2521
- const pattern = data.pattern;
2522
- const resolution = data.resolution;
2523
- const confidence = data.confidence || {};
2524
- return {
2525
- id: data.id,
2526
- name: data.name,
2527
- description: data.description || "",
2528
- pattern: {
2529
- symbols: pattern.symbols || {},
2530
- errorContains: pattern.errorContains,
2531
- errorMatches: pattern.errorMatches,
2532
- errorType: pattern.errorType,
2533
- missingSignals: pattern.missingSignals,
2534
- environment: pattern.environment
2535
- },
2536
- resolution: {
2537
- description: resolution.description,
2538
- strategy: resolution.strategy,
2539
- priority: resolution.priority || "medium",
2540
- codeHint: resolution.codeHint,
2541
- codeSnippet: resolution.codeSnippet,
2542
- symbolsToModify: resolution.symbolsToModify,
2543
- filesLikelyInvolved: resolution.filesLikelyInvolved,
2544
- commitRef: resolution.commitRef,
2545
- prRef: resolution.prRef,
2546
- docsRef: resolution.docsRef
2547
- },
2548
- confidence: {
2549
- score: confidence.score || 50,
2550
- timesMatched: confidence.timesMatched || 0,
2551
- timesResolved: confidence.timesResolved || 0,
2552
- timesRecurred: confidence.timesRecurred || 0,
2553
- avgTimeToResolve: confidence.avgTimeToResolve,
2554
- lastMatched: confidence.lastMatched,
2555
- lastResolved: confidence.lastResolved
2556
- },
2557
- source: data.source || "imported",
2558
- private: Boolean(data.private),
2559
- tags: data.tags || [],
2560
- createdAt: data.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
2561
- updatedAt: data.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
2562
- };
2563
- }
2564
- /**
2565
- * Merge patterns from multiple sources
2566
- */
2567
- mergePatterns(...exports) {
2568
- const patternMap = /* @__PURE__ */ new Map();
2569
- for (const exp of exports) {
2570
- for (const pattern of exp.patterns) {
2571
- patternMap.set(pattern.id, pattern);
2572
- }
2573
- }
2574
- return {
2575
- version: "1.0.0",
2576
- exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
2577
- patterns: Array.from(patternMap.values())
2578
- };
2579
- }
2580
- };
2581
-
2582
- export {
2583
- SentinelClient,
2584
- createSentinelClient,
2585
- SentinelTransport,
2586
- createSentinelTransport,
2587
- enableSentinel,
2588
- PatternMatcher,
2589
- loadUniversalPatterns,
2590
- loadParadigmPatterns,
2591
- loadAllSeedPatterns,
2592
- FlowTracker,
2593
- Sentinel,
2594
- detectSymbols,
2595
- generateConfig,
2596
- IncidentGrouper,
2597
- TimelineBuilder,
2598
- StatsCalculator,
2599
- ContextEnricher,
2600
- PatternSuggester,
2601
- PatternImporter
2602
- };