agentic-qe 3.9.15 → 3.9.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +37 -0
- package/assets/skills/skills-manifest.json +1 -1
- package/dist/cli/brain-commands.d.ts +14 -0
- package/dist/cli/brain-commands.js +24 -0
- package/dist/cli/bundle.js +7 -7
- package/dist/cli/chunks/adapter-2BIT6BGH.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-NA2VN5U2.js → agent-booster-wasm-JN7W7O5X.js} +2 -2
- package/dist/cli/chunks/{agent-handler-NRIF5IOC.js → agent-handler-F6Q75SJQ.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-NW3UB2UW.js → agent-memory-branch-3GGTDVR4.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-B5G3RG4W.js +2 -0
- package/dist/cli/chunks/{audit-5CSEDVJR.js → audit-R7KN45HM.js} +2 -2
- package/dist/cli/chunks/base-A3ZRMSIZ.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-FZ32SHZ6.js → better-sqlite3-2LTGEMYR.js} +2 -2
- package/dist/cli/chunks/brain-handler-PML5L6WQ.js +89 -0
- package/dist/cli/chunks/{branch-enumerator-IUHWHIMV.js → branch-enumerator-OKUPS2XC.js} +2 -2
- package/dist/cli/chunks/{browser-D4F3327X.js → browser-KOQOTSAT.js} +2 -2
- package/dist/cli/chunks/browser-workflow-C6Z53ZH6.js +2 -0
- package/dist/cli/chunks/chunk-2ARCG4XJ.js +2 -0
- package/dist/cli/chunks/{chunk-WI6UA5HV.js → chunk-2K7GRX5U.js} +2 -2
- package/dist/cli/chunks/{chunk-DATFN5DG.js → chunk-2LXXYKAP.js} +2 -2
- package/dist/cli/chunks/{chunk-O6J7MKRV.js → chunk-32FWC6G3.js} +2 -2
- package/dist/cli/chunks/{chunk-NL2PQLRD.js → chunk-3GYAIW2P.js} +2 -2
- package/dist/cli/chunks/{chunk-KJTXY3DW.js → chunk-3KIUCAVI.js} +1 -1
- package/dist/cli/chunks/{chunk-37ZSWRRP.js → chunk-3UGV2XWF.js} +2 -2
- package/dist/cli/chunks/{chunk-2CN2NPJQ.js → chunk-42HSEBOH.js} +2 -2
- package/dist/cli/chunks/{chunk-RODJK6G6.js → chunk-42TUEMH7.js} +1 -1
- package/dist/cli/chunks/{chunk-HPY7HGVQ.js → chunk-4TDIA2EN.js} +2 -2
- package/dist/cli/chunks/{chunk-N2RPLPVG.js → chunk-5J444NJR.js} +2 -2
- package/dist/cli/chunks/{chunk-B4BOOOYM.js → chunk-63ERVKIO.js} +1 -1
- package/dist/cli/chunks/{chunk-O6CHLZYT.js → chunk-63V33NAB.js} +2 -2
- package/dist/cli/chunks/{chunk-XALB3KRR.js → chunk-65Z6HMDA.js} +2 -2
- package/dist/cli/chunks/{chunk-62MVVEGH.js → chunk-6F6BNLVP.js} +1 -1
- package/dist/cli/chunks/{chunk-R4G64UH3.js → chunk-6HGRJPD6.js} +1 -1
- package/dist/cli/chunks/{chunk-GWUO3RY5.js → chunk-6MRUG5G2.js} +1 -1
- package/dist/cli/chunks/{chunk-3Y4YZDHJ.js → chunk-6PCGUJCG.js} +4 -4
- package/dist/cli/chunks/{chunk-BGUCXJEJ.js → chunk-6PRIY3HT.js} +2 -2
- package/dist/cli/chunks/{chunk-U4WDJPRL.js → chunk-6YCZDIGF.js} +2 -2
- package/dist/cli/chunks/{chunk-2XW36KDQ.js → chunk-6YFEWIL5.js} +2 -2
- package/dist/cli/chunks/{chunk-W4PUKTBF.js → chunk-7PWW2OXP.js} +1 -1
- package/dist/cli/chunks/{chunk-TZWCVGG2.js → chunk-7VGZDTY4.js} +1 -1
- package/dist/cli/chunks/{chunk-ORKGVVXK.js → chunk-A3WC5KTG.js} +1 -1
- package/dist/cli/chunks/{chunk-FSOY2XB4.js → chunk-A67FRRPJ.js} +3 -3
- package/dist/cli/chunks/{chunk-V775NJOM.js → chunk-AFLTMVMT.js} +1 -1
- package/dist/cli/chunks/{chunk-REUGPZIA.js → chunk-APWO3FI3.js} +1 -1
- package/dist/cli/chunks/{chunk-MS6T4VCU.js → chunk-ARN2KDLJ.js} +2 -2
- package/dist/cli/chunks/{chunk-OBZMQFWG.js → chunk-AZQ476BM.js} +2 -2
- package/dist/cli/chunks/{chunk-IPTGPCEL.js → chunk-AZWCJFT6.js} +2 -2
- package/dist/cli/chunks/{chunk-LLVS3UYZ.js → chunk-B36RPXAQ.js} +2 -2
- package/dist/cli/chunks/{chunk-YCYFUYCE.js → chunk-B3M3JEFD.js} +2 -2
- package/dist/cli/chunks/{chunk-TJDAXI6E.js → chunk-BCBC3DVN.js} +2 -2
- package/dist/cli/chunks/{chunk-Q3GDSFGA.js → chunk-BCIEQ4IP.js} +2 -2
- package/dist/cli/chunks/{chunk-OMTYOIOS.js → chunk-BGY4CHZA.js} +2 -2
- package/dist/cli/chunks/{chunk-7J5KWUC2.js → chunk-BUWZOMC7.js} +1 -1
- package/dist/cli/chunks/{chunk-V6QARSVQ.js → chunk-CPZUNBSQ.js} +2 -2
- package/dist/cli/chunks/{chunk-UZOFXYNC.js → chunk-CQSU7NTG.js} +2 -2
- package/dist/cli/chunks/{chunk-VBEVZUQW.js → chunk-CY73RJJJ.js} +1 -1
- package/dist/cli/chunks/{chunk-DYQ7HTEU.js → chunk-CZXV3JAF.js} +3 -3
- package/dist/cli/chunks/{chunk-6F3H2C5H.js → chunk-DDJUVCKF.js} +3 -3
- package/dist/cli/chunks/{chunk-JJDHD7SC.js → chunk-DJXYFFGA.js} +2 -2
- package/dist/cli/chunks/{chunk-AVKUFN3C.js → chunk-DR6SJ6P3.js} +2 -2
- package/dist/cli/chunks/{chunk-HJNFBJT5.js → chunk-DVEQOD74.js} +8 -8
- package/dist/cli/chunks/{chunk-3RSPEFU3.js → chunk-EGBRCXYT.js} +2 -2
- package/dist/cli/chunks/{chunk-AE65B2ZE.js → chunk-EVQYUUQ3.js} +2 -2
- package/dist/cli/chunks/{chunk-6OEGZSRK.js → chunk-F5X3U57Y.js} +2 -2
- package/dist/cli/chunks/{chunk-CF3W34BA.js → chunk-FCWB2FJG.js} +1 -1
- package/dist/cli/chunks/{chunk-WAQ3U4FC.js → chunk-FVVZWNLV.js} +1 -1
- package/dist/cli/chunks/{chunk-6BHAGCZD.js → chunk-FYNDV2NZ.js} +1 -1
- package/dist/cli/chunks/{chunk-SXUX6PTE.js → chunk-G3G5QEHL.js} +1 -1
- package/dist/cli/chunks/{chunk-6Z7LYE2B.js → chunk-G5DEPXD4.js} +2 -2
- package/dist/cli/chunks/{chunk-SSQ42GI7.js → chunk-HMT6LKHH.js} +2 -2
- package/dist/cli/chunks/{chunk-MO4Q5ZGE.js → chunk-HQXRCW7Z.js} +2 -2
- package/dist/cli/chunks/{chunk-PSOIVDD2.js → chunk-I3NUJ6KJ.js} +3 -3
- package/dist/cli/chunks/{chunk-JQRR37YY.js → chunk-I5BLJ2QQ.js} +2 -2
- package/dist/cli/chunks/{chunk-II5KTTIS.js → chunk-I64R2D4U.js} +4 -4
- package/dist/cli/chunks/{chunk-G3FUOFXA.js → chunk-JC4O47QG.js} +2 -2
- package/dist/cli/chunks/{chunk-DPEG44BS.js → chunk-JT2KLBDB.js} +2 -2
- package/dist/cli/chunks/{chunk-OHESV6I3.js → chunk-JVDYHVF2.js} +4 -4
- package/dist/cli/chunks/{chunk-D3ZUSXFY.js → chunk-K44EQV74.js} +2 -2
- package/dist/cli/chunks/{chunk-HNAQNAGI.js → chunk-K4FG3CRS.js} +3 -3
- package/dist/cli/chunks/{chunk-ISNXE6TP.js → chunk-KTJWRVFR.js} +2 -2
- package/dist/cli/chunks/{chunk-VDDQSW4L.js → chunk-KTUSZRS3.js} +2 -2
- package/dist/cli/chunks/{chunk-7ZPNQ3T6.js → chunk-KUEG6K4A.js} +1 -1
- package/dist/cli/chunks/{chunk-CWWUBZNX.js → chunk-L5JZIORJ.js} +2 -2
- package/dist/cli/chunks/{chunk-HWK27KJK.js → chunk-L6ZJSFAA.js} +1 -1
- package/dist/cli/chunks/{chunk-JAIIPEE6.js → chunk-LA565BGJ.js} +2 -2
- package/dist/cli/chunks/{chunk-WCOJGDGO.js → chunk-LD4OYOX2.js} +2 -2
- package/dist/cli/chunks/{chunk-2BBKAX7X.js → chunk-MER7IHAZ.js} +2 -2
- package/dist/cli/chunks/{chunk-4T36OQUK.js → chunk-MNSF47HC.js} +3 -3
- package/dist/cli/chunks/{chunk-H6DAP4KS.js → chunk-MPEQXXXR.js} +2 -2
- package/dist/cli/chunks/{chunk-2L5ZFBHP.js → chunk-N64PBOR5.js} +2 -2
- package/dist/cli/chunks/{chunk-6TOUMCSE.js → chunk-ORNWQXEX.js} +2 -2
- package/dist/cli/chunks/{chunk-ZOAPOVYW.js → chunk-OSBJWQZL.js} +2 -2
- package/dist/cli/chunks/{chunk-GLJ6CJNY.js → chunk-OUSQ4KQN.js} +2 -2
- package/dist/cli/chunks/{chunk-RWVFOXYM.js → chunk-P2V5ZG3Q.js} +1 -1
- package/dist/cli/chunks/{chunk-6AMD4PZB.js → chunk-PEHHOJE6.js} +2 -2
- package/dist/cli/chunks/{chunk-IHDW4HW7.js → chunk-PGTMLW5K.js} +2 -2
- package/dist/cli/chunks/{chunk-NWMYV7KG.js → chunk-PJZHNAUT.js} +2 -2
- package/dist/cli/chunks/{chunk-E3EDVRB5.js → chunk-PMH52K5J.js} +1 -1
- package/dist/cli/chunks/{chunk-EY2DGYQX.js → chunk-PMNZN4K7.js} +1 -1
- package/dist/cli/chunks/{chunk-56YHSI6R.js → chunk-PV6WBC2D.js} +2 -2
- package/dist/cli/chunks/{chunk-RTVD7SZQ.js → chunk-QFFSQWXP.js} +1 -1
- package/dist/cli/chunks/{chunk-Q3E6Z2RQ.js → chunk-QMVGGG4B.js} +1 -1
- package/dist/cli/chunks/{chunk-3BA2FGSA.js → chunk-QVJQXRHU.js} +2 -2
- package/dist/cli/chunks/{chunk-GHEO5YVA.js → chunk-QW554DTP.js} +1 -1
- package/dist/cli/chunks/{chunk-XXRDI53H.js → chunk-QXOAFWWK.js} +2 -2
- package/dist/cli/chunks/{chunk-V65DK6ZZ.js → chunk-QYDBV5MD.js} +1 -1
- package/dist/cli/chunks/{chunk-ELLNKP3I.js → chunk-R3COBKOP.js} +3 -3
- package/dist/cli/chunks/{chunk-ZHTCZGML.js → chunk-RP2RHB7H.js} +2 -2
- package/dist/cli/chunks/{chunk-EORSYD66.js → chunk-RYATPB5L.js} +2 -2
- package/dist/cli/chunks/{chunk-ESQSX37W.js → chunk-TATCL3AK.js} +2 -2
- package/dist/cli/chunks/{chunk-IPVKVPAF.js → chunk-USORP6QK.js} +2 -2
- package/dist/cli/chunks/{chunk-FW6QBTPE.js → chunk-UTO2M76W.js} +1 -1
- package/dist/cli/chunks/{chunk-D32YCVCA.js → chunk-V3VJNWOF.js} +2 -2
- package/dist/cli/chunks/{chunk-KKBSX43Q.js → chunk-V4DMYY6P.js} +2 -2
- package/dist/cli/chunks/{chunk-3NIHJIWP.js → chunk-VI2I5R6C.js} +2 -2
- package/dist/cli/chunks/{chunk-QNLZKD7E.js → chunk-VX6XHAG2.js} +2 -2
- package/dist/cli/chunks/{chunk-LNUWNRRJ.js → chunk-VYCFMW64.js} +9 -9
- package/dist/cli/chunks/{chunk-CSB2M7IX.js → chunk-W5HTZ3VZ.js} +2 -2
- package/dist/cli/chunks/{chunk-ZSC7NHK3.js → chunk-WGEJ646F.js} +2 -2
- package/dist/cli/chunks/{chunk-ICXWXO5P.js → chunk-WP55YBB2.js} +1 -1
- package/dist/cli/chunks/{chunk-MHL6CPGY.js → chunk-X66N7E7D.js} +1 -1
- package/dist/cli/chunks/{chunk-CUQBOVRP.js → chunk-XB4JRJU4.js} +1 -1
- package/dist/cli/chunks/{chunk-3FUKJT4S.js → chunk-XMMKAV5R.js} +2 -2
- package/dist/cli/chunks/{chunk-RPOW5LWO.js → chunk-XZOJWFLH.js} +1 -1
- package/dist/cli/chunks/{chunk-OUP2X3LT.js → chunk-Y47U7ICT.js} +1 -1
- package/dist/cli/chunks/{chunk-IMLH32AG.js → chunk-YE5AYBHX.js} +2 -2
- package/dist/cli/chunks/{chunk-D3FV5NNA.js → chunk-YUCMGFHE.js} +2 -2
- package/dist/cli/chunks/chunk-Z5R46W6Q.js +2 -0
- package/dist/cli/chunks/{chunk-4M7RBSW6.js → chunk-Z77BVREU.js} +2 -2
- package/dist/cli/chunks/{chunk-C5BRTU4V.js → chunk-ZI3UBCIN.js} +1 -1
- package/dist/cli/chunks/{chunk-65QA7MYW.js → chunk-ZLOMFM25.js} +2 -2
- package/dist/cli/chunks/{chunk-RSOOENGE.js → chunk-ZQKNVZPD.js} +2 -2
- package/dist/cli/chunks/{ci-BGUUHDUS.js → ci-TRWQ33L2.js} +2 -2
- package/dist/cli/chunks/{ci-output-CDFRGBNU.js → ci-output-TCFNHOTU.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-S3NFX6RQ.js → circuit-breaker-GO2TIL7E.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-AJIPJFMC.js → claude-flow-setup-U77JVSVU.js} +2 -2
- package/dist/cli/chunks/client-B3QSCZSJ.js +2 -0
- package/dist/cli/chunks/{cline-installer-6O4KZ5UH.js → cline-installer-XFD3SMGS.js} +2 -2
- package/dist/cli/chunks/{code-IZALXUL5.js → code-V3VE2TMW.js} +2 -2
- package/dist/cli/chunks/{code-index-extractor-N7VDH4XF.js → code-index-extractor-C6DHOOWA.js} +2 -2
- package/dist/cli/chunks/{codex-installer-35GTWCFJ.js → codex-installer-IUR7MVE6.js} +2 -2
- package/dist/cli/chunks/{completions-XPJFHGG2.js → completions-R7FZHNJJ.js} +91 -10
- package/dist/cli/chunks/{complexity-analyzer-DNLCJGUJ.js → complexity-analyzer-EP4QF5CS.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-PXAIKNYO.js → continuedev-installer-6DW2SBMQ.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-2TQ5IZNY.js → copilot-installer-U3UOX7D5.js} +2 -2
- package/dist/cli/chunks/{cost-tracker-A5XH4W6S.js → cost-tracker-5QZ5A46I.js} +2 -2
- package/dist/cli/chunks/{coverage-EPIMXTLW.js → coverage-QOOOITLD.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-OYBTXKCV.js +2 -0
- package/dist/cli/chunks/{cursor-installer-WMMRPW44.js → cursor-installer-SY3TRE2I.js} +2 -2
- package/dist/cli/chunks/{daemon-55DSODOH.js → daemon-HBSBIPUZ.js} +3 -3
- package/dist/cli/chunks/{dag-attention-scheduler-5DSWXMMK.js → dag-attention-scheduler-ZNLUW2HL.js} +2 -2
- package/dist/cli/chunks/{detect-NOS46AWN.js → detect-DMUJPGNC.js} +2 -2
- package/dist/cli/chunks/dist-node-4RPPRXUH.js +2 -0
- package/dist/cli/chunks/{domain-handler-BFRNU6S3.js → domain-handler-XJFDML77.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-BPSA4HFR.js → domain-transfer-MXPKJ2A2.js} +2 -2
- package/dist/cli/chunks/dream-R2F6L47W.js +2 -0
- package/dist/cli/chunks/{eval-YDLM23FB.js → eval-DHBZ74RL.js} +2 -2
- package/dist/cli/chunks/{fast-paths-GISZ7HBO.js → fast-paths-WTNFCV2I.js} +2 -2
- package/dist/cli/chunks/{feature-flags-3FLJF6CQ.js → feature-flags-264QUQ3E.js} +2 -2
- package/dist/cli/chunks/{feature-flags-5WGZLUPQ.js → feature-flags-VC7BQNHU.js} +2 -2
- package/dist/cli/chunks/{file-discovery-PPHUMFSI.js → file-discovery-LXQPIRKG.js} +2 -2
- package/dist/cli/chunks/{fleet-LHFZ53FS.js → fleet-4OAZWNXG.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-Z45DRWGI.js → gnn-wrapper-MAXAOMTP.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-VMLJ5PDH.js → heartbeat-handler-ZTUI75EB.js} +4 -4
- package/dist/cli/chunks/{heartbeat-scheduler-GUWYDHEY.js → heartbeat-scheduler-VWPA7XKA.js} +2 -2
- package/dist/cli/chunks/hnsw-adapter-TQPQE4OJ.js +2 -0
- package/dist/cli/chunks/hnsw-index-2X3NMTDU.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-S7UZWDUP.js → hnsw-legacy-bridge-EQDYPKGL.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-MIAAS7OI.js → hnswlib-node-G4QGTGIB.js} +2 -2
- package/dist/cli/chunks/hooks-RBVHAPBL.js +101 -0
- package/dist/cli/chunks/{hybrid-router-Y6LBFPL7.js → hybrid-router-XODWORQ3.js} +2 -2
- package/dist/cli/chunks/{hypergraph-engine-KK73LZYZ.js → hypergraph-engine-T73DH7N6.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-OBGDPIWG.js → hypergraph-handler-OZJJJW5B.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-B7GBDSA3.js +2 -0
- package/dist/cli/chunks/{init-handler-JJJ7VHM4.js → init-handler-YXXNCXM4.js} +6 -6
- package/dist/cli/chunks/init-wizard-7N6MCER4.js +2 -0
- package/dist/cli/chunks/kernel-6CJ4FP5Z.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-EF6DPX2D.js → kilocode-installer-3RCK2JPW.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-SG74CEVO.js → kiro-installer-LKC42QRS.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-4XYLO6ZW.js +2 -0
- package/dist/cli/chunks/{learning-LVWYMHF6.js → learning-BIBRKCYL.js} +3 -3
- package/dist/cli/chunks/{llm-router-QFK7MNPY.js → llm-router-Z6Z7TTBI.js} +4 -4
- package/dist/cli/chunks/{load-6XPV4WA2.js → load-T2QUB663.js} +2 -2
- package/dist/cli/chunks/load-test-UODCPBYF.js +2 -0
- package/dist/cli/chunks/{mcp-GZXOPYMH.js → mcp-QBOL6TK4.js} +2 -2
- package/dist/cli/chunks/{memory-QTE2Z5HU.js → memory-7RQ2SF36.js} +5 -5
- package/dist/cli/chunks/memory-backend-PUPAE4QQ.js +2 -0
- package/dist/cli/chunks/{memory-handlers-PC4P4YEF.js → memory-handlers-5OHDUBJS.js} +2 -2
- package/dist/cli/chunks/{multi-model-executor-FZOPSUOT.js → multi-model-executor-PGSNT3NO.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-CITDTCUQ.js → opencode-installer-AEOXTTFG.js} +2 -2
- package/dist/cli/chunks/{orchestrator-ZTG7MFHQ.js → orchestrator-6K2L36JA.js} +6 -6
- package/dist/cli/chunks/{pipeline-QXO4EJP4.js → pipeline-MFQCW7JD.js} +2 -2
- package/dist/cli/chunks/{platform-JJEDYCAK.js → platform-DM6RQ3FM.js} +2 -2
- package/dist/cli/chunks/{plugin-ZEKRM6F7.js → plugin-CCTGDC55.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-GRS4T6LR.js → prime-radiant-advanced-wasm-J4FXB63L.js} +2 -2
- package/dist/cli/chunks/protocol-executor-X3EYJINP.js +2 -0
- package/dist/cli/chunks/{protocol-handler-KWI2T6OR.js → protocol-handler-7UOBNLET.js} +2 -2
- package/dist/cli/chunks/{prove-7FJN2HEH.js → prove-VAPGITFF.js} +2 -2
- package/dist/cli/chunks/{provider-manager-QYYZZLLO.js → provider-manager-F6TLUJFW.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-3RDWPSYG.js +2 -0
- package/dist/cli/chunks/{quality-4NHO2NY5.js → quality-7LJQI3SB.js} +2 -2
- package/dist/cli/chunks/queen-coordinator-XIQZIYAZ.js +2 -0
- package/dist/cli/chunks/{real-embeddings-SIELAOWX.js → real-embeddings-NHWAUSV3.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-ANYXH3NR.js → roocode-installer-HQFQJJPU.js} +2 -2
- package/dist/cli/chunks/router-AFEFPU2A.js +2 -0
- package/dist/cli/chunks/routing-feedback-AGYMQFMV.js +2 -0
- package/dist/cli/chunks/{routing-handler-6QQHK4KV.js → routing-handler-VH66WSPU.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-YEUA3MZB.js → ruvector-commands-IPUWLJFU.js} +2 -2
- package/dist/cli/chunks/{rvf-dual-writer-UJFRHPVE.js → rvf-dual-writer-KRFEM6JH.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-adapter-CSDFG7UA.js → rvf-migration-adapter-SVCZ72IU.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-coordinator-QO7OENQF.js → rvf-migration-coordinator-FYBIF3SX.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-AFOWXCZH.js +2 -0
- package/dist/cli/chunks/safe-db-NNF5DE5T.js +2 -0
- package/dist/cli/chunks/schedule-HJUZSHEA.js +2 -0
- package/dist/cli/chunks/scheduler-DZ53RPJQ.js +2 -0
- package/dist/cli/chunks/{security-QCIUC5FX.js → security-C2I6CG7B.js} +3 -3
- package/dist/cli/chunks/shared-rvf-adapter-5UQSTUSR.js +2 -0
- package/dist/cli/chunks/{shared-rvf-dual-writer-LVJJS3PD.js → shared-rvf-dual-writer-BPIFGN7I.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-27ESC5DX.js +2 -0
- package/dist/cli/chunks/{status-handler-O77A4JWM.js → status-handler-57UA6GNR.js} +2 -2
- package/dist/cli/chunks/{structural-health-WIIBIIQI.js → structural-health-KMHBG6FO.js} +2 -2
- package/dist/cli/chunks/{sync-UN6D6OF2.js → sync-53YM6U4S.js} +2 -2
- package/dist/cli/chunks/{task-handler-RBOSMJCK.js → task-handler-W2XPS5WW.js} +2 -2
- package/dist/cli/chunks/{task-handlers-VWMXQKAT.js → task-handlers-BG4IAMBJ.js} +2 -2
- package/dist/cli/chunks/{test-XK5M3PGT.js → test-QJBBVPL2.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-CTQ3JJ7G.js → test-scheduling-Y4J6EY2K.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-D5CQ3I5M.js → token-bootstrap-3TKR3UIE.js} +2 -2
- package/dist/cli/chunks/{token-usage-L4QSLWQ5.js → token-usage-5FUNHHVZ.js} +2 -2
- package/dist/cli/chunks/{transformers-SRPJDBKA.js → transformers-KVPA35SR.js} +2 -2
- package/dist/cli/chunks/{tree-sitter-wasm-parser-DOU5ITWB.js → tree-sitter-wasm-parser-LTBBLY5U.js} +2 -2
- package/dist/cli/chunks/{types-LECYZUBN.js → types-Y2BHPD6B.js} +2 -2
- package/dist/cli/chunks/unified-memory-O7GFUSD3.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-XBLROJEN.js +2 -0
- package/dist/cli/chunks/unified-persistence-YBHEAL2S.js +2 -0
- package/dist/cli/chunks/upgrade-E4VAQZQR.js +5 -0
- package/dist/cli/chunks/{validate-SIKNIS6B.js → validate-4ICDQCKJ.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-EHAMMILJ.js → validate-swarm-AIEOQOUF.js} +2 -2
- package/dist/cli/chunks/{vibium-LJ4NYXMZ.js → vibium-AF2K6YXR.js} +2 -2
- package/dist/cli/chunks/visual-security-4F7VYCAU.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-DZQ3T4JD.js → web-tree-sitter-PM67K5SP.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-U6Z73O6J.js → windsurf-installer-4MKUQ2KT.js} +2 -2
- package/dist/cli/chunks/witness-chain-AXJ44BGW.js +2 -0
- package/dist/cli/chunks/{witness-chain-JE3QU4YP.js → witness-chain-FLPF7CS6.js} +2 -2
- package/dist/cli/chunks/{workflow-62QXGZQO.js → workflow-DHTCI6QD.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-UAFUPHD3.js +2 -0
- package/dist/cli/chunks/{wrappers-CAX5EZSH.js → wrappers-5K6UGI3T.js} +2 -2
- package/dist/cli/commands/hooks-handlers/routing-hooks.d.ts +6 -0
- package/dist/cli/commands/hooks-handlers/routing-hooks.js +80 -4
- package/dist/cli/commands/upgrade.d.ts +96 -0
- package/dist/cli/commands/upgrade.js +342 -0
- package/dist/cli/completions/index.d.ts +27 -0
- package/dist/cli/completions/index.js +112 -14
- package/dist/cli/handlers/brain-handler.d.ts +2 -0
- package/dist/cli/handlers/brain-handler.js +221 -1
- package/dist/cli/index.js +5 -1
- package/dist/init/init-wizard-hooks.js +4 -1
- package/dist/init/phases/07-hooks.js +4 -1
- package/dist/integrations/ruvector/brain-diff.d.ts +93 -0
- package/dist/integrations/ruvector/brain-diff.js +281 -0
- package/dist/integrations/ruvector/brain-search.d.ts +78 -0
- package/dist/integrations/ruvector/brain-search.js +154 -0
- package/dist/mcp/bundle.js +348 -348
- package/package.json +2 -2
- package/dist/cli/chunks/adapter-P2EPBJLF.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-6UITO3NJ.js +0 -2
- package/dist/cli/chunks/base-JHBJXVGP.js +0 -2
- package/dist/cli/chunks/brain-handler-ISVST4MR.js +0 -68
- package/dist/cli/chunks/browser-workflow-U4OON5DZ.js +0 -2
- package/dist/cli/chunks/chunk-FEVTMHO6.js +0 -2
- package/dist/cli/chunks/chunk-MBDX4OHD.js +0 -2
- package/dist/cli/chunks/client-UHHMKUPF.js +0 -2
- package/dist/cli/chunks/cross-domain-router-GEBXTPZW.js +0 -2
- package/dist/cli/chunks/dream-XBRGYPBC.js +0 -2
- package/dist/cli/chunks/esm-node-EV4HOHTZ.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-BG73YVXI.js +0 -2
- package/dist/cli/chunks/hnsw-index-K73ZTLJN.js +0 -2
- package/dist/cli/chunks/hooks-ZN4FV5XS.js +0 -101
- package/dist/cli/chunks/impact-analyzer-GWIUYYCQ.js +0 -2
- package/dist/cli/chunks/init-wizard-RIJJAKE3.js +0 -2
- package/dist/cli/chunks/kernel-SIPBCRGL.js +0 -2
- package/dist/cli/chunks/knowledge-graph-NOYZXHIG.js +0 -2
- package/dist/cli/chunks/load-test-DIMUH75F.js +0 -2
- package/dist/cli/chunks/memory-backend-IWOGO4BV.js +0 -2
- package/dist/cli/chunks/protocol-executor-NT4TILJW.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-VDROHXFS.js +0 -2
- package/dist/cli/chunks/queen-coordinator-7LO73IV3.js +0 -2
- package/dist/cli/chunks/router-SFVOLN2W.js +0 -2
- package/dist/cli/chunks/routing-feedback-MRFV7WUZ.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-6L7FZZC7.js +0 -2
- package/dist/cli/chunks/safe-db-PYWBVGOV.js +0 -2
- package/dist/cli/chunks/schedule-BUQU75HY.js +0 -2
- package/dist/cli/chunks/scheduler-XOSKWZO2.js +0 -2
- package/dist/cli/chunks/shared-rvf-adapter-OZ7S4ZQL.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-7UXQZ5Y6.js +0 -2
- package/dist/cli/chunks/unified-memory-L6735TFM.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-7TZNEDGY.js +0 -2
- package/dist/cli/chunks/unified-persistence-FNYZ3C2B.js +0 -2
- package/dist/cli/chunks/visual-security-SMPZPDY4.js +0 -2
- package/dist/cli/chunks/witness-chain-FNCOTWFA.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-RCR4N7OA.js +0 -2
|
@@ -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
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brain Export Search
|
|
3
|
+
*
|
|
4
|
+
* Offline, read-only filtered search over a JSONL brain export directory.
|
|
5
|
+
* Useful for exploring what a snapshot contains without importing it.
|
|
6
|
+
*
|
|
7
|
+
* Defaults to searching qe_patterns but can target any of the 25 exported
|
|
8
|
+
* tables via the `table` option. Supports filters by domain, pattern_type,
|
|
9
|
+
* date range, and a substring query that matches `name` + `description`.
|
|
10
|
+
*
|
|
11
|
+
* RVF exports are not supported directly by this module — callers should use
|
|
12
|
+
* `aqe brain export --format jsonl` for searchable snapshots.
|
|
13
|
+
*/
|
|
14
|
+
export interface BrainSearchOptions {
|
|
15
|
+
/** Table to search. Defaults to 'qe_patterns'. */
|
|
16
|
+
readonly table?: string;
|
|
17
|
+
/** Restrict to these domains (matched against the table's domain column). */
|
|
18
|
+
readonly domains?: readonly string[];
|
|
19
|
+
/** Restrict to rows with this exact pattern_type (qe_patterns only). */
|
|
20
|
+
readonly patternType?: string;
|
|
21
|
+
/** ISO timestamp — only rows at or after this are included. */
|
|
22
|
+
readonly since?: string;
|
|
23
|
+
/** ISO timestamp — only rows at or before this are included. */
|
|
24
|
+
readonly until?: string;
|
|
25
|
+
/** Case-insensitive substring matched against name + description. */
|
|
26
|
+
readonly query?: string;
|
|
27
|
+
/** Max rows to return. Defaults to 20. */
|
|
28
|
+
readonly limit?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface BrainSearchHit {
|
|
31
|
+
/** Primary-key identity string (best effort per table). */
|
|
32
|
+
readonly id: string;
|
|
33
|
+
/** Minimal surface shown in default CLI output. */
|
|
34
|
+
readonly display: {
|
|
35
|
+
readonly name?: string;
|
|
36
|
+
readonly description?: string;
|
|
37
|
+
readonly domain?: string;
|
|
38
|
+
readonly patternType?: string;
|
|
39
|
+
readonly confidence?: number;
|
|
40
|
+
readonly updatedAt?: string;
|
|
41
|
+
};
|
|
42
|
+
/** Full raw row for callers that want more (used by --json). */
|
|
43
|
+
readonly row: Record<string, unknown>;
|
|
44
|
+
}
|
|
45
|
+
export interface BrainSearchResult {
|
|
46
|
+
readonly table: string;
|
|
47
|
+
readonly inputPath: string;
|
|
48
|
+
readonly totalScanned: number;
|
|
49
|
+
readonly totalMatched: number;
|
|
50
|
+
readonly limit: number;
|
|
51
|
+
readonly hits: readonly BrainSearchHit[];
|
|
52
|
+
readonly truncated: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Search a brain export directory for rows matching the given filters.
|
|
56
|
+
*
|
|
57
|
+
* Throws if the path isn't a JSONL export directory, if the requested table
|
|
58
|
+
* isn't known, or if the JSONL file for that table is missing.
|
|
59
|
+
*/
|
|
60
|
+
export declare function searchBrain(inputPath: string, options?: BrainSearchOptions): BrainSearchResult;
|
|
61
|
+
interface FilterContext {
|
|
62
|
+
readonly domainColumn?: string;
|
|
63
|
+
readonly domains?: Set<string>;
|
|
64
|
+
readonly patternType?: string;
|
|
65
|
+
readonly since?: string;
|
|
66
|
+
readonly until?: string;
|
|
67
|
+
readonly queryLower?: string;
|
|
68
|
+
}
|
|
69
|
+
declare function rowMatches(row: Record<string, unknown>, ctx: FilterContext): boolean;
|
|
70
|
+
declare function pickTimestamp(row: Record<string, unknown>): string | undefined;
|
|
71
|
+
declare function toHit(row: Record<string, unknown>, tableName: string, domainColumn: string | undefined): BrainSearchHit;
|
|
72
|
+
export declare const __test__: {
|
|
73
|
+
pickTimestamp: typeof pickTimestamp;
|
|
74
|
+
rowMatches: typeof rowMatches;
|
|
75
|
+
toHit: typeof toHit;
|
|
76
|
+
};
|
|
77
|
+
export {};
|
|
78
|
+
//# sourceMappingURL=brain-search.d.ts.map
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brain Export Search
|
|
3
|
+
*
|
|
4
|
+
* Offline, read-only filtered search over a JSONL brain export directory.
|
|
5
|
+
* Useful for exploring what a snapshot contains without importing it.
|
|
6
|
+
*
|
|
7
|
+
* Defaults to searching qe_patterns but can target any of the 25 exported
|
|
8
|
+
* tables via the `table` option. Supports filters by domain, pattern_type,
|
|
9
|
+
* date range, and a substring query that matches `name` + `description`.
|
|
10
|
+
*
|
|
11
|
+
* RVF exports are not supported directly by this module — callers should use
|
|
12
|
+
* `aqe brain export --format jsonl` for searchable snapshots.
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync, statSync } from 'fs';
|
|
15
|
+
import { join, resolve } from 'path';
|
|
16
|
+
import { safeJsonParse } from '../../shared/safe-json.js';
|
|
17
|
+
import { readJsonl, TABLE_CONFIGS } from './brain-shared.js';
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Constants
|
|
20
|
+
// ============================================================================
|
|
21
|
+
const DEFAULT_LIMIT = 20;
|
|
22
|
+
const DEFAULT_TABLE = 'qe_patterns';
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Public API
|
|
25
|
+
// ============================================================================
|
|
26
|
+
/**
|
|
27
|
+
* Search a brain export directory for rows matching the given filters.
|
|
28
|
+
*
|
|
29
|
+
* Throws if the path isn't a JSONL export directory, if the requested table
|
|
30
|
+
* isn't known, or if the JSONL file for that table is missing.
|
|
31
|
+
*/
|
|
32
|
+
export function searchBrain(inputPath, options = {}) {
|
|
33
|
+
const resolved = resolve(inputPath);
|
|
34
|
+
assertJsonlExport(resolved);
|
|
35
|
+
const tableName = options.table ?? DEFAULT_TABLE;
|
|
36
|
+
const config = TABLE_CONFIGS.find((c) => c.tableName === tableName);
|
|
37
|
+
if (!config) {
|
|
38
|
+
throw new Error(`Unknown table: ${tableName}`);
|
|
39
|
+
}
|
|
40
|
+
const filePath = join(resolved, config.fileName);
|
|
41
|
+
if (!existsSync(filePath)) {
|
|
42
|
+
throw new Error(`Table file not found: ${config.fileName} ` +
|
|
43
|
+
`(expected in ${resolved}). Was this export generated with --format jsonl?`);
|
|
44
|
+
}
|
|
45
|
+
const rows = readJsonl(filePath, safeJsonParse);
|
|
46
|
+
const domainColumn = config.domainColumn;
|
|
47
|
+
const limit = Math.max(1, options.limit ?? DEFAULT_LIMIT);
|
|
48
|
+
const queryLower = options.query ? options.query.toLowerCase() : undefined;
|
|
49
|
+
const domains = options.domains && options.domains.length > 0 ? new Set(options.domains) : undefined;
|
|
50
|
+
const since = options.since;
|
|
51
|
+
const until = options.until;
|
|
52
|
+
const patternType = options.patternType;
|
|
53
|
+
let matched = 0;
|
|
54
|
+
const hits = [];
|
|
55
|
+
for (const row of rows) {
|
|
56
|
+
if (!rowMatches(row, { domainColumn, domains, patternType, since, until, queryLower })) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
matched++;
|
|
60
|
+
if (hits.length < limit) {
|
|
61
|
+
hits.push(toHit(row, config.tableName, domainColumn));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
table: tableName,
|
|
66
|
+
inputPath: resolved,
|
|
67
|
+
totalScanned: rows.length,
|
|
68
|
+
totalMatched: matched,
|
|
69
|
+
limit,
|
|
70
|
+
hits,
|
|
71
|
+
truncated: matched > limit,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function rowMatches(row, ctx) {
|
|
75
|
+
// Domain filter — only applied if table has a domain column.
|
|
76
|
+
if (ctx.domains) {
|
|
77
|
+
if (!ctx.domainColumn)
|
|
78
|
+
return false; // caller asked for a domain filter on a table that has none
|
|
79
|
+
const v = row[ctx.domainColumn];
|
|
80
|
+
if (typeof v !== 'string' || !ctx.domains.has(v))
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
// Pattern type filter — only meaningful for qe_patterns.
|
|
84
|
+
if (ctx.patternType !== undefined) {
|
|
85
|
+
const v = row['pattern_type'];
|
|
86
|
+
if (v !== ctx.patternType)
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
// Date range — matched against updated_at | created_at | timestamp (in that order).
|
|
90
|
+
if (ctx.since !== undefined || ctx.until !== undefined) {
|
|
91
|
+
const ts = pickTimestamp(row);
|
|
92
|
+
if (ts === undefined)
|
|
93
|
+
return false;
|
|
94
|
+
if (ctx.since !== undefined && ts < ctx.since)
|
|
95
|
+
return false;
|
|
96
|
+
if (ctx.until !== undefined && ts > ctx.until)
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
// Substring query — matched against name + description (case-insensitive).
|
|
100
|
+
if (ctx.queryLower !== undefined) {
|
|
101
|
+
const name = typeof row['name'] === 'string' ? row['name'].toLowerCase() : '';
|
|
102
|
+
const desc = typeof row['description'] === 'string' ? row['description'].toLowerCase() : '';
|
|
103
|
+
if (!name.includes(ctx.queryLower) && !desc.includes(ctx.queryLower))
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
function pickTimestamp(row) {
|
|
109
|
+
for (const col of ['updated_at', 'created_at', 'timestamp']) {
|
|
110
|
+
const v = row[col];
|
|
111
|
+
if (typeof v === 'string' && v.length > 0)
|
|
112
|
+
return v;
|
|
113
|
+
}
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
// ============================================================================
|
|
117
|
+
// Result formatting
|
|
118
|
+
// ============================================================================
|
|
119
|
+
function toHit(row, tableName, domainColumn) {
|
|
120
|
+
const id = (typeof row['id'] === 'string' || typeof row['id'] === 'number'
|
|
121
|
+
? String(row['id'])
|
|
122
|
+
: undefined) ?? `${tableName}:?`;
|
|
123
|
+
const display = {
|
|
124
|
+
name: typeof row['name'] === 'string' ? row['name'] : undefined,
|
|
125
|
+
description: typeof row['description'] === 'string' ? row['description'] : undefined,
|
|
126
|
+
domain: domainColumn && typeof row[domainColumn] === 'string' ? row[domainColumn] : undefined,
|
|
127
|
+
patternType: typeof row['pattern_type'] === 'string' ? row['pattern_type'] : undefined,
|
|
128
|
+
confidence: typeof row['confidence'] === 'number' ? row['confidence'] : undefined,
|
|
129
|
+
updatedAt: pickTimestamp(row),
|
|
130
|
+
};
|
|
131
|
+
return { id, display, row };
|
|
132
|
+
}
|
|
133
|
+
// ============================================================================
|
|
134
|
+
// Helpers
|
|
135
|
+
// ============================================================================
|
|
136
|
+
function assertJsonlExport(path) {
|
|
137
|
+
if (!existsSync(path)) {
|
|
138
|
+
throw new Error(`Path not found: ${path}`);
|
|
139
|
+
}
|
|
140
|
+
const s = statSync(path);
|
|
141
|
+
if (s.isFile()) {
|
|
142
|
+
if (path.endsWith('.rvf')) {
|
|
143
|
+
throw new Error('Brain search does not support RVF exports. Re-export with --format jsonl, or use `aqe brain info` for RVF summaries.');
|
|
144
|
+
}
|
|
145
|
+
throw new Error(`Unsupported brain export: ${path} (expected a JSONL directory)`);
|
|
146
|
+
}
|
|
147
|
+
const manifest = join(path, 'manifest.json');
|
|
148
|
+
if (!existsSync(manifest)) {
|
|
149
|
+
throw new Error(`Manifest not found at ${manifest}. Is this a brain export directory?`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Re-export for test access / future helpers without widening the public API.
|
|
153
|
+
export const __test__ = { pickTimestamp, rowMatches, toHit };
|
|
154
|
+
//# sourceMappingURL=brain-search.js.map
|