agentic-qe 3.9.15 → 3.9.16

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 (295) hide show
  1. package/.claude/skills/skills-manifest.json +1 -1
  2. package/CHANGELOG.md +25 -0
  3. package/assets/skills/skills-manifest.json +1 -1
  4. package/dist/cli/brain-commands.d.ts +14 -0
  5. package/dist/cli/brain-commands.js +24 -0
  6. package/dist/cli/bundle.js +7 -7
  7. package/dist/cli/chunks/adapter-XFJIW42U.js +2 -0
  8. package/dist/cli/chunks/{agent-booster-wasm-NA2VN5U2.js → agent-booster-wasm-IECTFMRK.js} +2 -2
  9. package/dist/cli/chunks/{agent-handler-NRIF5IOC.js → agent-handler-HLLTKZ5G.js} +2 -2
  10. package/dist/cli/chunks/{agent-memory-branch-NW3UB2UW.js → agent-memory-branch-WJUD3DS4.js} +2 -2
  11. package/dist/cli/chunks/aqe-learning-engine-UD4SXENM.js +2 -0
  12. package/dist/cli/chunks/{audit-5CSEDVJR.js → audit-3DLZNWHO.js} +2 -2
  13. package/dist/cli/chunks/base-ETEN7L2V.js +2 -0
  14. package/dist/cli/chunks/{better-sqlite3-FZ32SHZ6.js → better-sqlite3-Q356NEQ6.js} +2 -2
  15. package/dist/cli/chunks/brain-handler-MX2HP7LO.js +89 -0
  16. package/dist/cli/chunks/{branch-enumerator-IUHWHIMV.js → branch-enumerator-Z3TF3HVO.js} +2 -2
  17. package/dist/cli/chunks/{browser-D4F3327X.js → browser-Z6PQ7FTO.js} +2 -2
  18. package/dist/cli/chunks/browser-workflow-KVHPOIBA.js +2 -0
  19. package/dist/cli/chunks/{chunk-ELLNKP3I.js → chunk-2KCMS4UW.js} +3 -3
  20. package/dist/cli/chunks/{chunk-IMLH32AG.js → chunk-2MJEAEOW.js} +2 -2
  21. package/dist/cli/chunks/{chunk-ISNXE6TP.js → chunk-3ADFXSO2.js} +2 -2
  22. package/dist/cli/chunks/{chunk-WI6UA5HV.js → chunk-3CAPNE2H.js} +2 -2
  23. package/dist/cli/chunks/{chunk-65QA7MYW.js → chunk-3EUA73H6.js} +2 -2
  24. package/dist/cli/chunks/{chunk-D3FV5NNA.js → chunk-3H657FNU.js} +2 -2
  25. package/dist/cli/chunks/{chunk-OMTYOIOS.js → chunk-3K4IX7L4.js} +2 -2
  26. package/dist/cli/chunks/{chunk-DYQ7HTEU.js → chunk-3SLFWPRE.js} +3 -3
  27. package/dist/cli/chunks/{chunk-MHL6CPGY.js → chunk-3ZGYB23S.js} +1 -1
  28. package/dist/cli/chunks/{chunk-IHDW4HW7.js → chunk-46K7ALFU.js} +2 -2
  29. package/dist/cli/chunks/{chunk-HNAQNAGI.js → chunk-4CFQZHUC.js} +3 -3
  30. package/dist/cli/chunks/{chunk-2XW36KDQ.js → chunk-4PFHQH4B.js} +2 -2
  31. package/dist/cli/chunks/{chunk-C5BRTU4V.js → chunk-4ZN4GM7W.js} +1 -1
  32. package/dist/cli/chunks/{chunk-3FUKJT4S.js → chunk-5A5XANSD.js} +2 -2
  33. package/dist/cli/chunks/{chunk-OUP2X3LT.js → chunk-5E7FVOOG.js} +1 -1
  34. package/dist/cli/chunks/chunk-5LDXAVDC.js +2 -0
  35. package/dist/cli/chunks/{chunk-6Z7LYE2B.js → chunk-666L7MC2.js} +2 -2
  36. package/dist/cli/chunks/{chunk-DPEG44BS.js → chunk-66BUIFFH.js} +2 -2
  37. package/dist/cli/chunks/{chunk-HJNFBJT5.js → chunk-6V5P2VMQ.js} +8 -8
  38. package/dist/cli/chunks/{chunk-3NIHJIWP.js → chunk-6XKZ62O7.js} +2 -2
  39. package/dist/cli/chunks/{chunk-D3ZUSXFY.js → chunk-77OVXVN2.js} +2 -2
  40. package/dist/cli/chunks/{chunk-WCOJGDGO.js → chunk-7DP2IQ6F.js} +2 -2
  41. package/dist/cli/chunks/{chunk-Q3GDSFGA.js → chunk-7IF4LRX2.js} +2 -2
  42. package/dist/cli/chunks/{chunk-ZOAPOVYW.js → chunk-7JFSMXIA.js} +2 -2
  43. package/dist/cli/chunks/{chunk-O6J7MKRV.js → chunk-7MF6LVLH.js} +2 -2
  44. package/dist/cli/chunks/{chunk-REUGPZIA.js → chunk-7NMLIJHL.js} +1 -1
  45. package/dist/cli/chunks/{chunk-DATFN5DG.js → chunk-7PHYOV2X.js} +2 -2
  46. package/dist/cli/chunks/{chunk-RSOOENGE.js → chunk-7V2Z3PUJ.js} +2 -2
  47. package/dist/cli/chunks/{chunk-UZOFXYNC.js → chunk-AA6IUBCM.js} +2 -2
  48. package/dist/cli/chunks/{chunk-QNLZKD7E.js → chunk-AFLQFUXA.js} +2 -2
  49. package/dist/cli/chunks/{chunk-7J5KWUC2.js → chunk-BCT26J7X.js} +1 -1
  50. package/dist/cli/chunks/{chunk-RODJK6G6.js → chunk-BEE5KXQT.js} +1 -1
  51. package/dist/cli/chunks/{chunk-BGUCXJEJ.js → chunk-BNDK7JRW.js} +2 -2
  52. package/dist/cli/chunks/{chunk-6AMD4PZB.js → chunk-CR7LLS26.js} +2 -2
  53. package/dist/cli/chunks/{chunk-62MVVEGH.js → chunk-DBCN7R63.js} +1 -1
  54. package/dist/cli/chunks/{chunk-AVKUFN3C.js → chunk-DF3DZP7H.js} +2 -2
  55. package/dist/cli/chunks/{chunk-HWK27KJK.js → chunk-DJPS7H2M.js} +1 -1
  56. package/dist/cli/chunks/{chunk-MBDX4OHD.js → chunk-ED5OUSYZ.js} +1 -1
  57. package/dist/cli/chunks/{chunk-FW6QBTPE.js → chunk-EFTK4ZVP.js} +1 -1
  58. package/dist/cli/chunks/{chunk-N2RPLPVG.js → chunk-FEQ5RDQL.js} +2 -2
  59. package/dist/cli/chunks/{chunk-JQRR37YY.js → chunk-FKQV52TC.js} +2 -2
  60. package/dist/cli/chunks/{chunk-KJTXY3DW.js → chunk-FLWIEPAT.js} +1 -1
  61. package/dist/cli/chunks/{chunk-ORKGVVXK.js → chunk-FQTUUZVK.js} +1 -1
  62. package/dist/cli/chunks/{chunk-RTVD7SZQ.js → chunk-G5DMEEQQ.js} +1 -1
  63. package/dist/cli/chunks/{chunk-IPVKVPAF.js → chunk-GB6D3SSY.js} +2 -2
  64. package/dist/cli/chunks/{chunk-37ZSWRRP.js → chunk-GP7IXB3E.js} +2 -2
  65. package/dist/cli/chunks/{chunk-LNUWNRRJ.js → chunk-H3JEGAFC.js} +9 -9
  66. package/dist/cli/chunks/{chunk-LLVS3UYZ.js → chunk-H4BZJVKU.js} +2 -2
  67. package/dist/cli/chunks/{chunk-RPOW5LWO.js → chunk-HFGCLV56.js} +1 -1
  68. package/dist/cli/chunks/{chunk-MS6T4VCU.js → chunk-HJUC2DE6.js} +2 -2
  69. package/dist/cli/chunks/{chunk-II5KTTIS.js → chunk-HN6GVQ4Q.js} +4 -4
  70. package/dist/cli/chunks/{chunk-CSB2M7IX.js → chunk-HON4X4Z3.js} +2 -2
  71. package/dist/cli/chunks/{chunk-NL2PQLRD.js → chunk-HVAW64YW.js} +2 -2
  72. package/dist/cli/chunks/{chunk-6TOUMCSE.js → chunk-HXF4FUPY.js} +2 -2
  73. package/dist/cli/chunks/{chunk-TJDAXI6E.js → chunk-IUQ6HE2J.js} +2 -2
  74. package/dist/cli/chunks/{chunk-7ZPNQ3T6.js → chunk-J2ERTUDX.js} +1 -1
  75. package/dist/cli/chunks/{chunk-2CN2NPJQ.js → chunk-JCQ5PXVM.js} +2 -2
  76. package/dist/cli/chunks/{chunk-WAQ3U4FC.js → chunk-JNXIYHLI.js} +1 -1
  77. package/dist/cli/chunks/{chunk-EY2DGYQX.js → chunk-JUKCBZCZ.js} +1 -1
  78. package/dist/cli/chunks/{chunk-TZWCVGG2.js → chunk-JZOMOYHZ.js} +1 -1
  79. package/dist/cli/chunks/{chunk-ZSC7NHK3.js → chunk-KLVS6FT2.js} +2 -2
  80. package/dist/cli/chunks/{chunk-XALB3KRR.js → chunk-KR7S4IZZ.js} +2 -2
  81. package/dist/cli/chunks/{chunk-MO4Q5ZGE.js → chunk-L2GANTQN.js} +2 -2
  82. package/dist/cli/chunks/{chunk-ESQSX37W.js → chunk-LJINNQNN.js} +2 -2
  83. package/dist/cli/chunks/{chunk-OBZMQFWG.js → chunk-LSA4XGSE.js} +2 -2
  84. package/dist/cli/chunks/{chunk-3Y4YZDHJ.js → chunk-LVA53A5R.js} +4 -4
  85. package/dist/cli/chunks/{chunk-V775NJOM.js → chunk-LVK2PDUW.js} +1 -1
  86. package/dist/cli/chunks/{chunk-B4BOOOYM.js → chunk-LWG7LKOK.js} +1 -1
  87. package/dist/cli/chunks/{chunk-NWMYV7KG.js → chunk-MECDNFOJ.js} +2 -2
  88. package/dist/cli/chunks/{chunk-Q3E6Z2RQ.js → chunk-MFRC267A.js} +1 -1
  89. package/dist/cli/chunks/{chunk-2BBKAX7X.js → chunk-MJKFU6A6.js} +2 -2
  90. package/dist/cli/chunks/{chunk-4T36OQUK.js → chunk-MQHP65QB.js} +3 -3
  91. package/dist/cli/chunks/{chunk-GLJ6CJNY.js → chunk-MTF6ABUH.js} +2 -2
  92. package/dist/cli/chunks/{chunk-56YHSI6R.js → chunk-N5ZTPAX7.js} +2 -2
  93. package/dist/cli/chunks/{chunk-V65DK6ZZ.js → chunk-NCXXXZGL.js} +1 -1
  94. package/dist/cli/chunks/{chunk-YCYFUYCE.js → chunk-NIXMFJJC.js} +2 -2
  95. package/dist/cli/chunks/{chunk-GHEO5YVA.js → chunk-NLU4XJBN.js} +1 -1
  96. package/dist/cli/chunks/{chunk-CUQBOVRP.js → chunk-NOJVROCD.js} +1 -1
  97. package/dist/cli/chunks/{chunk-HPY7HGVQ.js → chunk-OE7SGIX2.js} +2 -2
  98. package/dist/cli/chunks/{chunk-AE65B2ZE.js → chunk-OP7X434R.js} +2 -2
  99. package/dist/cli/chunks/{chunk-E3EDVRB5.js → chunk-P4IYRPCB.js} +1 -1
  100. package/dist/cli/chunks/{chunk-PSOIVDD2.js → chunk-PNZADZSI.js} +3 -3
  101. package/dist/cli/chunks/{chunk-FSOY2XB4.js → chunk-PPUEXTH2.js} +3 -3
  102. package/dist/cli/chunks/{chunk-6F3H2C5H.js → chunk-PQLT3X6X.js} +3 -3
  103. package/dist/cli/chunks/{chunk-W4PUKTBF.js → chunk-QEKZA2NJ.js} +1 -1
  104. package/dist/cli/chunks/{chunk-IPTGPCEL.js → chunk-QKQAQPXY.js} +2 -2
  105. package/dist/cli/chunks/{chunk-JAIIPEE6.js → chunk-RFLSJ7OL.js} +2 -2
  106. package/dist/cli/chunks/{chunk-U4WDJPRL.js → chunk-RVQXMMRO.js} +2 -2
  107. package/dist/cli/chunks/{chunk-EORSYD66.js → chunk-RYCAVZSD.js} +2 -2
  108. package/dist/cli/chunks/{chunk-D32YCVCA.js → chunk-SMNOZEM7.js} +2 -2
  109. package/dist/cli/chunks/{chunk-ZHTCZGML.js → chunk-T36IXY5W.js} +2 -2
  110. package/dist/cli/chunks/{chunk-6OEGZSRK.js → chunk-T7VIUEKI.js} +2 -2
  111. package/dist/cli/chunks/{chunk-6BHAGCZD.js → chunk-TFBEX7ED.js} +1 -1
  112. package/dist/cli/chunks/{chunk-V6QARSVQ.js → chunk-TPRYLARW.js} +2 -2
  113. package/dist/cli/chunks/{chunk-3BA2FGSA.js → chunk-TR4NPMRW.js} +2 -2
  114. package/dist/cli/chunks/{chunk-R4G64UH3.js → chunk-TUPFBZKO.js} +1 -1
  115. package/dist/cli/chunks/{chunk-KKBSX43Q.js → chunk-TWEBJWJI.js} +2 -2
  116. package/dist/cli/chunks/{chunk-RWVFOXYM.js → chunk-UH7TV6BY.js} +1 -1
  117. package/dist/cli/chunks/{chunk-2L5ZFBHP.js → chunk-UT4CXF6C.js} +2 -2
  118. package/dist/cli/chunks/{chunk-JJDHD7SC.js → chunk-V2ELGHLG.js} +2 -2
  119. package/dist/cli/chunks/{chunk-G3FUOFXA.js → chunk-VK2GKQYI.js} +2 -2
  120. package/dist/cli/chunks/{chunk-VBEVZUQW.js → chunk-VNAAXZGF.js} +1 -1
  121. package/dist/cli/chunks/{chunk-O6CHLZYT.js → chunk-VOAECU7B.js} +2 -2
  122. package/dist/cli/chunks/{chunk-3RSPEFU3.js → chunk-W4ZV6LAJ.js} +2 -2
  123. package/dist/cli/chunks/{chunk-XXRDI53H.js → chunk-W6TMZY5R.js} +2 -2
  124. package/dist/cli/chunks/{chunk-CWWUBZNX.js → chunk-WKLSXJD4.js} +2 -2
  125. package/dist/cli/chunks/{chunk-H6DAP4KS.js → chunk-WSKASZYC.js} +2 -2
  126. package/dist/cli/chunks/{chunk-VDDQSW4L.js → chunk-WVFLNGOK.js} +2 -2
  127. package/dist/cli/chunks/{chunk-SSQ42GI7.js → chunk-WVHH3OQ4.js} +2 -2
  128. package/dist/cli/chunks/{chunk-OHESV6I3.js → chunk-XAULPLOC.js} +4 -4
  129. package/dist/cli/chunks/{chunk-GWUO3RY5.js → chunk-XKMMFQSJ.js} +1 -1
  130. package/dist/cli/chunks/{chunk-SXUX6PTE.js → chunk-XQ6WIPDC.js} +1 -1
  131. package/dist/cli/chunks/{chunk-4M7RBSW6.js → chunk-ZCE6JNRI.js} +2 -2
  132. package/dist/cli/chunks/{chunk-CF3W34BA.js → chunk-ZCZJYM42.js} +1 -1
  133. package/dist/cli/chunks/{chunk-ICXWXO5P.js → chunk-ZXLF3IKT.js} +1 -1
  134. package/dist/cli/chunks/{ci-BGUUHDUS.js → ci-TTP5HJSW.js} +2 -2
  135. package/dist/cli/chunks/{ci-output-CDFRGBNU.js → ci-output-TKESU45X.js} +2 -2
  136. package/dist/cli/chunks/{circuit-breaker-S3NFX6RQ.js → circuit-breaker-GFRV5R7E.js} +2 -2
  137. package/dist/cli/chunks/{claude-flow-setup-AJIPJFMC.js → claude-flow-setup-LY6MADFA.js} +2 -2
  138. package/dist/cli/chunks/client-ZDVM5WFL.js +2 -0
  139. package/dist/cli/chunks/{cline-installer-6O4KZ5UH.js → cline-installer-OSAILLDH.js} +2 -2
  140. package/dist/cli/chunks/{code-IZALXUL5.js → code-ASRSOGYH.js} +2 -2
  141. package/dist/cli/chunks/{code-index-extractor-N7VDH4XF.js → code-index-extractor-AMLGVHB7.js} +2 -2
  142. package/dist/cli/chunks/{codex-installer-35GTWCFJ.js → codex-installer-3CKH3WV4.js} +2 -2
  143. package/dist/cli/chunks/{completions-XPJFHGG2.js → completions-MXNPWLOE.js} +91 -10
  144. package/dist/cli/chunks/{complexity-analyzer-DNLCJGUJ.js → complexity-analyzer-2Z347PXF.js} +2 -2
  145. package/dist/cli/chunks/{continuedev-installer-PXAIKNYO.js → continuedev-installer-LE7K745N.js} +2 -2
  146. package/dist/cli/chunks/{copilot-installer-2TQ5IZNY.js → copilot-installer-CHJL3275.js} +2 -2
  147. package/dist/cli/chunks/{cost-tracker-A5XH4W6S.js → cost-tracker-C3ZWNNSV.js} +2 -2
  148. package/dist/cli/chunks/{coverage-EPIMXTLW.js → coverage-6JOXBVDL.js} +3 -3
  149. package/dist/cli/chunks/cross-domain-router-J5VK276J.js +2 -0
  150. package/dist/cli/chunks/{cursor-installer-WMMRPW44.js → cursor-installer-RKCNWO42.js} +2 -2
  151. package/dist/cli/chunks/{daemon-55DSODOH.js → daemon-XXWOT6TM.js} +3 -3
  152. package/dist/cli/chunks/{dag-attention-scheduler-5DSWXMMK.js → dag-attention-scheduler-37MG6XR4.js} +2 -2
  153. package/dist/cli/chunks/{detect-NOS46AWN.js → detect-QOTL36CE.js} +2 -2
  154. package/dist/cli/chunks/{domain-handler-BFRNU6S3.js → domain-handler-TJNLNJ7Z.js} +2 -2
  155. package/dist/cli/chunks/{domain-transfer-BPSA4HFR.js → domain-transfer-FDHC2MGH.js} +2 -2
  156. package/dist/cli/chunks/dream-VCLN6RM4.js +2 -0
  157. package/dist/cli/chunks/esm-node-YZSRCH6T.js +2 -0
  158. package/dist/cli/chunks/{eval-YDLM23FB.js → eval-JP7CLUTD.js} +2 -2
  159. package/dist/cli/chunks/{fast-paths-GISZ7HBO.js → fast-paths-CWTVLIIC.js} +2 -2
  160. package/dist/cli/chunks/{feature-flags-5WGZLUPQ.js → feature-flags-H2UU53L4.js} +2 -2
  161. package/dist/cli/chunks/{feature-flags-3FLJF6CQ.js → feature-flags-SKFBAHR3.js} +2 -2
  162. package/dist/cli/chunks/{file-discovery-PPHUMFSI.js → file-discovery-RWVGKIDB.js} +2 -2
  163. package/dist/cli/chunks/{fleet-LHFZ53FS.js → fleet-JOSUYRTZ.js} +3 -3
  164. package/dist/cli/chunks/{gnn-wrapper-Z45DRWGI.js → gnn-wrapper-WNOZFTDD.js} +2 -2
  165. package/dist/cli/chunks/{heartbeat-handler-VMLJ5PDH.js → heartbeat-handler-73YSR6K7.js} +4 -4
  166. package/dist/cli/chunks/{heartbeat-scheduler-GUWYDHEY.js → heartbeat-scheduler-EN52JZUX.js} +2 -2
  167. package/dist/cli/chunks/hnsw-adapter-Y5HVTNJW.js +2 -0
  168. package/dist/cli/chunks/hnsw-index-NZTCPZA5.js +2 -0
  169. package/dist/cli/chunks/{hnsw-legacy-bridge-S7UZWDUP.js → hnsw-legacy-bridge-PWD6DXS4.js} +2 -2
  170. package/dist/cli/chunks/{hnswlib-node-MIAAS7OI.js → hnswlib-node-VAZOCNY7.js} +2 -2
  171. package/dist/cli/chunks/{hooks-ZN4FV5XS.js → hooks-K7XGDF2Y.js} +6 -6
  172. package/dist/cli/chunks/{hybrid-router-Y6LBFPL7.js → hybrid-router-6W323WKW.js} +2 -2
  173. package/dist/cli/chunks/{hypergraph-engine-KK73LZYZ.js → hypergraph-engine-R2N4C24I.js} +2 -2
  174. package/dist/cli/chunks/{hypergraph-handler-OBGDPIWG.js → hypergraph-handler-AY4YZDOG.js} +3 -3
  175. package/dist/cli/chunks/impact-analyzer-ROWLIS6H.js +2 -0
  176. package/dist/cli/chunks/{init-handler-JJJ7VHM4.js → init-handler-UDBW4P3Z.js} +6 -6
  177. package/dist/cli/chunks/init-wizard-MI76CUL5.js +2 -0
  178. package/dist/cli/chunks/kernel-5WVAV5RX.js +2 -0
  179. package/dist/cli/chunks/{kilocode-installer-EF6DPX2D.js → kilocode-installer-J2NZUDEQ.js} +2 -2
  180. package/dist/cli/chunks/{kiro-installer-SG74CEVO.js → kiro-installer-AHOOKFQH.js} +2 -2
  181. package/dist/cli/chunks/knowledge-graph-QXL3AWPV.js +2 -0
  182. package/dist/cli/chunks/{learning-LVWYMHF6.js → learning-VC7X2HKA.js} +3 -3
  183. package/dist/cli/chunks/{llm-router-QFK7MNPY.js → llm-router-3PU7CH5P.js} +4 -4
  184. package/dist/cli/chunks/{load-6XPV4WA2.js → load-WB4JD6X7.js} +2 -2
  185. package/dist/cli/chunks/load-test-2JOY7YH6.js +2 -0
  186. package/dist/cli/chunks/{mcp-GZXOPYMH.js → mcp-QUU2DYYK.js} +2 -2
  187. package/dist/cli/chunks/{memory-QTE2Z5HU.js → memory-UAEWPG34.js} +5 -5
  188. package/dist/cli/chunks/memory-backend-ZKGLAWQZ.js +2 -0
  189. package/dist/cli/chunks/{memory-handlers-PC4P4YEF.js → memory-handlers-3FBXIZG4.js} +2 -2
  190. package/dist/cli/chunks/{multi-model-executor-FZOPSUOT.js → multi-model-executor-CIUHXR43.js} +2 -2
  191. package/dist/cli/chunks/{opencode-installer-CITDTCUQ.js → opencode-installer-VV6RIHNR.js} +2 -2
  192. package/dist/cli/chunks/{orchestrator-ZTG7MFHQ.js → orchestrator-WV27PZZM.js} +5 -5
  193. package/dist/cli/chunks/{pipeline-QXO4EJP4.js → pipeline-JRBCX2U3.js} +2 -2
  194. package/dist/cli/chunks/{platform-JJEDYCAK.js → platform-TUPMH4ND.js} +2 -2
  195. package/dist/cli/chunks/{plugin-ZEKRM6F7.js → plugin-H757CYQK.js} +2 -2
  196. package/dist/cli/chunks/{prime-radiant-advanced-wasm-GRS4T6LR.js → prime-radiant-advanced-wasm-5BWO25RA.js} +2 -2
  197. package/dist/cli/chunks/protocol-executor-3Q4QY7G6.js +2 -0
  198. package/dist/cli/chunks/{protocol-handler-KWI2T6OR.js → protocol-handler-Z6DCNTUU.js} +2 -2
  199. package/dist/cli/chunks/{prove-7FJN2HEH.js → prove-4OGWFOUM.js} +2 -2
  200. package/dist/cli/chunks/{provider-manager-QYYZZLLO.js → provider-manager-K736L6LN.js} +2 -2
  201. package/dist/cli/chunks/qe-reasoning-bank-SAMJF3NF.js +2 -0
  202. package/dist/cli/chunks/{quality-4NHO2NY5.js → quality-YFLEATGZ.js} +2 -2
  203. package/dist/cli/chunks/queen-coordinator-OFRH67Y2.js +2 -0
  204. package/dist/cli/chunks/{real-embeddings-SIELAOWX.js → real-embeddings-5QUSL7J4.js} +2 -2
  205. package/dist/cli/chunks/{roocode-installer-ANYXH3NR.js → roocode-installer-HDWE5XW3.js} +2 -2
  206. package/dist/cli/chunks/router-UDHEENEY.js +2 -0
  207. package/dist/cli/chunks/routing-feedback-PBZRVFVL.js +2 -0
  208. package/dist/cli/chunks/{routing-handler-6QQHK4KV.js → routing-handler-P6PP3FYW.js} +2 -2
  209. package/dist/cli/chunks/{ruvector-commands-YEUA3MZB.js → ruvector-commands-VNMTRQML.js} +2 -2
  210. package/dist/cli/chunks/{rvf-dual-writer-UJFRHPVE.js → rvf-dual-writer-A7VW5CAT.js} +2 -2
  211. package/dist/cli/chunks/{rvf-migration-adapter-CSDFG7UA.js → rvf-migration-adapter-QIPSNASM.js} +2 -2
  212. package/dist/cli/chunks/{rvf-migration-coordinator-QO7OENQF.js → rvf-migration-coordinator-XT4XDLRZ.js} +2 -2
  213. package/dist/cli/chunks/rvf-native-adapter-CJFEDG74.js +2 -0
  214. package/dist/cli/chunks/safe-db-YMSZFHWP.js +2 -0
  215. package/dist/cli/chunks/schedule-B43N6CVB.js +2 -0
  216. package/dist/cli/chunks/scheduler-ITZH5YQM.js +2 -0
  217. package/dist/cli/chunks/{security-QCIUC5FX.js → security-E2XCP5CG.js} +3 -3
  218. package/dist/cli/chunks/shared-rvf-adapter-PV5ZBJ25.js +2 -0
  219. package/dist/cli/chunks/{shared-rvf-dual-writer-LVJJS3PD.js → shared-rvf-dual-writer-NPWTXHUI.js} +2 -2
  220. package/dist/cli/chunks/sqlite-persistence-RK5CKPHB.js +2 -0
  221. package/dist/cli/chunks/{status-handler-O77A4JWM.js → status-handler-MWVNDZSZ.js} +2 -2
  222. package/dist/cli/chunks/{structural-health-WIIBIIQI.js → structural-health-2KZO43IF.js} +2 -2
  223. package/dist/cli/chunks/{sync-UN6D6OF2.js → sync-C5BOK3WU.js} +2 -2
  224. package/dist/cli/chunks/{task-handler-RBOSMJCK.js → task-handler-KRVSHJGJ.js} +2 -2
  225. package/dist/cli/chunks/{task-handlers-VWMXQKAT.js → task-handlers-CKOHD633.js} +2 -2
  226. package/dist/cli/chunks/{test-XK5M3PGT.js → test-3B7FK6MJ.js} +4 -4
  227. package/dist/cli/chunks/{test-scheduling-CTQ3JJ7G.js → test-scheduling-HZIMSTAX.js} +3 -3
  228. package/dist/cli/chunks/{token-bootstrap-D5CQ3I5M.js → token-bootstrap-JJCANIHJ.js} +2 -2
  229. package/dist/cli/chunks/{token-usage-L4QSLWQ5.js → token-usage-5VCMBZU7.js} +2 -2
  230. package/dist/cli/chunks/{transformers-SRPJDBKA.js → transformers-ETUTMOTF.js} +2 -2
  231. package/dist/cli/chunks/{tree-sitter-wasm-parser-DOU5ITWB.js → tree-sitter-wasm-parser-TMR44BKP.js} +2 -2
  232. package/dist/cli/chunks/{types-LECYZUBN.js → types-GYT6373C.js} +2 -2
  233. package/dist/cli/chunks/unified-memory-LIKELZVA.js +2 -0
  234. package/dist/cli/chunks/unified-memory-hnsw-VTN3MUB4.js +2 -0
  235. package/dist/cli/chunks/unified-persistence-MQVUY5WN.js +2 -0
  236. package/dist/cli/chunks/upgrade-534QLY7P.js +5 -0
  237. package/dist/cli/chunks/{validate-SIKNIS6B.js → validate-UBVF3CSS.js} +2 -2
  238. package/dist/cli/chunks/{validate-swarm-EHAMMILJ.js → validate-swarm-2XD45EVM.js} +2 -2
  239. package/dist/cli/chunks/{vibium-LJ4NYXMZ.js → vibium-NMT6AQ4S.js} +2 -2
  240. package/dist/cli/chunks/visual-security-HVJWGY7T.js +2 -0
  241. package/dist/cli/chunks/{web-tree-sitter-DZQ3T4JD.js → web-tree-sitter-RNG6NRDD.js} +2 -2
  242. package/dist/cli/chunks/{windsurf-installer-U6Z73O6J.js → windsurf-installer-RVCDSJT3.js} +2 -2
  243. package/dist/cli/chunks/witness-chain-5R322YYF.js +2 -0
  244. package/dist/cli/chunks/{witness-chain-JE3QU4YP.js → witness-chain-YDFB22MT.js} +2 -2
  245. package/dist/cli/chunks/{workflow-62QXGZQO.js → workflow-MHW4KHNK.js} +4 -4
  246. package/dist/cli/chunks/workflow-orchestrator-637BCZI4.js +2 -0
  247. package/dist/cli/chunks/{wrappers-CAX5EZSH.js → wrappers-SAZY3C2S.js} +2 -2
  248. package/dist/cli/commands/upgrade.d.ts +96 -0
  249. package/dist/cli/commands/upgrade.js +342 -0
  250. package/dist/cli/completions/index.d.ts +27 -0
  251. package/dist/cli/completions/index.js +112 -14
  252. package/dist/cli/handlers/brain-handler.d.ts +2 -0
  253. package/dist/cli/handlers/brain-handler.js +221 -1
  254. package/dist/cli/index.js +5 -1
  255. package/dist/integrations/ruvector/brain-diff.d.ts +93 -0
  256. package/dist/integrations/ruvector/brain-diff.js +281 -0
  257. package/dist/integrations/ruvector/brain-search.d.ts +78 -0
  258. package/dist/integrations/ruvector/brain-search.js +154 -0
  259. package/dist/mcp/bundle.js +1 -1
  260. package/package.json +1 -1
  261. package/dist/cli/chunks/adapter-P2EPBJLF.js +0 -2
  262. package/dist/cli/chunks/aqe-learning-engine-6UITO3NJ.js +0 -2
  263. package/dist/cli/chunks/base-JHBJXVGP.js +0 -2
  264. package/dist/cli/chunks/brain-handler-ISVST4MR.js +0 -68
  265. package/dist/cli/chunks/browser-workflow-U4OON5DZ.js +0 -2
  266. package/dist/cli/chunks/chunk-FEVTMHO6.js +0 -2
  267. package/dist/cli/chunks/client-UHHMKUPF.js +0 -2
  268. package/dist/cli/chunks/cross-domain-router-GEBXTPZW.js +0 -2
  269. package/dist/cli/chunks/dream-XBRGYPBC.js +0 -2
  270. package/dist/cli/chunks/esm-node-EV4HOHTZ.js +0 -2
  271. package/dist/cli/chunks/hnsw-adapter-BG73YVXI.js +0 -2
  272. package/dist/cli/chunks/hnsw-index-K73ZTLJN.js +0 -2
  273. package/dist/cli/chunks/impact-analyzer-GWIUYYCQ.js +0 -2
  274. package/dist/cli/chunks/init-wizard-RIJJAKE3.js +0 -2
  275. package/dist/cli/chunks/kernel-SIPBCRGL.js +0 -2
  276. package/dist/cli/chunks/knowledge-graph-NOYZXHIG.js +0 -2
  277. package/dist/cli/chunks/load-test-DIMUH75F.js +0 -2
  278. package/dist/cli/chunks/memory-backend-IWOGO4BV.js +0 -2
  279. package/dist/cli/chunks/protocol-executor-NT4TILJW.js +0 -2
  280. package/dist/cli/chunks/qe-reasoning-bank-VDROHXFS.js +0 -2
  281. package/dist/cli/chunks/queen-coordinator-7LO73IV3.js +0 -2
  282. package/dist/cli/chunks/router-SFVOLN2W.js +0 -2
  283. package/dist/cli/chunks/routing-feedback-MRFV7WUZ.js +0 -2
  284. package/dist/cli/chunks/rvf-native-adapter-6L7FZZC7.js +0 -2
  285. package/dist/cli/chunks/safe-db-PYWBVGOV.js +0 -2
  286. package/dist/cli/chunks/schedule-BUQU75HY.js +0 -2
  287. package/dist/cli/chunks/scheduler-XOSKWZO2.js +0 -2
  288. package/dist/cli/chunks/shared-rvf-adapter-OZ7S4ZQL.js +0 -2
  289. package/dist/cli/chunks/sqlite-persistence-7UXQZ5Y6.js +0 -2
  290. package/dist/cli/chunks/unified-memory-L6735TFM.js +0 -2
  291. package/dist/cli/chunks/unified-memory-hnsw-7TZNEDGY.js +0 -2
  292. package/dist/cli/chunks/unified-persistence-FNYZ3C2B.js +0 -2
  293. package/dist/cli/chunks/visual-security-SMPZPDY4.js +0 -2
  294. package/dist/cli/chunks/witness-chain-FNCOTWFA.js +0 -2
  295. package/dist/cli/chunks/workflow-orchestrator-RCR4N7OA.js +0 -2
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import path from 'path';
8
8
  import chalk from 'chalk';
9
- import { exportBrain, importBrain, brainInfo, witnessBackfill, } from '../brain-commands.js';
9
+ import { exportBrain, importBrain, brainInfo, brainDiff, brainSearch, witnessBackfill, } from '../brain-commands.js';
10
10
  // ============================================================================
11
11
  // Brain Handler
12
12
  // ============================================================================
@@ -56,6 +56,32 @@ export class BrainHandler {
56
56
  .action(async (options) => {
57
57
  await this.executeWitnessBackfill(options);
58
58
  });
59
+ brain
60
+ .command('diff')
61
+ .description('Compare two brain exports (JSONL directory or .rvf file)')
62
+ .argument('<a>', 'Path to first brain export')
63
+ .argument('<b>', 'Path to second brain export')
64
+ .option('--table <name>', 'Restrict comparison to a single table')
65
+ .option('--verbose', 'Show the IDs of added/removed/changed records', false)
66
+ .option('--json', 'Emit the diff as JSON to stdout', false)
67
+ .action(async (a, b, options) => {
68
+ await this.executeDiff(a, b, options);
69
+ });
70
+ brain
71
+ .command('search')
72
+ .description('Search a JSONL brain export with filters')
73
+ .requiredOption('-i, --input <path>', 'Path to brain export directory (JSONL)')
74
+ .option('--table <name>', 'Table to search (default: qe_patterns)')
75
+ .option('--domain <name...>', 'Restrict to one or more domains')
76
+ .option('--pattern-type <type>', 'Restrict to a specific pattern_type (qe_patterns only)')
77
+ .option('--since <iso>', 'Include rows with timestamp ≥ <iso>')
78
+ .option('--until <iso>', 'Include rows with timestamp ≤ <iso>')
79
+ .option('-q, --query <text>', 'Substring match across name + description (case-insensitive)')
80
+ .option('-l, --limit <n>', 'Maximum results to return', '20')
81
+ .option('--json', 'Emit results as JSON to stdout', false)
82
+ .action(async (options) => {
83
+ await this.executeSearch(options);
84
+ });
59
85
  }
60
86
  async executeExport(options) {
61
87
  try {
@@ -224,6 +250,51 @@ export class BrainHandler {
224
250
  await this.cleanupAndExit(1);
225
251
  }
226
252
  }
253
+ async executeDiff(a, b, options) {
254
+ try {
255
+ const result = await brainDiff(path.resolve(a), path.resolve(b), {
256
+ tableFilter: options.table,
257
+ });
258
+ if (options.json) {
259
+ process.stdout.write(JSON.stringify(result, null, 2) + '\n');
260
+ await this.cleanupAndExit(result.identical ? 0 : 1);
261
+ return;
262
+ }
263
+ renderDiff(result, options.verbose);
264
+ // Exit code convention: 0 when identical, 1 when differences exist.
265
+ await this.cleanupAndExit(result.identical ? 0 : 1);
266
+ }
267
+ catch (error) {
268
+ console.error(chalk.red('\n Brain diff failed:'), error);
269
+ await this.cleanupAndExit(2);
270
+ }
271
+ }
272
+ async executeSearch(options) {
273
+ try {
274
+ const limit = parseLimit(options.limit);
275
+ const domains = normalizeDomainOption(options.domain);
276
+ const result = await brainSearch(path.resolve(options.input), {
277
+ table: options.table,
278
+ domains,
279
+ patternType: options.patternType,
280
+ since: options.since,
281
+ until: options.until,
282
+ query: options.query,
283
+ limit,
284
+ });
285
+ if (options.json) {
286
+ process.stdout.write(JSON.stringify(result, null, 2) + '\n');
287
+ await this.cleanupAndExit(result.totalMatched > 0 ? 0 : 3);
288
+ return;
289
+ }
290
+ renderSearch(result);
291
+ await this.cleanupAndExit(result.totalMatched > 0 ? 0 : 3);
292
+ }
293
+ catch (error) {
294
+ console.error(chalk.red('\n Brain search failed:'), error);
295
+ await this.cleanupAndExit(2);
296
+ }
297
+ }
227
298
  async executeWitnessBackfill(options) {
228
299
  try {
229
300
  console.log(chalk.blue('\n Running witness chain backfill...\n'));
@@ -258,6 +329,8 @@ Subcommands:
258
329
  export Export brain state to a portable .rvf file or JSONL directory
259
330
  import Import a brain export into the local database
260
331
  info Show manifest metadata for an existing brain export
332
+ diff Compare two brain exports (manifest always; record-level for JSONL)
333
+ search Filtered search over a JSONL brain export
261
334
 
262
335
  Examples:
263
336
  aqe brain export -o .agentic-qe/brain.rvf
@@ -266,6 +339,9 @@ Examples:
266
339
  aqe brain import -i .agentic-qe/brain.rvf --strategy latest-wins
267
340
  aqe brain import -i .agentic-qe/brain.rvf --dry-run
268
341
  aqe brain info -i .agentic-qe/brain.rvf
342
+ aqe brain diff ./brain-a ./brain-b --verbose
343
+ aqe brain search -i ./brain-export --query oauth --domain test-generation
344
+ aqe brain search -i ./brain-export --since 2026-03-01 --limit 50 --json
269
345
  `;
270
346
  }
271
347
  }
@@ -285,6 +361,150 @@ function formatBytes(bytes) {
285
361
  return `${(bytes / 1024).toFixed(1)} KB`;
286
362
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
287
363
  }
364
+ function parseLimit(raw) {
365
+ const n = Number.parseInt(raw, 10);
366
+ if (!Number.isFinite(n) || n < 1)
367
+ return 20;
368
+ return n;
369
+ }
370
+ function normalizeDomainOption(value) {
371
+ if (value === undefined)
372
+ return undefined;
373
+ const arr = Array.isArray(value) ? value : [value];
374
+ const out = [];
375
+ for (const raw of arr) {
376
+ for (const part of raw.split(',')) {
377
+ const trimmed = part.trim();
378
+ if (trimmed)
379
+ out.push(trimmed);
380
+ }
381
+ }
382
+ return out.length > 0 ? out : undefined;
383
+ }
384
+ function renderDiff(result, verbose) {
385
+ console.log(chalk.blue('\n Brain Diff\n'));
386
+ console.log(` A: ${chalk.cyan(result.pathA)} (${result.formatA})`);
387
+ console.log(` B: ${chalk.cyan(result.pathB)} (${result.formatB})`);
388
+ console.log(` Versions: ${chalk.cyan(result.manifestA.version)} → ${chalk.cyan(result.manifestB.version)}` +
389
+ (result.versionMatch ? chalk.gray(' (match)') : chalk.yellow(' (differ)')));
390
+ console.log(` Checksums: ${chalk.gray(result.manifestA.checksum.slice(0, 12))}… → ` +
391
+ `${chalk.gray(result.manifestB.checksum.slice(0, 12))}…` +
392
+ (result.checksumMatch ? chalk.gray(' (match)') : chalk.yellow(' (differ)')));
393
+ console.log(` Exported: ${chalk.gray(result.manifestA.exportedAt)} → ${chalk.gray(result.manifestB.exportedAt)}`);
394
+ console.log(` Records: ${chalk.cyan(result.manifestA.totalRecords)} → ${chalk.cyan(result.manifestB.totalRecords)} ` +
395
+ formatDelta(result.manifestB.totalRecords - result.manifestA.totalRecords));
396
+ if (result.domainsOnlyInA.length > 0 || result.domainsOnlyInB.length > 0) {
397
+ console.log(chalk.blue('\n Domains:'));
398
+ if (result.domainsOnlyInA.length > 0) {
399
+ console.log(` Only in A: ${chalk.yellow(result.domainsOnlyInA.join(', '))}`);
400
+ }
401
+ if (result.domainsOnlyInB.length > 0) {
402
+ console.log(` Only in B: ${chalk.yellow(result.domainsOnlyInB.join(', '))}`);
403
+ }
404
+ }
405
+ if (!result.recordLevel) {
406
+ console.log(chalk.gray('\n Note: record-level diff is only available when both sides are JSONL exports.\n' +
407
+ ' Per-table counts shown below; re-export with --format jsonl for added/removed/changed IDs.'));
408
+ }
409
+ console.log(chalk.blue('\n Tables:'));
410
+ const changed = result.tableDiffs.filter(tableHasChange);
411
+ if (changed.length === 0) {
412
+ console.log(chalk.gray(' (no differences)'));
413
+ }
414
+ else {
415
+ for (const t of changed) {
416
+ console.log(` ${t.tableName.padEnd(28)} ${chalk.cyan(String(t.countA).padStart(7))} → ` +
417
+ `${chalk.cyan(String(t.countB).padStart(7))} ${formatDelta(t.delta)}` +
418
+ formatRecordBuckets(t, verbose));
419
+ if (verbose) {
420
+ if (t.added && t.added.length > 0)
421
+ printIdBucket('added', t.added);
422
+ if (t.removed && t.removed.length > 0)
423
+ printIdBucket('removed', t.removed);
424
+ if (t.changed && t.changed.length > 0)
425
+ printIdBucket('changed', t.changed);
426
+ }
427
+ }
428
+ }
429
+ console.log('');
430
+ if (result.identical) {
431
+ console.log(chalk.green(' Result: identical\n'));
432
+ }
433
+ else {
434
+ console.log(chalk.yellow(' Result: differences found\n'));
435
+ }
436
+ }
437
+ function tableHasChange(t) {
438
+ if (t.delta !== 0)
439
+ return true;
440
+ if (t.added && t.added.length > 0)
441
+ return true;
442
+ if (t.removed && t.removed.length > 0)
443
+ return true;
444
+ if (t.changed && t.changed.length > 0)
445
+ return true;
446
+ return false;
447
+ }
448
+ function formatDelta(delta) {
449
+ if (delta === 0)
450
+ return chalk.gray('(±0)');
451
+ if (delta > 0)
452
+ return chalk.green(`(+${delta})`);
453
+ return chalk.red(`(${delta})`);
454
+ }
455
+ function formatRecordBuckets(t, verbose) {
456
+ const parts = [];
457
+ if (t.added && t.added.length > 0)
458
+ parts.push(chalk.green(`+${t.added.length}`));
459
+ if (t.removed && t.removed.length > 0)
460
+ parts.push(chalk.red(`-${t.removed.length}`));
461
+ if (t.changed && t.changed.length > 0)
462
+ parts.push(chalk.yellow(`~${t.changed.length}`));
463
+ if (parts.length === 0)
464
+ return '';
465
+ if (verbose)
466
+ return ' ' + parts.join(' ');
467
+ return ' ' + chalk.gray('[') + parts.join(' ') + chalk.gray(']');
468
+ }
469
+ function printIdBucket(label, ids) {
470
+ const preview = ids.slice(0, 10).join(', ');
471
+ const suffix = ids.length > 10 ? chalk.gray(` …(+${ids.length - 10} more)`) : '';
472
+ console.log(` ${chalk.gray(label + ':')} ${preview}${suffix}`);
473
+ }
474
+ function renderSearch(result) {
475
+ console.log(chalk.blue('\n Brain Search\n'));
476
+ console.log(` Input: ${chalk.cyan(result.inputPath)}`);
477
+ console.log(` Table: ${chalk.cyan(result.table)}`);
478
+ console.log(` Scanned: ${chalk.cyan(result.totalScanned)} ` +
479
+ `Matched: ${chalk.cyan(result.totalMatched)} ` +
480
+ `Shown: ${chalk.cyan(result.hits.length)}` +
481
+ (result.truncated ? chalk.yellow(` (truncated to limit ${result.limit})`) : ''));
482
+ if (result.hits.length === 0) {
483
+ console.log(chalk.yellow('\n No matching rows.\n'));
484
+ return;
485
+ }
486
+ console.log('');
487
+ for (const hit of result.hits) {
488
+ const header = chalk.cyan(hit.id) +
489
+ (hit.display.patternType ? chalk.gray(` ${hit.display.patternType}`) : '') +
490
+ (hit.display.domain ? chalk.gray(` [${hit.display.domain}]`) : '') +
491
+ (hit.display.confidence !== undefined
492
+ ? chalk.gray(` conf=${hit.display.confidence.toFixed(2)}`)
493
+ : '');
494
+ console.log(` ${header}`);
495
+ if (hit.display.name)
496
+ console.log(` ${chalk.bold(hit.display.name)}`);
497
+ if (hit.display.description) {
498
+ const desc = hit.display.description.length > 200
499
+ ? hit.display.description.slice(0, 200) + '…'
500
+ : hit.display.description;
501
+ console.log(` ${chalk.gray(desc)}`);
502
+ }
503
+ if (hit.display.updatedAt)
504
+ console.log(` ${chalk.gray(hit.display.updatedAt)}`);
505
+ console.log('');
506
+ }
507
+ }
288
508
  // ============================================================================
289
509
  // Factory
290
510
  // ============================================================================
package/dist/cli/index.js CHANGED
@@ -47,7 +47,6 @@ console.log = (...args) => {
47
47
  originalConsoleLog(...args);
48
48
  };
49
49
  // Also redirect timestamped INFO/WARN/ERROR log lines (e.g. "[07:12:24.372] [INFO ]")
50
- const originalConsoleInfo = console.info.bind(console);
51
50
  console.info = (...args) => {
52
51
  process.stderr.write(args.map(String).join(' ') + '\n');
53
52
  };
@@ -249,6 +248,11 @@ registerLazyCommand(program, {
249
248
  description: 'Generate shell completions for aqe',
250
249
  factory: () => import('./commands/completions.js').then(m => m.createCompletionsCommand(cleanupAndExit)),
251
250
  });
251
+ registerLazyCommand(program, {
252
+ name: 'upgrade',
253
+ description: 'Detect optional native bindings and recommend install / flag changes',
254
+ factory: () => import('./commands/upgrade.js').then(m => m.createUpgradeCommand(cleanupAndExit)),
255
+ });
252
256
  registerLazyCommand(program, {
253
257
  name: 'fleet',
254
258
  description: 'Fleet operations with multi-agent progress tracking',
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Brain Export Diff
3
+ *
4
+ * Compares two brain exports (JSONL directory or RVF file) and returns a
5
+ * structured diff.
6
+ *
7
+ * Two levels of comparison:
8
+ * - Manifest-level (always available): version, checksum, per-table record
9
+ * counts, exported_at, domain list delta.
10
+ * - Record-level (JSONL exports only): for each table with a PK, the set of
11
+ * added / removed / changed record IDs. For append-only tables only counts
12
+ * are reported.
13
+ *
14
+ * For RVF exports, record-level diff is not supported by this module (the
15
+ * kernel is opaque without @ruvector/rvf-node). Export as JSONL for full diff.
16
+ */
17
+ import { type TableExportConfig } from './brain-shared.js';
18
+ export type ExportFormat = 'rvf' | 'jsonl';
19
+ export interface ManifestSummary {
20
+ readonly format: ExportFormat;
21
+ readonly version: string;
22
+ readonly exportedAt: string;
23
+ readonly sourceDb: string;
24
+ readonly checksum: string;
25
+ readonly totalRecords: number;
26
+ readonly domains: readonly string[];
27
+ readonly tableRecordCounts: Record<string, number>;
28
+ }
29
+ export interface TableDiff {
30
+ readonly tableName: string;
31
+ readonly countA: number;
32
+ readonly countB: number;
33
+ readonly delta: number;
34
+ /** Only populated for JSONL↔JSONL record-level diffs on PK tables. */
35
+ readonly added?: readonly string[];
36
+ readonly removed?: readonly string[];
37
+ readonly changed?: readonly string[];
38
+ }
39
+ export interface BrainDiffResult {
40
+ readonly pathA: string;
41
+ readonly pathB: string;
42
+ readonly formatA: ExportFormat;
43
+ readonly formatB: ExportFormat;
44
+ readonly manifestA: ManifestSummary;
45
+ readonly manifestB: ManifestSummary;
46
+ readonly checksumMatch: boolean;
47
+ readonly versionMatch: boolean;
48
+ readonly identical: boolean;
49
+ readonly recordLevel: boolean;
50
+ readonly tableDiffs: readonly TableDiff[];
51
+ readonly domainsOnlyInA: readonly string[];
52
+ readonly domainsOnlyInB: readonly string[];
53
+ }
54
+ export interface BrainDiffOptions {
55
+ /** Restrict comparison to a single table (by table name). */
56
+ readonly tableFilter?: string;
57
+ /** Cap on the number of IDs retained per added/removed/changed list. */
58
+ readonly maxIdsPerBucket?: number;
59
+ }
60
+ /**
61
+ * Compute the diff between two brain exports.
62
+ *
63
+ * Both paths may be JSONL directories or `.rvf` files. Record-level diff is
64
+ * only available when both sides are JSONL.
65
+ */
66
+ export declare function diffBrains(pathA: string, pathB: string, options?: BrainDiffOptions): BrainDiffResult;
67
+ declare function pkFor(config: TableExportConfig): string;
68
+ /**
69
+ * Read a JSONL file and build a Map<identity, contentHash>.
70
+ *
71
+ * For PK tables the identity is the PK column value. For append-only tables
72
+ * the identity is a concatenation of the dedup columns (collisions are
73
+ * treated as "same record").
74
+ */
75
+ declare function buildIdentityMap(filePath: string, config: TableExportConfig): Map<string, string>;
76
+ declare function identityOf(row: Record<string, unknown>, config: TableExportConfig): string | undefined;
77
+ declare function stableStringify(obj: Record<string, unknown>): string;
78
+ export interface DiffSummary {
79
+ readonly tablesChanged: number;
80
+ readonly totalAdded: number;
81
+ readonly totalRemoved: number;
82
+ readonly totalChanged: number;
83
+ readonly recordCountDelta: number;
84
+ }
85
+ export declare function summarizeDiff(result: BrainDiffResult): DiffSummary;
86
+ export declare const __test__: {
87
+ stableStringify: typeof stableStringify;
88
+ identityOf: typeof identityOf;
89
+ buildIdentityMap: typeof buildIdentityMap;
90
+ pkFor: typeof pkFor;
91
+ };
92
+ export {};
93
+ //# sourceMappingURL=brain-diff.d.ts.map
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Brain Export Diff
3
+ *
4
+ * Compares two brain exports (JSONL directory or RVF file) and returns a
5
+ * structured diff.
6
+ *
7
+ * Two levels of comparison:
8
+ * - Manifest-level (always available): version, checksum, per-table record
9
+ * counts, exported_at, domain list delta.
10
+ * - Record-level (JSONL exports only): for each table with a PK, the set of
11
+ * added / removed / changed record IDs. For append-only tables only counts
12
+ * are reported.
13
+ *
14
+ * For RVF exports, record-level diff is not supported by this module (the
15
+ * kernel is opaque without @ruvector/rvf-node). Export as JSONL for full diff.
16
+ */
17
+ import { existsSync, readFileSync, statSync } from 'fs';
18
+ import { join, resolve } from 'path';
19
+ import { safeJsonParse } from '../../shared/safe-json.js';
20
+ import { brainInfoFromRvf } from './brain-rvf-exporter.js';
21
+ import { readJsonl, sha256, TABLE_CONFIGS, PK_COLUMNS, } from './brain-shared.js';
22
+ // ============================================================================
23
+ // Public API
24
+ // ============================================================================
25
+ /**
26
+ * Compute the diff between two brain exports.
27
+ *
28
+ * Both paths may be JSONL directories or `.rvf` files. Record-level diff is
29
+ * only available when both sides are JSONL.
30
+ */
31
+ export function diffBrains(pathA, pathB, options = {}) {
32
+ const resolvedA = resolve(pathA);
33
+ const resolvedB = resolve(pathB);
34
+ const formatA = detectFormat(resolvedA);
35
+ const formatB = detectFormat(resolvedB);
36
+ const manifestA = readManifestSummary(resolvedA, formatA);
37
+ const manifestB = readManifestSummary(resolvedB, formatB);
38
+ const recordLevel = formatA === 'jsonl' && formatB === 'jsonl';
39
+ const tableDiffs = computeTableDiffs({
40
+ pathA: resolvedA,
41
+ pathB: resolvedB,
42
+ manifestA,
43
+ manifestB,
44
+ recordLevel,
45
+ tableFilter: options.tableFilter,
46
+ maxIdsPerBucket: options.maxIdsPerBucket ?? 500,
47
+ });
48
+ const domainsA = new Set(manifestA.domains);
49
+ const domainsB = new Set(manifestB.domains);
50
+ const domainsOnlyInA = manifestA.domains.filter((d) => !domainsB.has(d));
51
+ const domainsOnlyInB = manifestB.domains.filter((d) => !domainsA.has(d));
52
+ const checksumMatch = manifestA.checksum === manifestB.checksum;
53
+ const versionMatch = manifestA.version === manifestB.version;
54
+ const identical = checksumMatch &&
55
+ versionMatch &&
56
+ tableDiffs.every((t) => t.delta === 0 &&
57
+ (t.added?.length ?? 0) === 0 &&
58
+ (t.removed?.length ?? 0) === 0 &&
59
+ (t.changed?.length ?? 0) === 0);
60
+ return {
61
+ pathA: resolvedA,
62
+ pathB: resolvedB,
63
+ formatA,
64
+ formatB,
65
+ manifestA,
66
+ manifestB,
67
+ checksumMatch,
68
+ versionMatch,
69
+ identical,
70
+ recordLevel,
71
+ tableDiffs,
72
+ domainsOnlyInA,
73
+ domainsOnlyInB,
74
+ };
75
+ }
76
+ // ============================================================================
77
+ // Format detection + manifest reading
78
+ // ============================================================================
79
+ function detectFormat(path) {
80
+ if (!existsSync(path)) {
81
+ throw new Error(`Path not found: ${path}`);
82
+ }
83
+ if (path.endsWith('.rvf'))
84
+ return 'rvf';
85
+ const s = statSync(path);
86
+ if (s.isFile()) {
87
+ // Any single file that isn't .rvf is treated as an error — JSONL exports
88
+ // are directories.
89
+ throw new Error(`Unsupported brain export: ${path} (expected a .rvf file or a JSONL directory)`);
90
+ }
91
+ // Directory: assume JSONL
92
+ return 'jsonl';
93
+ }
94
+ function readManifestSummary(path, format) {
95
+ if (format === 'rvf') {
96
+ return readRvfManifestSummary(path);
97
+ }
98
+ return readJsonlManifestSummary(path);
99
+ }
100
+ function readJsonlManifestSummary(dir) {
101
+ const manifestPath = join(dir, 'manifest.json');
102
+ if (!existsSync(manifestPath)) {
103
+ throw new Error(`Manifest not found at ${manifestPath}`);
104
+ }
105
+ const raw = safeJsonParse(readFileSync(manifestPath, 'utf-8'));
106
+ return toManifestSummary(raw, 'jsonl');
107
+ }
108
+ function readRvfManifestSummary(rvfPath) {
109
+ // Delegate to the RVF exporter's info path so we honour its format handling.
110
+ const raw = brainInfoFromRvf(rvfPath);
111
+ return toManifestSummary(raw, 'rvf');
112
+ }
113
+ function toManifestSummary(raw, format) {
114
+ return {
115
+ format,
116
+ version: raw.version ?? 'unknown',
117
+ exportedAt: raw.exportedAt ?? 'unknown',
118
+ sourceDb: raw.sourceDb ?? 'unknown',
119
+ checksum: raw.checksum ?? '',
120
+ totalRecords: raw.stats?.totalRecords ?? 0,
121
+ domains: raw.domains ?? [],
122
+ tableRecordCounts: raw.tableRecordCounts ?? {},
123
+ };
124
+ }
125
+ function computeTableDiffs(input) {
126
+ const configs = input.tableFilter
127
+ ? TABLE_CONFIGS.filter((c) => c.tableName === input.tableFilter)
128
+ : TABLE_CONFIGS;
129
+ if (input.tableFilter && configs.length === 0) {
130
+ throw new Error(`Unknown table: ${input.tableFilter}`);
131
+ }
132
+ const diffs = [];
133
+ for (const config of configs) {
134
+ const countA = input.manifestA.tableRecordCounts[config.tableName] ?? 0;
135
+ const countB = input.manifestB.tableRecordCounts[config.tableName] ?? 0;
136
+ const delta = countB - countA;
137
+ let added;
138
+ let removed;
139
+ let changed;
140
+ if (input.recordLevel && hasIdentity(config)) {
141
+ const recordDiff = recordLevelDiff(join(input.pathA, config.fileName), join(input.pathB, config.fileName), config, input.maxIdsPerBucket);
142
+ added = recordDiff.added;
143
+ removed = recordDiff.removed;
144
+ changed = recordDiff.changed;
145
+ }
146
+ diffs.push({
147
+ tableName: config.tableName,
148
+ countA,
149
+ countB,
150
+ delta,
151
+ ...(added !== undefined ? { added } : {}),
152
+ ...(removed !== undefined ? { removed } : {}),
153
+ ...(changed !== undefined ? { changed } : {}),
154
+ });
155
+ }
156
+ return diffs;
157
+ }
158
+ function hasIdentity(_config) {
159
+ // PK tables always have identity; append-only tables can be deduped via
160
+ // their dedup columns, which is good enough to compute added/removed.
161
+ return true;
162
+ }
163
+ function pkFor(config) {
164
+ if (config.dedupColumns && config.dedupColumns.length > 0) {
165
+ // Composite identity — joined with a separator unlikely to occur in values.
166
+ return config.dedupColumns.join('');
167
+ }
168
+ return PK_COLUMNS[config.tableName] ?? 'id';
169
+ }
170
+ function recordLevelDiff(fileA, fileB, config, maxIdsPerBucket) {
171
+ const mapA = buildIdentityMap(fileA, config);
172
+ const mapB = buildIdentityMap(fileB, config);
173
+ const added = [];
174
+ const removed = [];
175
+ const changed = [];
176
+ // In A but not in B → removed.
177
+ for (const [id, hashA] of mapA) {
178
+ const hashB = mapB.get(id);
179
+ if (hashB === undefined) {
180
+ if (removed.length < maxIdsPerBucket)
181
+ removed.push(id);
182
+ }
183
+ else if (hashB !== hashA) {
184
+ // Append-only tables use dedup columns as identity, so if the identity
185
+ // matches the record IS the same — guard via dedup flag.
186
+ if (config.dedupColumns && config.dedupColumns.length > 0)
187
+ continue;
188
+ if (changed.length < maxIdsPerBucket)
189
+ changed.push(id);
190
+ }
191
+ }
192
+ // In B but not in A → added.
193
+ for (const id of mapB.keys()) {
194
+ if (!mapA.has(id)) {
195
+ if (added.length < maxIdsPerBucket)
196
+ added.push(id);
197
+ }
198
+ }
199
+ added.sort();
200
+ removed.sort();
201
+ changed.sort();
202
+ return { added, removed, changed };
203
+ }
204
+ /**
205
+ * Read a JSONL file and build a Map<identity, contentHash>.
206
+ *
207
+ * For PK tables the identity is the PK column value. For append-only tables
208
+ * the identity is a concatenation of the dedup columns (collisions are
209
+ * treated as "same record").
210
+ */
211
+ function buildIdentityMap(filePath, config) {
212
+ const map = new Map();
213
+ if (!existsSync(filePath))
214
+ return map;
215
+ const rows = readJsonl(filePath, safeJsonParse);
216
+ for (const row of rows) {
217
+ const id = identityOf(row, config);
218
+ if (id === undefined)
219
+ continue;
220
+ // Stable content hash: JSON-stringify with sorted keys.
221
+ const content = stableStringify(row);
222
+ map.set(id, sha256Hex(content));
223
+ }
224
+ return map;
225
+ }
226
+ function identityOf(row, config) {
227
+ if (config.dedupColumns && config.dedupColumns.length > 0) {
228
+ const parts = [];
229
+ for (const col of config.dedupColumns) {
230
+ const v = row[col];
231
+ if (v === undefined || v === null)
232
+ return undefined;
233
+ parts.push(String(v));
234
+ }
235
+ return parts.join('');
236
+ }
237
+ const pk = PK_COLUMNS[config.tableName] ?? 'id';
238
+ const v = row[pk];
239
+ if (v === undefined || v === null)
240
+ return undefined;
241
+ return String(v);
242
+ }
243
+ function stableStringify(obj) {
244
+ const keys = Object.keys(obj).sort();
245
+ const ordered = {};
246
+ for (const k of keys)
247
+ ordered[k] = obj[k];
248
+ return JSON.stringify(ordered);
249
+ }
250
+ function sha256Hex(s) {
251
+ // sha256() from brain-shared operates on utf-8 strings; both paths yield the
252
+ // same hash for the same input. Kept as a thin wrapper for readability.
253
+ return sha256(s);
254
+ }
255
+ export function summarizeDiff(result) {
256
+ let tablesChanged = 0;
257
+ let totalAdded = 0;
258
+ let totalRemoved = 0;
259
+ let totalChanged = 0;
260
+ for (const t of result.tableDiffs) {
261
+ const hasChange = t.delta !== 0 ||
262
+ (t.added && t.added.length > 0) ||
263
+ (t.removed && t.removed.length > 0) ||
264
+ (t.changed && t.changed.length > 0);
265
+ if (hasChange)
266
+ tablesChanged++;
267
+ totalAdded += t.added?.length ?? 0;
268
+ totalRemoved += t.removed?.length ?? 0;
269
+ totalChanged += t.changed?.length ?? 0;
270
+ }
271
+ return {
272
+ tablesChanged,
273
+ totalAdded,
274
+ totalRemoved,
275
+ totalChanged,
276
+ recordCountDelta: result.manifestB.totalRecords - result.manifestA.totalRecords,
277
+ };
278
+ }
279
+ // Export internal helpers for test access without widening the public API.
280
+ export const __test__ = { stableStringify, identityOf, buildIdentityMap, pkFor };
281
+ //# sourceMappingURL=brain-diff.js.map