agentic-qe 3.12.2 → 3.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. package/.claude/skills/skills-manifest.json +1 -1
  2. package/CHANGELOG.md +39 -0
  3. package/assets/skills/skills-manifest.json +1 -1
  4. package/dist/cli/bundle.js +5 -5
  5. package/dist/cli/chunks/adapter-D657MKZY.js +2 -0
  6. package/dist/cli/chunks/{agent-booster-wasm-3KYNICBC.js → agent-booster-wasm-XFAQATTH.js} +2 -2
  7. package/dist/cli/chunks/{agent-handler-NGPTMI6E.js → agent-handler-2ZV4CA3U.js} +2 -2
  8. package/dist/cli/chunks/{agent-memory-branch-GNTQKQMG.js → agent-memory-branch-6WGP7F5T.js} +2 -2
  9. package/dist/cli/chunks/aqe-learning-engine-AFR6OZJK.js +2 -0
  10. package/dist/cli/chunks/{arena-HQEP2NWI.js → arena-FWX7XZAE.js} +4 -4
  11. package/dist/cli/chunks/{arena-PA7VIYD4.js → arena-KJUNQK4N.js} +2 -2
  12. package/dist/cli/chunks/{audit-XSDM57GC.js → audit-YFUDEOKN.js} +3 -3
  13. package/dist/cli/chunks/base-K5QRGZWE.js +2 -0
  14. package/dist/cli/chunks/{hnswlib-node-BCASOCNU.js → better-sqlite3-FE55OGYB.js} +2 -2
  15. package/dist/cli/chunks/brain-handler-ZCK4WTPK.js +89 -0
  16. package/dist/cli/chunks/{branch-enumerator-ZW7RNMUF.js → branch-enumerator-HTVINRYG.js} +2 -2
  17. package/dist/cli/chunks/{browser-4LU22CPP.js → browser-WUL2B77M.js} +2 -2
  18. package/dist/cli/chunks/browser-workflow-ZMMKCGYW.js +2 -0
  19. package/dist/cli/chunks/{chunk-TRHUH24V.js → chunk-2CPJCXV6.js} +2 -2
  20. package/dist/cli/chunks/{chunk-TLYZPOA7.js → chunk-2HCMRGMO.js} +2 -2
  21. package/dist/cli/chunks/{chunk-X47GHZY3.js → chunk-2LNDU7AW.js} +2 -2
  22. package/dist/cli/chunks/{chunk-OIUIVV2N.js → chunk-2OX74DOO.js} +1 -1
  23. package/dist/cli/chunks/{chunk-AJ6DZXKK.js → chunk-2YDZXFO2.js} +2 -2
  24. package/dist/cli/chunks/{chunk-Z63IOTDW.js → chunk-32L7DKNQ.js} +2 -2
  25. package/dist/cli/chunks/{chunk-7DV42KFP.js → chunk-3YC4YUGB.js} +2 -2
  26. package/dist/cli/chunks/{chunk-R5HC6JVJ.js → chunk-4EHW4TNA.js} +2 -2
  27. package/dist/cli/chunks/{chunk-NDAJWCXN.js → chunk-4HP7N6SP.js} +2 -2
  28. package/dist/cli/chunks/{chunk-BMRR3MBR.js → chunk-5FAWIIWF.js} +2 -2
  29. package/dist/cli/chunks/{chunk-5CGTBAVF.js → chunk-67BCEHU5.js} +1 -1
  30. package/dist/cli/chunks/{chunk-BDX54WJV.js → chunk-6E47R27C.js} +1 -1
  31. package/dist/cli/chunks/{chunk-J6EFAKDQ.js → chunk-6HQDPDN5.js} +2 -2
  32. package/dist/cli/chunks/{chunk-ABHKXMOJ.js → chunk-6SQ72FG7.js} +1 -1
  33. package/dist/cli/chunks/{chunk-WMNGPIP3.js → chunk-6SUSRXXF.js} +1 -1
  34. package/dist/cli/chunks/{chunk-6X65BGGK.js → chunk-72QQDR3Y.js} +2 -2
  35. package/dist/cli/chunks/{chunk-YYV3FYVB.js → chunk-7Q74K3HZ.js} +1 -1
  36. package/dist/cli/chunks/{chunk-Z3FA5KR6.js → chunk-7WF3TW3G.js} +4 -4
  37. package/dist/cli/chunks/{chunk-WL5VMIO4.js → chunk-7XUM4LBC.js} +1 -1
  38. package/dist/cli/chunks/{chunk-EZ3JVN6S.js → chunk-ADQFQBFJ.js} +2 -2
  39. package/dist/cli/chunks/{chunk-LIAW5FD7.js → chunk-AIWRYWK2.js} +2 -2
  40. package/dist/cli/chunks/{chunk-KBAXD6PH.js → chunk-AZ24ONMX.js} +1 -1
  41. package/dist/cli/chunks/{chunk-ZHWXI4SK.js → chunk-BDGKB2PT.js} +2 -2
  42. package/dist/cli/chunks/{chunk-4FHJYJCH.js → chunk-BEPP57C2.js} +2 -2
  43. package/dist/cli/chunks/{chunk-WY5CX3VH.js → chunk-BQ2K4BPD.js} +2 -2
  44. package/dist/cli/chunks/{chunk-T6TQPF5P.js → chunk-BSNNTOHY.js} +3 -3
  45. package/dist/cli/chunks/chunk-CHFTHSMM.js +9 -0
  46. package/dist/cli/chunks/{chunk-HNU32LN3.js → chunk-CL6SNCFF.js} +1 -1
  47. package/dist/cli/chunks/{chunk-K43YXI7C.js → chunk-CXMOIE7D.js} +1 -1
  48. package/dist/cli/chunks/{chunk-QYST2TZW.js → chunk-CYSBM52D.js} +2 -2
  49. package/dist/cli/chunks/{chunk-UFPCNUJA.js → chunk-D4GMAUTP.js} +10 -10
  50. package/dist/cli/chunks/{chunk-WE5QHYL7.js → chunk-DCYBV6HV.js} +1 -1
  51. package/dist/cli/chunks/chunk-DDYP6FBC.js +2 -0
  52. package/dist/cli/chunks/{chunk-GP7IXYOY.js → chunk-DHUZHT5D.js} +1 -1
  53. package/dist/cli/chunks/{chunk-7KMYBRKJ.js → chunk-DMD6WVJ2.js} +2 -2
  54. package/dist/cli/chunks/{chunk-RXEQB4OT.js → chunk-DTZFZ5M7.js} +2 -2
  55. package/dist/cli/chunks/{chunk-M4XVEUUM.js → chunk-DW7OI5IF.js} +2 -2
  56. package/dist/cli/chunks/{chunk-ADZTWGEB.js → chunk-DZ775UGW.js} +2 -2
  57. package/dist/cli/chunks/{chunk-KDGLNJPB.js → chunk-E2U3LTGM.js} +1 -1
  58. package/dist/cli/chunks/{chunk-7OD6HFCP.js → chunk-E53UR2EW.js} +3 -3
  59. package/dist/cli/chunks/{chunk-R554WVIG.js → chunk-EH7TSJPS.js} +2 -2
  60. package/dist/cli/chunks/{chunk-FKUH33L3.js → chunk-EHO52NKU.js} +2 -2
  61. package/dist/cli/chunks/{chunk-ZBYMF2QJ.js → chunk-EOUJ6X5H.js} +1 -1
  62. package/dist/cli/chunks/{chunk-CDMAVNV5.js → chunk-FHHCH7WL.js} +1 -1
  63. package/dist/cli/chunks/{chunk-AL5QT6OX.js → chunk-FJACKKRL.js} +2 -2
  64. package/dist/cli/chunks/{chunk-MF4FULAI.js → chunk-FTM562PF.js} +1 -1
  65. package/dist/cli/chunks/{chunk-MNHGBG4D.js → chunk-FXOOOJQD.js} +1 -1
  66. package/dist/cli/chunks/chunk-G5OGKVLO.js +2 -0
  67. package/dist/cli/chunks/{chunk-WYFEVPLO.js → chunk-GGTCD4MA.js} +1 -1
  68. package/dist/cli/chunks/{chunk-LWVUNBZO.js → chunk-GMFFMJD6.js} +2 -2
  69. package/dist/cli/chunks/{chunk-V2QYW5KW.js → chunk-GS6G7AVS.js} +2 -2
  70. package/dist/cli/chunks/{chunk-IKIKIHFQ.js → chunk-GV2BS5NC.js} +2 -2
  71. package/dist/cli/chunks/{chunk-FUBN5GPY.js → chunk-HGJQSTQD.js} +1 -1
  72. package/dist/cli/chunks/{chunk-6SWR2BN7.js → chunk-HJ2LG5IH.js} +1 -1
  73. package/dist/cli/chunks/{chunk-C7VNQ4PY.js → chunk-HJ4U64BL.js} +2 -2
  74. package/dist/cli/chunks/{chunk-VM6VBRRU.js → chunk-ILRKO6A5.js} +3 -3
  75. package/dist/cli/chunks/{chunk-RXH2TC2K.js → chunk-IWQHQLT6.js} +2 -2
  76. package/dist/cli/chunks/{chunk-N57BKUVE.js → chunk-J2RJOJ5Q.js} +1 -1
  77. package/dist/cli/chunks/{chunk-KNOO6TFO.js → chunk-KA4EAMMQ.js} +3 -3
  78. package/dist/cli/chunks/{chunk-BOR5MME3.js → chunk-KE3RK35K.js} +1 -1
  79. package/dist/cli/chunks/{chunk-AMPYON7M.js → chunk-KGHSKDC7.js} +2 -2
  80. package/dist/cli/chunks/{chunk-2R7J4ZGT.js → chunk-KKOFH26C.js} +1 -1
  81. package/dist/cli/chunks/{chunk-OMIGKGJJ.js → chunk-KNWBRMLL.js} +2 -2
  82. package/dist/cli/chunks/{chunk-KV5OZ6T3.js → chunk-KRS4KGX5.js} +2 -2
  83. package/dist/cli/chunks/{chunk-PXKVW6PT.js → chunk-KVHCWH4H.js} +2 -2
  84. package/dist/cli/chunks/{chunk-ZF65VOQH.js → chunk-KXKACV3E.js} +2 -2
  85. package/dist/cli/chunks/{chunk-P65S7AZA.js → chunk-L2X3BWMN.js} +2 -2
  86. package/dist/cli/chunks/{chunk-ERQL3D2O.js → chunk-L6GZGEFQ.js} +2 -2
  87. package/dist/cli/chunks/{chunk-E5XWCGSX.js → chunk-LCM7TY76.js} +2 -2
  88. package/dist/cli/chunks/{chunk-HH5Y4NCR.js → chunk-LGYEOYQJ.js} +2 -2
  89. package/dist/cli/chunks/{chunk-6FBXYS6X.js → chunk-LHAUFY4Y.js} +2 -2
  90. package/dist/cli/chunks/{chunk-5YLY2WT2.js → chunk-LNIHLNW4.js} +3 -3
  91. package/dist/cli/chunks/{chunk-BUKGW63B.js → chunk-M32DTUZM.js} +2 -2
  92. package/dist/cli/chunks/{chunk-OSAPKOGN.js → chunk-M7W6VJ65.js} +1 -1
  93. package/dist/cli/chunks/{chunk-KBXW7S3W.js → chunk-MB7TZQW3.js} +3 -3
  94. package/dist/cli/chunks/{chunk-YRO7HNS4.js → chunk-MOX25RZQ.js} +2 -2
  95. package/dist/cli/chunks/{chunk-F3CKOVZM.js → chunk-MOXKKY5Q.js} +6 -6
  96. package/dist/cli/chunks/{chunk-XNNYHQLW.js → chunk-MS6VOSPY.js} +5 -5
  97. package/dist/cli/chunks/{chunk-6N62KS3C.js → chunk-MSDIIRLM.js} +2 -2
  98. package/dist/cli/chunks/{chunk-2R7XZ2WP.js → chunk-MZ7SIO6R.js} +2 -2
  99. package/dist/cli/chunks/{chunk-CMKCPRWX.js → chunk-N4ML23ZG.js} +1 -1
  100. package/dist/cli/chunks/{chunk-SYLTJKN2.js → chunk-NAMJGRGC.js} +1 -1
  101. package/dist/cli/chunks/{chunk-ACDZ2CRV.js → chunk-NJDLJ3KD.js} +2 -2
  102. package/dist/cli/chunks/{chunk-EGU54SNK.js → chunk-NKTLKMUB.js} +1 -1
  103. package/dist/cli/chunks/{chunk-YZ44FUVJ.js → chunk-NLDLUHOF.js} +2 -2
  104. package/dist/cli/chunks/{chunk-APVXTHTA.js → chunk-NOSQI2OW.js} +2 -2
  105. package/dist/cli/chunks/{chunk-MNNNA57O.js → chunk-NT66CT73.js} +2 -2
  106. package/dist/cli/chunks/{chunk-CQKEVUMO.js → chunk-NX522PRH.js} +2 -2
  107. package/dist/cli/chunks/{chunk-CKFZOPZN.js → chunk-OBL6W4Z5.js} +2 -2
  108. package/dist/cli/chunks/chunk-OPG2HV2W.js +2 -0
  109. package/dist/cli/chunks/{chunk-GCQATSMK.js → chunk-PDX7IYTJ.js} +2 -2
  110. package/dist/cli/chunks/{chunk-YDZIPP3Y.js → chunk-PEHEANAM.js} +2 -2
  111. package/dist/cli/chunks/{chunk-MALFTRCT.js → chunk-PPUDKQ4X.js} +2 -2
  112. package/dist/cli/chunks/{chunk-TMQ3S7HR.js → chunk-PSDH7CIL.js} +1 -1
  113. package/dist/cli/chunks/{chunk-R6LDR3IO.js → chunk-PTPN6HQ7.js} +2 -2
  114. package/dist/cli/chunks/{chunk-BDVOXGY5.js → chunk-PXCJDB7J.js} +1 -1
  115. package/dist/cli/chunks/{chunk-VOHYQ6MX.js → chunk-QILF6BZH.js} +2 -2
  116. package/dist/cli/chunks/{chunk-UEIIIDBJ.js → chunk-R6WMGSEK.js} +2 -2
  117. package/dist/cli/chunks/{chunk-DGOZ3CGB.js → chunk-RE42RJYR.js} +2 -2
  118. package/dist/cli/chunks/{chunk-TERRRQVY.js → chunk-RLBNAB6Y.js} +1 -1
  119. package/dist/cli/chunks/{chunk-BPSEFLJ6.js → chunk-ROFCS47F.js} +1 -1
  120. package/dist/cli/chunks/{chunk-3LELACAQ.js → chunk-RSZOCQOL.js} +2 -2
  121. package/dist/cli/chunks/{chunk-YSCEUK55.js → chunk-S47YGWXK.js} +2 -2
  122. package/dist/cli/chunks/{chunk-RFQIC6ZF.js → chunk-SFS3UHNF.js} +1 -1
  123. package/dist/cli/chunks/{chunk-HU6ETNA7.js → chunk-SGMJ277D.js} +1 -1
  124. package/dist/cli/chunks/{chunk-2L7K2J2T.js → chunk-SPI4LUJ6.js} +2 -2
  125. package/dist/cli/chunks/{chunk-LOZAUP6L.js → chunk-SV7J5FDW.js} +2 -2
  126. package/dist/cli/chunks/{chunk-GUGUYFU5.js → chunk-TP3UAWMB.js} +2 -2
  127. package/dist/cli/chunks/{chunk-ILNQPPKB.js → chunk-TXLPOXAN.js} +1 -1
  128. package/dist/cli/chunks/{chunk-UF3YOGHV.js → chunk-UAPUA6OY.js} +2 -2
  129. package/dist/cli/chunks/{chunk-GECWGFRR.js → chunk-UGW23T6S.js} +2 -2
  130. package/dist/cli/chunks/{chunk-B7DI76SY.js → chunk-UGXHMQ6P.js} +2 -2
  131. package/dist/cli/chunks/{chunk-VHYACXLN.js → chunk-UIHZ34SJ.js} +2 -2
  132. package/dist/cli/chunks/{chunk-WRMUQVKY.js → chunk-ULQCEM7K.js} +2 -2
  133. package/dist/cli/chunks/{chunk-ZL7ZOIHO.js → chunk-UZ7FXVH5.js} +1 -1
  134. package/dist/cli/chunks/{chunk-3AJUJAUJ.js → chunk-VFYMWDSJ.js} +1 -1
  135. package/dist/cli/chunks/{chunk-TQNNKW7K.js → chunk-VSD6JE2H.js} +2 -2
  136. package/dist/cli/chunks/{chunk-327YEKBU.js → chunk-VUCVSKJC.js} +2 -2
  137. package/dist/cli/chunks/{chunk-LGEPR7MH.js → chunk-WBZNLFTV.js} +3 -3
  138. package/dist/cli/chunks/{chunk-OELLHV7S.js → chunk-WFPGIP4N.js} +2 -2
  139. package/dist/cli/chunks/{chunk-WC5PM33J.js → chunk-WKE6WL5C.js} +3 -3
  140. package/dist/cli/chunks/{chunk-P2FYRAC5.js → chunk-WQASUQ5P.js} +1 -1
  141. package/dist/cli/chunks/{chunk-OEZNUXY7.js → chunk-WUE53ZPH.js} +1 -1
  142. package/dist/cli/chunks/{chunk-KJJP446A.js → chunk-XBOCRCC6.js} +1 -1
  143. package/dist/cli/chunks/{chunk-TFVWUR2U.js → chunk-XDHGCBTS.js} +2 -2
  144. package/dist/cli/chunks/{chunk-WKWIUS5G.js → chunk-XQ5JT7KM.js} +2 -2
  145. package/dist/cli/chunks/{chunk-CTFW7CMI.js → chunk-XUUVAAHV.js} +2 -2
  146. package/dist/cli/chunks/{chunk-IQ56KMMH.js → chunk-XZGOXLZH.js} +1 -1
  147. package/dist/cli/chunks/{chunk-EKTWIEEO.js → chunk-Y5L37K7X.js} +2 -2
  148. package/dist/cli/chunks/{chunk-VQU2JXTK.js → chunk-Y625LP6K.js} +2 -2
  149. package/dist/cli/chunks/{chunk-56MXYSYY.js → chunk-Y6XNISHP.js} +2 -2
  150. package/dist/cli/chunks/{chunk-FTG4ZVTX.js → chunk-YDYKFSD2.js} +10 -10
  151. package/dist/cli/chunks/{chunk-W7LBT3BF.js → chunk-YEC55GO5.js} +2 -2
  152. package/dist/cli/chunks/{chunk-DTXHRALB.js → chunk-YOG5KQZF.js} +2 -2
  153. package/dist/cli/chunks/{chunk-4KEOBDEI.js → chunk-YUDGQZJN.js} +2 -2
  154. package/dist/cli/chunks/{chunk-PHIEJAQK.js → chunk-Z3SXMYVI.js} +3 -3
  155. package/dist/cli/chunks/{chunk-PSA2SOON.js → chunk-ZFLE4D4X.js} +2 -2
  156. package/dist/cli/chunks/{chunk-5SM57X4D.js → chunk-ZGKQCUPB.js} +2 -2
  157. package/dist/cli/chunks/{chunk-SVUWAV6Y.js → chunk-ZTKCGEB6.js} +1 -1
  158. package/dist/cli/chunks/{ci-NT4DUGQ4.js → ci-MMLUV6L6.js} +2 -2
  159. package/dist/cli/chunks/{ci-output-PXBD2QPH.js → ci-output-25GS6RXR.js} +2 -2
  160. package/dist/cli/chunks/{circuit-breaker-ZPCCEEDX.js → circuit-breaker-4OWAN6R6.js} +2 -2
  161. package/dist/cli/chunks/{claude-flow-setup-CZCDFZOE.js → claude-flow-setup-LR3SRBX6.js} +2 -2
  162. package/dist/cli/chunks/client-WI7RRUZO.js +2 -0
  163. package/dist/cli/chunks/{cline-installer-6J2S7GLM.js → cline-installer-YSZWRZUI.js} +2 -2
  164. package/dist/cli/chunks/{code-UTERK5AP.js → code-UUWUIXI7.js} +2 -2
  165. package/dist/cli/chunks/{code-index-extractor-O3MJTOS2.js → code-index-extractor-2LSPQORU.js} +2 -2
  166. package/dist/cli/chunks/{codex-installer-AZJIVXJR.js → codex-installer-E5BVXZVA.js} +2 -2
  167. package/dist/cli/chunks/{completions-A6ANQSZN.js → completions-YKXBKZSO.js} +2 -2
  168. package/dist/cli/chunks/{complexity-analyzer-MRSN7VUP.js → complexity-analyzer-HNT2QRWB.js} +2 -2
  169. package/dist/cli/chunks/{continuedev-installer-6LMKQRUI.js → continuedev-installer-AW5VCB66.js} +2 -2
  170. package/dist/cli/chunks/{copilot-installer-KP3TWUNO.js → copilot-installer-B6SVZXQT.js} +2 -2
  171. package/dist/cli/chunks/core-handlers-T6URR57V.js +2 -0
  172. package/dist/cli/chunks/{cost-tracker-R3C5IQPZ.js → cost-tracker-POZMBN2V.js} +2 -2
  173. package/dist/cli/chunks/{coverage-MR4QA2NM.js → coverage-V5BGPN5Q.js} +3 -3
  174. package/dist/cli/chunks/cross-domain-router-WHTTKHWM.js +2 -0
  175. package/dist/cli/chunks/{cursor-installer-LPZ7NGOS.js → cursor-installer-EYBI4QVK.js} +2 -2
  176. package/dist/cli/chunks/{daemon-X5KXHRY3.js → daemon-CF6ENQB2.js} +3 -3
  177. package/dist/cli/chunks/{daemon-K3KW2UDV.js → daemon-HKARXY2W.js} +4 -4
  178. package/dist/cli/chunks/{dag-attention-scheduler-J4FJSGNN.js → dag-attention-scheduler-XIL5IAP7.js} +2 -2
  179. package/dist/cli/chunks/{detect-22TX2NCA.js → detect-RRX2U2KK.js} +2 -2
  180. package/dist/cli/chunks/{dist-node-QI4I4QPS.js → dist-node-DOANNRCS.js} +2 -2
  181. package/dist/cli/chunks/{domain-handler-ZYZGPNOQ.js → domain-handler-QMTJV5OR.js} +2 -2
  182. package/dist/cli/chunks/{domain-transfer-2EEQTNIU.js → domain-transfer-FSNH75XW.js} +2 -2
  183. package/dist/cli/chunks/dream-QUL6SURC.js +2 -0
  184. package/dist/cli/chunks/{embed-and-insert-pattern-LYCTU5BS.js → embed-and-insert-pattern-NI7PGONV.js} +2 -2
  185. package/dist/cli/chunks/{eval-SOA72GUX.js → eval-6ZAF2RY3.js} +2 -2
  186. package/dist/cli/chunks/{experience-capture-middleware-AFFYOMYM.js → experience-capture-middleware-JMXR7N5G.js} +3 -3
  187. package/dist/cli/chunks/{fast-paths-WNMHOSUH.js → fast-paths-YB7XZZ76.js} +2 -2
  188. package/dist/cli/chunks/{feature-flags-FT4YBZH4.js → feature-flags-2RC4GFC4.js} +2 -2
  189. package/dist/cli/chunks/{feature-flags-HAP5IAAY.js → feature-flags-KJSP7KR6.js} +2 -2
  190. package/dist/cli/chunks/{file-discovery-B4FFOH3Z.js → file-discovery-SUPBXFYI.js} +2 -2
  191. package/dist/cli/chunks/{fleet-2ICPYV3J.js → fleet-KSXFOLFW.js} +3 -3
  192. package/dist/cli/chunks/{gnn-wrapper-XIBJAHMW.js → gnn-wrapper-DFZ5KPPK.js} +2 -2
  193. package/dist/cli/chunks/{heartbeat-handler-NSLSKDOI.js → heartbeat-handler-G3EADK2H.js} +4 -4
  194. package/dist/cli/chunks/heartbeat-scheduler-VZNKE33K.js +2 -0
  195. package/dist/cli/chunks/hnsw-adapter-LGWLDZLC.js +2 -0
  196. package/dist/cli/chunks/hnsw-index-66FOOI7U.js +2 -0
  197. package/dist/cli/chunks/{hnsw-legacy-bridge-FTV4CCBB.js → hnsw-legacy-bridge-MA676GER.js} +2 -2
  198. package/dist/cli/chunks/{better-sqlite3-RQCOOAZC.js → hnswlib-node-SKTT5KIH.js} +2 -2
  199. package/dist/cli/chunks/{hooks-SM4EU52N.js → hooks-HTCPMZNZ.js} +10 -10
  200. package/dist/cli/chunks/hybrid-router-I5MEVQDF.js +2 -0
  201. package/dist/cli/chunks/{hypergraph-engine-RRMX4N3L.js → hypergraph-engine-QPB3IH4A.js} +2 -2
  202. package/dist/cli/chunks/{hypergraph-handler-MNFGDKAP.js → hypergraph-handler-GBFSVD7N.js} +3 -3
  203. package/dist/cli/chunks/impact-analyzer-K6ANYIY3.js +2 -0
  204. package/dist/cli/chunks/{init-handler-BNHIJ5TX.js → init-handler-XYBTBCPD.js} +6 -6
  205. package/dist/cli/chunks/init-wizard-URHGXJ32.js +2 -0
  206. package/dist/cli/chunks/kernel-OKI5ZY5P.js +2 -0
  207. package/dist/cli/chunks/{kilocode-installer-GFKUKPLY.js → kilocode-installer-LY6JOBFY.js} +2 -2
  208. package/dist/cli/chunks/{kiro-installer-YBIYKODN.js → kiro-installer-JF6NXTJL.js} +2 -2
  209. package/dist/cli/chunks/knowledge-graph-VQQSK7T5.js +2 -0
  210. package/dist/cli/chunks/{learning-QEWUPCK6.js → learning-BIISN67N.js} +3 -3
  211. package/dist/cli/chunks/{llm-router-D5FQIMVQ.js → llm-router-YZUNVZQE.js} +4 -4
  212. package/dist/cli/chunks/llm-router-service-TISH33SY.js +2 -0
  213. package/dist/cli/chunks/{load-CLBUCKZQ.js → load-MTWNBNLL.js} +2 -2
  214. package/dist/cli/chunks/load-test-KWKWC4Q7.js +2 -0
  215. package/dist/cli/chunks/{mcp-VOMG5DPV.js → mcp-37PYMNHQ.js} +2 -2
  216. package/dist/cli/chunks/{memory-WZO63VSC.js → memory-IXUUDCI3.js} +5 -5
  217. package/dist/cli/chunks/memory-backend-JSQQMXVS.js +2 -0
  218. package/dist/cli/chunks/memory-handlers-RM2VOFJX.js +2 -0
  219. package/dist/cli/chunks/{multi-model-executor-7UKW43VV.js → multi-model-executor-RKKS5XYG.js} +2 -2
  220. package/dist/cli/chunks/{opencode-installer-MLFPRRL2.js → opencode-installer-3VXI5MTR.js} +2 -2
  221. package/dist/cli/chunks/{orchestrator-XNYDBGIN.js → orchestrator-UO3ZOGFZ.js} +5 -5
  222. package/dist/cli/chunks/pattern-null-store-SXBIUKE5.js +2 -0
  223. package/dist/cli/chunks/{pattern-usage-recorder-ZAP7ASQI.js → pattern-usage-recorder-YJKRL2GI.js} +2 -2
  224. package/dist/cli/chunks/{pipeline-4EJYOPBC.js → pipeline-GJQJKXWX.js} +2 -2
  225. package/dist/cli/chunks/{platform-ALPOWCOH.js → platform-RHVCZK6C.js} +2 -2
  226. package/dist/cli/chunks/{plugin-S2RX3KHR.js → plugin-ZKAIW7O6.js} +2 -2
  227. package/dist/cli/chunks/{prime-radiant-advanced-wasm-P2JB73XX.js → prime-radiant-advanced-wasm-4X3DSKQV.js} +2 -2
  228. package/dist/cli/chunks/protocol-executor-D3Q5P3WY.js +2 -0
  229. package/dist/cli/chunks/{protocol-handler-ZBJXSESA.js → protocol-handler-KKYQZMB2.js} +2 -2
  230. package/dist/cli/chunks/{prove-MYJ5YV45.js → prove-OD6RPKWX.js} +2 -2
  231. package/dist/cli/chunks/provider-manager-2EIX7E5Q.js +2 -0
  232. package/dist/cli/chunks/qe-reasoning-bank-ITOW2ZHC.js +2 -0
  233. package/dist/cli/chunks/{quality-NIACQC4M.js → quality-ZRWBXCKO.js} +2 -2
  234. package/dist/cli/chunks/{quality-gate-OAZ23ON5.js → quality-gate-Y6BWQV7J.js} +3 -3
  235. package/dist/cli/chunks/queen-coordinator-TO5X2EXL.js +2 -0
  236. package/dist/cli/chunks/{real-embeddings-6I4LP7PL.js → real-embeddings-YYEUO4P2.js} +2 -2
  237. package/dist/cli/chunks/{roocode-installer-LRQHP6MK.js → roocode-installer-JBCPS3FK.js} +2 -2
  238. package/dist/cli/chunks/router-GZJQEJU3.js +2 -0
  239. package/dist/cli/chunks/routing-feedback-CRXSKFNS.js +2 -0
  240. package/dist/cli/chunks/{routing-handler-A7BW7MV4.js → routing-handler-KTPJOSBJ.js} +2 -2
  241. package/dist/cli/chunks/{ruvector-commands-ZDRRFSJS.js → ruvector-commands-SCZZVRE7.js} +2 -2
  242. package/dist/cli/chunks/{rvf-dual-writer-QWE3Z6BB.js → rvf-dual-writer-IP7GELQJ.js} +2 -2
  243. package/dist/cli/chunks/{rvf-migration-adapter-6UDAP7QB.js → rvf-migration-adapter-WLFTDARU.js} +2 -2
  244. package/dist/cli/chunks/{rvf-migration-coordinator-FEW2N4R4.js → rvf-migration-coordinator-MGFDQ5WD.js} +2 -2
  245. package/dist/cli/chunks/rvf-native-adapter-WHADT5HX.js +2 -0
  246. package/dist/cli/chunks/rvf-store-integrity-OTOAGT5W.js +2 -0
  247. package/dist/cli/chunks/safe-db-MIZ2OFWC.js +2 -0
  248. package/dist/cli/chunks/schedule-XFILYTYC.js +2 -0
  249. package/dist/cli/chunks/scheduler-EIPJ777A.js +2 -0
  250. package/dist/cli/chunks/{security-KFXBV65O.js → security-B2CLZKRB.js} +3 -3
  251. package/dist/cli/chunks/shared-rvf-adapter-2PMFAQMN.js +2 -0
  252. package/dist/cli/chunks/{shared-rvf-dual-writer-CXXTB7CU.js → shared-rvf-dual-writer-B6P732AV.js} +2 -2
  253. package/dist/cli/chunks/sqlite-persistence-PFU3GSRD.js +2 -0
  254. package/dist/cli/chunks/{status-handler-CXSVM236.js → status-handler-M6SN2W2D.js} +2 -2
  255. package/dist/cli/chunks/{structural-health-LMHSM7MJ.js → structural-health-YCCTGI3K.js} +2 -2
  256. package/dist/cli/chunks/{sync-REEFKICL.js → sync-3SDMVAIU.js} +2 -2
  257. package/dist/cli/chunks/{sync-DMOUY2EY.js → sync-KSRF77ID.js} +2 -2
  258. package/dist/cli/chunks/{task-handler-DMSNFIH3.js → task-handler-MIKRB2SL.js} +2 -2
  259. package/dist/cli/chunks/{task-handlers-3Z3QV7X7.js → task-handlers-YXKRUBQ4.js} +3 -3
  260. package/dist/cli/chunks/{test-U6CGMDLN.js → test-MLOLQCB7.js} +4 -4
  261. package/dist/cli/chunks/{test-scheduling-YHYA3BP5.js → test-scheduling-3KXESUZS.js} +3 -3
  262. package/dist/cli/chunks/token-bootstrap-6V2PMDBJ.js +2 -0
  263. package/dist/cli/chunks/{token-usage-EOOTM7Q3.js → token-usage-DP6THJ3I.js} +2 -2
  264. package/dist/cli/chunks/{transformers-EKDJW2H6.js → transformers-QFOBOP2Y.js} +2 -2
  265. package/dist/cli/chunks/{tree-sitter-wasm-parser-HTGAXDQA.js → tree-sitter-wasm-parser-COK2XERS.js} +2 -2
  266. package/dist/cli/chunks/{types-GLRXY4RY.js → types-PYHUCVOZ.js} +2 -2
  267. package/dist/cli/chunks/unified-memory-OUVCMFGK.js +2 -0
  268. package/dist/cli/chunks/unified-memory-hnsw-YGQPOHXB.js +2 -0
  269. package/dist/cli/chunks/unified-persistence-GFRZVDOW.js +2 -0
  270. package/dist/cli/chunks/{upgrade-KU55H77X.js → upgrade-ONP2HNGL.js} +2 -2
  271. package/dist/cli/chunks/{validate-26VSBOJN.js → validate-NWSICDAY.js} +2 -2
  272. package/dist/cli/chunks/{validate-swarm-OIALRDKF.js → validate-swarm-KXS5P3U7.js} +2 -2
  273. package/dist/cli/chunks/{vibium-LOTWW25P.js → vibium-TZSGZRCQ.js} +2 -2
  274. package/dist/cli/chunks/visual-security-LVOOYQ64.js +2 -0
  275. package/dist/cli/chunks/{web-tree-sitter-6LWPPBYU.js → web-tree-sitter-V2FADNRA.js} +2 -2
  276. package/dist/cli/chunks/{windsurf-installer-ILOQYENG.js → windsurf-installer-GQM7KWDC.js} +2 -2
  277. package/dist/cli/chunks/{witness-chain-YBS6OHS4.js → witness-chain-GTITDIA2.js} +2 -2
  278. package/dist/cli/chunks/witness-chain-QNFPV4UL.js +2 -0
  279. package/dist/cli/chunks/{witness-key-manager-SI3WV3ZQ.js → witness-key-manager-AHRM2M52.js} +2 -2
  280. package/dist/cli/chunks/{workflow-GY6SJRQW.js → workflow-XCGHEL3I.js} +4 -4
  281. package/dist/cli/chunks/workflow-orchestrator-MIVBCALG.js +2 -0
  282. package/dist/cli/chunks/{wrappers-MMO5YKOZ.js → wrappers-VGO2GO4J.js} +2 -2
  283. package/dist/integrations/ruvector/brain-rvf-exporter.js +115 -13
  284. package/dist/integrations/ruvector/rvf-dual-writer.js +20 -3
  285. package/dist/integrations/ruvector/rvf-store-integrity.d.ts +49 -0
  286. package/dist/integrations/ruvector/rvf-store-integrity.js +137 -0
  287. package/dist/integrations/ruvector/shared-rvf-adapter.js +23 -5
  288. package/dist/learning/pattern-store.js +23 -5
  289. package/dist/learning/qe-flywheel/platform-signer.d.ts +32 -0
  290. package/dist/learning/qe-flywheel/platform-signer.js +60 -0
  291. package/dist/learning/qe-flywheel/receipt.js +9 -2
  292. package/dist/mcp/bundle.js +363 -363
  293. package/package.json +2 -2
  294. package/dist/cli/chunks/adapter-RL6GNUOS.js +0 -2
  295. package/dist/cli/chunks/aqe-learning-engine-UEEW6AQG.js +0 -2
  296. package/dist/cli/chunks/base-JQA5YULE.js +0 -2
  297. package/dist/cli/chunks/brain-handler-T7RDPKNM.js +0 -89
  298. package/dist/cli/chunks/browser-workflow-XTKUHTIT.js +0 -2
  299. package/dist/cli/chunks/chunk-KPV4N4KT.js +0 -9
  300. package/dist/cli/chunks/chunk-T75VH6NT.js +0 -2
  301. package/dist/cli/chunks/chunk-YY4KXDI6.js +0 -2
  302. package/dist/cli/chunks/client-S7DIRNFJ.js +0 -2
  303. package/dist/cli/chunks/core-handlers-NM2KCI6Z.js +0 -2
  304. package/dist/cli/chunks/cross-domain-router-3TSZMCBM.js +0 -2
  305. package/dist/cli/chunks/dream-QIIJONYI.js +0 -2
  306. package/dist/cli/chunks/heartbeat-scheduler-CDNGLJJO.js +0 -2
  307. package/dist/cli/chunks/hnsw-adapter-CR7Y4OAM.js +0 -2
  308. package/dist/cli/chunks/hnsw-index-TEDO4MQC.js +0 -2
  309. package/dist/cli/chunks/hybrid-router-O24ZDIP5.js +0 -2
  310. package/dist/cli/chunks/impact-analyzer-PDM4SDB6.js +0 -2
  311. package/dist/cli/chunks/init-wizard-F4KODPNW.js +0 -2
  312. package/dist/cli/chunks/kernel-77UM35L6.js +0 -2
  313. package/dist/cli/chunks/knowledge-graph-R6ZWWV2K.js +0 -2
  314. package/dist/cli/chunks/llm-router-service-7QYCZ66H.js +0 -2
  315. package/dist/cli/chunks/load-test-AWVA3CAQ.js +0 -2
  316. package/dist/cli/chunks/memory-backend-YESSIHFW.js +0 -2
  317. package/dist/cli/chunks/memory-handlers-EOOWSUHI.js +0 -2
  318. package/dist/cli/chunks/pattern-null-store-X3UXLJNL.js +0 -2
  319. package/dist/cli/chunks/protocol-executor-KXDCTMWI.js +0 -2
  320. package/dist/cli/chunks/provider-manager-XJZVHYI6.js +0 -2
  321. package/dist/cli/chunks/qe-reasoning-bank-DPHPNIC6.js +0 -2
  322. package/dist/cli/chunks/queen-coordinator-EVGWME5C.js +0 -2
  323. package/dist/cli/chunks/router-R2N7TMAS.js +0 -2
  324. package/dist/cli/chunks/routing-feedback-G6W3H26L.js +0 -2
  325. package/dist/cli/chunks/rvf-native-adapter-D7R2GWXK.js +0 -2
  326. package/dist/cli/chunks/safe-db-CQZGF2KA.js +0 -2
  327. package/dist/cli/chunks/schedule-UP7E3LRC.js +0 -2
  328. package/dist/cli/chunks/scheduler-ENIZHYSL.js +0 -2
  329. package/dist/cli/chunks/shared-rvf-adapter-HDDCXCHY.js +0 -2
  330. package/dist/cli/chunks/sqlite-persistence-CEVJVWS5.js +0 -2
  331. package/dist/cli/chunks/token-bootstrap-MQCTJURQ.js +0 -2
  332. package/dist/cli/chunks/unified-memory-PXOQ4N53.js +0 -2
  333. package/dist/cli/chunks/unified-memory-hnsw-VEXD6ASE.js +0 -2
  334. package/dist/cli/chunks/unified-persistence-46G6MZYC.js +0 -2
  335. package/dist/cli/chunks/visual-security-4X3T3MFL.js +0 -2
  336. package/dist/cli/chunks/witness-chain-XW4S3LVW.js +0 -2
  337. package/dist/cli/chunks/workflow-orchestrator-IIVV6TCP.js +0 -2
@@ -0,0 +1,2 @@
1
+ import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.12.3");process.exit(0)}
2
+ import{a,b,c,d}from"./chunk-PDX7IYTJ.js";import"./chunk-Y6XNISHP.js";import"./chunk-NOSQI2OW.js";import"./chunk-FJACKKRL.js";import"./chunk-L2X3BWMN.js";import"./chunk-G5OGKVLO.js";import"./chunk-4EHW4TNA.js";import"./chunk-NJDLJ3KD.js";import"./chunk-OBL6W4Z5.js";import"./chunk-NKTLKMUB.js";import"./chunk-2LNDU7AW.js";import"./chunk-EOUJ6X5H.js";import"./chunk-ULQCEM7K.js";import"./chunk-UAPUA6OY.js";import"./chunk-GS6G7AVS.js";import"./chunk-YUDGQZJN.js";import"./chunk-HJ4U64BL.js";import"./chunk-CYSBM52D.js";import"./chunk-NLDLUHOF.js";import"./chunk-PEHEANAM.js";import"./chunk-XUUVAAHV.js";import"./chunk-SGMJ277D.js";export{b as DEFAULT_WORKFLOW_CONFIG,a as WorkflowEvents,c as WorkflowOrchestrator,d as createWorkflowOrchestrator};
@@ -1,2 +1,2 @@
1
- import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.12.2");process.exit(0)}
2
- import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v as L,w as M,x as N}from"./chunk-VOHYQ6MX.js";import{a as v,b as w,c as x,d as y,e as z,f as A,g as B,h as C,i as D,j as E,k as F,l as G,m as H,n as I,o as J,p as K}from"./chunk-DTXHRALB.js";import"./chunk-APVXTHTA.js";import"./chunk-AL5QT6OX.js";import"./chunk-YY4KXDI6.js";import"./chunk-R5HC6JVJ.js";import"./chunk-ACDZ2CRV.js";import"./chunk-CKFZOPZN.js";import"./chunk-P65S7AZA.js";import"./chunk-X47GHZY3.js";import"./chunk-WRMUQVKY.js";import"./chunk-UF3YOGHV.js";import"./chunk-V2QYW5KW.js";import"./chunk-4KEOBDEI.js";import"./chunk-C7VNQ4PY.js";import"./chunk-QYST2TZW.js";import"./chunk-YZ44FUVJ.js";import"./chunk-YDZIPP3Y.js";import"./chunk-CTFW7CMI.js";import"./chunk-HU6ETNA7.js";export{z as GNNLayerFactory,i as QEFlashAttention,x as QEGNNEmbeddingIndex,y as QEGNNIndexFactory,a as QESONA,e as QE_FLASH_ATTENTION_CONFIG,g as QE_PERFORMANCE_TARGETS,f as QE_SONA_CONFIG,A as TensorCompressionFactory,u as batchComputeAttention,K as batchDifferentiableSearch,M as checkRuvectorPackagesAvailable,c as createDomainQESONA,j as createQEFlashAttention,b as createQESONA,D as getDifferentiableSearch,F as getGetCompressionLevel,E as getHierarchicalForward,G as getInit,h as getOptimalBlockConfig,k as getQEFlashAttentionConfig,n as getRuvectorDotProductAttention,m as getRuvectorFlashAttention,p as getRuvectorHyperbolicAttention,B as getRuvectorLayer,q as getRuvectorLinearAttention,r as getRuvectorMoEAttention,o as getRuvectorMultiHeadAttention,L as getRuvectorPackageVersions,C as getTensorCompress,l as getWorkloadTypes,N as initAllRuvectorPackages,w as initGNN,d as isAttentionAvailable,v as isGNNAvailable,s as toFloat32Array,H as toFloat32ArrayGNN,J as toIEmbedding,t as toNumberArrayAttn,I as toNumberArrayGNN};
1
+ import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.12.3");process.exit(0)}
2
+ import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v as L,w as M,x as N}from"./chunk-QILF6BZH.js";import{a as v,b as w,c as x,d as y,e as z,f as A,g as B,h as C,i as D,j as E,k as F,l as G,m as H,n as I,o as J,p as K}from"./chunk-YOG5KQZF.js";import"./chunk-NOSQI2OW.js";import"./chunk-FJACKKRL.js";import"./chunk-L2X3BWMN.js";import"./chunk-G5OGKVLO.js";import"./chunk-4EHW4TNA.js";import"./chunk-NJDLJ3KD.js";import"./chunk-OBL6W4Z5.js";import"./chunk-2LNDU7AW.js";import"./chunk-ULQCEM7K.js";import"./chunk-UAPUA6OY.js";import"./chunk-GS6G7AVS.js";import"./chunk-YUDGQZJN.js";import"./chunk-HJ4U64BL.js";import"./chunk-CYSBM52D.js";import"./chunk-NLDLUHOF.js";import"./chunk-PEHEANAM.js";import"./chunk-XUUVAAHV.js";import"./chunk-SGMJ277D.js";export{z as GNNLayerFactory,i as QEFlashAttention,x as QEGNNEmbeddingIndex,y as QEGNNIndexFactory,a as QESONA,e as QE_FLASH_ATTENTION_CONFIG,g as QE_PERFORMANCE_TARGETS,f as QE_SONA_CONFIG,A as TensorCompressionFactory,u as batchComputeAttention,K as batchDifferentiableSearch,M as checkRuvectorPackagesAvailable,c as createDomainQESONA,j as createQEFlashAttention,b as createQESONA,D as getDifferentiableSearch,F as getGetCompressionLevel,E as getHierarchicalForward,G as getInit,h as getOptimalBlockConfig,k as getQEFlashAttentionConfig,n as getRuvectorDotProductAttention,m as getRuvectorFlashAttention,p as getRuvectorHyperbolicAttention,B as getRuvectorLayer,q as getRuvectorLinearAttention,r as getRuvectorMoEAttention,o as getRuvectorMultiHeadAttention,L as getRuvectorPackageVersions,C as getTensorCompress,l as getWorkloadTypes,N as initAllRuvectorPackages,w as initGNN,d as isAttentionAvailable,v as isGNNAvailable,s as toFloat32Array,H as toFloat32ArrayGNN,J as toIEmbedding,t as toNumberArrayAttn,I as toNumberArrayGNN};
@@ -3,11 +3,82 @@
3
3
  * `.rvf` file using the @ruvector/rvf-node native binding via rvf-native-adapter.
4
4
  * Falls back to JSONL directory format when the native binding is unavailable.
5
5
  */
6
- import { existsSync, statSync, unlinkSync, writeFileSync } from 'fs';
7
- import { resolve } from 'path';
6
+ import { existsSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from 'fs';
7
+ import { basename, dirname, join, resolve } from 'path';
8
8
  import { createRvfStore, openRvfStore, openRvfStoreReadonly, isRvfNativeAvailable, } from './rvf-native-adapter.js';
9
9
  import { sha256, tableExists, queryAll, domainFilterForColumn, ensureTargetTables, mergeGenericRow, mergeAppendOnlyRow, TABLE_CONFIGS, TABLE_BLOB_COLUMNS, PK_COLUMNS, CONFIDENCE_COLUMNS, TIMESTAMP_COLUMNS, serializeRowBlobs, deserializeRowBlobs, } from './brain-shared.js';
10
10
  // --- Export ---
11
+ /**
12
+ * Sidecar suffixes that make up a complete store on disk. `''` is the store
13
+ * itself; the adapter writes `.idmap.json` on close, and we write the manifest.
14
+ */
15
+ const RVF_STORE_SUFFIXES = ['', '.idmap.json', '.manifest.json'];
16
+ /**
17
+ * Everything an abandoned tmp export can leave behind. `.lock` is cleaned up
18
+ * but deliberately absent from RVF_STORE_SUFFIXES — renaming a lock into the
19
+ * final path is the very corruption this fix exists to prevent.
20
+ */
21
+ const RVF_CLEANUP_SUFFIXES = [...RVF_STORE_SUFFIXES, '.lock'];
22
+ /** Best-effort removal of a store and its sidecars at `base`. */
23
+ function removeStoreFiles(base) {
24
+ for (const suffix of RVF_CLEANUP_SUFFIXES) {
25
+ try {
26
+ const p = `${base}${suffix}`;
27
+ if (existsSync(p))
28
+ unlinkSync(p);
29
+ }
30
+ catch {
31
+ // best-effort — a leftover tmp is inert, unlike a corrupt final store
32
+ }
33
+ }
34
+ }
35
+ /**
36
+ * Remove tmp stores orphaned by killed exports (#563). Each interrupted export
37
+ * strands a full-size tmp store, so on a project where the checkpoint hook is
38
+ * killed regularly these would accumulate unbounded.
39
+ *
40
+ * Only tmps whose owning pid is gone are removed: a live pid means a concurrent
41
+ * export is mid-write, and deleting its tmp would corrupt exactly what this
42
+ * change exists to protect.
43
+ */
44
+ function sweepStaleTmpFiles(outPath) {
45
+ const dir = dirname(outPath);
46
+ const prefix = `${basename(outPath)}.tmp.`;
47
+ let entries;
48
+ try {
49
+ entries = readdirSync(dir);
50
+ }
51
+ catch {
52
+ return;
53
+ }
54
+ for (const entry of entries) {
55
+ if (!entry.startsWith(prefix))
56
+ continue;
57
+ // `<name>.rvf.tmp.<pid>` and its `<...>.tmp.<pid>.idmap.json` siblings.
58
+ const pid = Number.parseInt(entry.slice(prefix.length).split('.')[0], 10);
59
+ if (!Number.isInteger(pid) || pid <= 0)
60
+ continue;
61
+ if (pid !== process.pid && isPidAlive(pid))
62
+ continue;
63
+ try {
64
+ unlinkSync(join(dir, entry));
65
+ }
66
+ catch {
67
+ // best-effort
68
+ }
69
+ }
70
+ }
71
+ /** True when a process with `pid` exists (signal 0 probes without delivering). */
72
+ function isPidAlive(pid) {
73
+ try {
74
+ process.kill(pid, 0);
75
+ return true;
76
+ }
77
+ catch (err) {
78
+ // EPERM means it exists but belongs to another user — still alive.
79
+ return err.code === 'EPERM';
80
+ }
81
+ }
11
82
  /** Export brain state to a single `.rvf` file with vector embeddings + kernel. */
12
83
  export function exportBrainToRvf(db, options, sourceDbLabel = 'memory.db') {
13
84
  if (!isRvfNativeAvailable()) {
@@ -15,14 +86,20 @@ export function exportBrainToRvf(db, options, sourceDbLabel = 'memory.db') {
15
86
  }
16
87
  const outPath = resolve(options.outputPath);
17
88
  const dimension = options.dimension ?? 384;
18
- // Clean up any existing file
19
- if (existsSync(outPath))
20
- unlinkSync(outPath);
21
- const idmapPath = `${outPath}.idmap.json`;
22
- if (existsSync(idmapPath))
23
- unlinkSync(idmapPath);
89
+ // Issue #563: build the store at a private tmp path and rename it over the
90
+ // final path only once it is closed and complete. The previous code deleted
91
+ // the old store and then built the new one in place, so any interruption
92
+ // (hook timeout, session teardown, SIGKILL) left a created-but-incomplete
93
+ // store that could neither be opened (ManifestNotFound) nor created over
94
+ // (FsyncFailed) — permanently disabling the RVF backend. With tmp+rename an
95
+ // interrupted export leaves the *previous* good store untouched and orphans
96
+ // only an inert tmp file, which the next export sweeps.
97
+ const tmpPath = `${outPath}.tmp.${process.pid}`;
98
+ sweepStaleTmpFiles(outPath);
99
+ removeStoreFiles(tmpPath);
24
100
  // Create RVF container via adapter (handles idmap automatically)
25
- const rvf = createRvfStore(outPath, dimension);
101
+ const rvf = createRvfStore(tmpPath, dimension);
102
+ let closed = false;
26
103
  try {
27
104
  // --- Export all tables using TABLE_CONFIGS ---
28
105
  const allTableData = {};
@@ -153,12 +230,37 @@ export function exportBrainToRvf(db, options, sourceDbLabel = 'memory.db') {
153
230
  catch { /* best-effort */ }
154
231
  }
155
232
  // Persist manifest as sidecar JSON alongside the .rvf file
156
- const manifestPath = `${outPath}.manifest.json`;
157
- writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');
233
+ writeFileSync(`${tmpPath}.manifest.json`, JSON.stringify(manifest, null, 2), 'utf-8');
234
+ // Close before promoting: close() flushes the store and writes the idmap
235
+ // sidecar, so renaming any earlier would publish an incomplete store.
236
+ rvf.close();
237
+ closed = true;
238
+ // Promote tmp → final. The store itself goes last: until it lands, the
239
+ // previous store (if any) is still the one on disk, and a crash mid-promote
240
+ // leaves the old store readable rather than a half-written new one.
241
+ for (const suffix of [...RVF_STORE_SUFFIXES].reverse()) {
242
+ const from = `${tmpPath}${suffix}`;
243
+ const to = `${outPath}${suffix}`;
244
+ if (existsSync(from)) {
245
+ renameSync(from, to);
246
+ }
247
+ else if (existsSync(to)) {
248
+ // No new sidecar produced — drop the stale one so it can't be read
249
+ // against the new store.
250
+ unlinkSync(to);
251
+ }
252
+ }
158
253
  return manifest;
159
254
  }
160
- finally {
161
- rvf.close();
255
+ catch (err) {
256
+ if (!closed) {
257
+ try {
258
+ rvf.close();
259
+ }
260
+ catch { /* best-effort */ }
261
+ }
262
+ removeStoreFiles(tmpPath);
263
+ throw err;
162
264
  }
163
265
  }
164
266
  /** Legacy field-to-table mapping for older RVF exports. */
@@ -87,14 +87,31 @@ export class RvfDualWriter {
87
87
  nativeAdapter = adapter.openRvfStore(this.config.rvfPath);
88
88
  }
89
89
  catch {
90
- nativeAdapter = adapter.createRvfStore(this.config.rvfPath, this.config.dimensions);
90
+ try {
91
+ nativeAdapter = adapter.createRvfStore(this.config.rvfPath, this.config.dimensions);
92
+ }
93
+ catch (createErr) {
94
+ // Issue #563: open failed *and* create failed, so the file on disk is
95
+ // provably unusable — the signature of an export killed mid-write
96
+ // (open → ManifestNotFound, create → FsyncFailed because the path
97
+ // exists). Previously this fell to the catch below and disabled RVF
98
+ // silently for the whole run. Quarantine and rebuild instead.
99
+ const { quarantineUnusableStore } = await import('./rvf-store-integrity.js');
100
+ const quarantined = quarantineUnusableStore(this.config.rvfPath, createErr instanceof Error ? createErr.message : String(createErr));
101
+ if (!quarantined)
102
+ throw createErr; // live peer, or nothing to move
103
+ nativeAdapter = adapter.createRvfStore(this.config.rvfPath, this.config.dimensions);
104
+ }
91
105
  }
92
106
  this.rvfStore = wrapNativeAdapter(nativeAdapter, this.config.dimensions);
93
107
  this.rvfAvailable = true;
94
108
  }
95
- catch {
96
- // Native adapter module not available at all
109
+ catch (err) {
110
+ // Native adapter unavailable, or recovery itself failed. Degrade to
111
+ // sqlite-only — but say so, instead of vanishing silently (#563).
97
112
  this.rvfAvailable = false;
113
+ console.warn(`[RVF] Dual-writer disabled for ${this.config.rvfPath}; falling back to SQLite: ` +
114
+ `${err instanceof Error ? err.message : String(err)}`);
98
115
  }
99
116
  }
100
117
  /**
@@ -0,0 +1,49 @@
1
+ /**
2
+ * RVF store integrity helpers (issue #563).
3
+ *
4
+ * An export that is killed mid-write leaves a store that was created but never
5
+ * completed. Such a file cannot be opened (`RVF error 0x0106: ManifestNotFound`)
6
+ * and cannot be created over either, because the path already exists
7
+ * (`RVF error 0x0303: FsyncFailed`). Both paths fail forever, so the RVF
8
+ * backend stays disabled for the life of the project until someone deletes the
9
+ * file by hand.
10
+ *
11
+ * Recovery has to be evidence-based rather than fingerprint-based. Measured
12
+ * against @ruvector/rvf-node 0.1.8:
13
+ *
14
+ * • A *valid, empty* store is 162 bytes with magic `SFVR` — byte-for-byte
15
+ * the size the issue reports as "truncated: header only". Size and magic
16
+ * therefore cannot distinguish a broken store from a healthy empty one.
17
+ * • `<store>.lock` is a 104-byte record with magic `FLVR` and the owning pid
18
+ * as a little-endian u32 at offset 4. `FLVR` in a lock is the *normal*
19
+ * case — the issue reads it as "RVF store bytes leaked into the lock", but
20
+ * the store magic is `SFVR`; a 104-byte `FLVR` lock is just a live-or-stale
21
+ * lock record.
22
+ *
23
+ * So the only sound trigger is "open failed *and* create failed": at that point
24
+ * the file is provably unusable. The lock's pid is used as a *guard* — if it is
25
+ * held by a live process, the store is presumed healthy and left alone.
26
+ */
27
+ /** The pid recorded in `<rvfPath>.lock`, or null if there is no readable lock. */
28
+ export declare function readLockOwnerPid(rvfPath: string): number | null;
29
+ /**
30
+ * True when the store's lock is held by a process that is still running.
31
+ *
32
+ * Deliberately conservative: an unreadable or pid-less lock reports false (the
33
+ * caller's open already failed, so there is nothing to protect), while a live
34
+ * pid reports true and blocks recovery. Pid reuse can only produce a false
35
+ * "alive", which fails safe — we leave the store alone.
36
+ */
37
+ export declare function isLockHeldByLiveProcess(rvfPath: string): boolean;
38
+ /**
39
+ * Move an unusable store and its sidecars aside so the next create succeeds.
40
+ * Returns the quarantine base path, or null if nothing was quarantined.
41
+ *
42
+ * Only call this once open *and* create have both failed — that is the proof
43
+ * the file is unusable. The store is a derived cache, rebuilt from the unified
44
+ * DB, so quarantining is recoverable; we move rather than delete because the
45
+ * bytes may hold writes that never reached SQLite, and they are the only
46
+ * evidence if this recurs.
47
+ */
48
+ export declare function quarantineUnusableStore(rvfPath: string, reason: string): string | null;
49
+ //# sourceMappingURL=rvf-store-integrity.d.ts.map
@@ -0,0 +1,137 @@
1
+ /**
2
+ * RVF store integrity helpers (issue #563).
3
+ *
4
+ * An export that is killed mid-write leaves a store that was created but never
5
+ * completed. Such a file cannot be opened (`RVF error 0x0106: ManifestNotFound`)
6
+ * and cannot be created over either, because the path already exists
7
+ * (`RVF error 0x0303: FsyncFailed`). Both paths fail forever, so the RVF
8
+ * backend stays disabled for the life of the project until someone deletes the
9
+ * file by hand.
10
+ *
11
+ * Recovery has to be evidence-based rather than fingerprint-based. Measured
12
+ * against @ruvector/rvf-node 0.1.8:
13
+ *
14
+ * • A *valid, empty* store is 162 bytes with magic `SFVR` — byte-for-byte
15
+ * the size the issue reports as "truncated: header only". Size and magic
16
+ * therefore cannot distinguish a broken store from a healthy empty one.
17
+ * • `<store>.lock` is a 104-byte record with magic `FLVR` and the owning pid
18
+ * as a little-endian u32 at offset 4. `FLVR` in a lock is the *normal*
19
+ * case — the issue reads it as "RVF store bytes leaked into the lock", but
20
+ * the store magic is `SFVR`; a 104-byte `FLVR` lock is just a live-or-stale
21
+ * lock record.
22
+ *
23
+ * So the only sound trigger is "open failed *and* create failed": at that point
24
+ * the file is provably unusable. The lock's pid is used as a *guard* — if it is
25
+ * held by a live process, the store is presumed healthy and left alone.
26
+ */
27
+ import { existsSync, openSync, readSync, closeSync, renameSync, unlinkSync } from 'fs';
28
+ /** Magic of a lock record (the store's own magic is `SFVR`). */
29
+ const LOCK_MAGIC = 'FLVR';
30
+ /** Byte offset of the owning pid within a lock record (u32 LE). */
31
+ const LOCK_PID_OFFSET = 4;
32
+ /** Sidecars that belong to a store and must be quarantined alongside it. */
33
+ const STORE_SIDECAR_SUFFIXES = ['', '.idmap.json', '.manifest.json'];
34
+ /** Read the first `n` bytes of a file, or null if unreadable/shorter. */
35
+ function readHead(path, n) {
36
+ let fd;
37
+ try {
38
+ fd = openSync(path, 'r');
39
+ const buf = Buffer.alloc(n);
40
+ if (readSync(fd, buf, 0, n, 0) < n)
41
+ return null;
42
+ return buf;
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ finally {
48
+ if (fd !== undefined) {
49
+ try {
50
+ closeSync(fd);
51
+ }
52
+ catch { /* best-effort */ }
53
+ }
54
+ }
55
+ }
56
+ /** True when a process with `pid` exists (signal 0 probes without delivering). */
57
+ function isPidAlive(pid) {
58
+ try {
59
+ process.kill(pid, 0);
60
+ return true;
61
+ }
62
+ catch (err) {
63
+ // EPERM means it exists but belongs to another user — still alive.
64
+ return err.code === 'EPERM';
65
+ }
66
+ }
67
+ /** The pid recorded in `<rvfPath>.lock`, or null if there is no readable lock. */
68
+ export function readLockOwnerPid(rvfPath) {
69
+ const head = readHead(`${rvfPath}.lock`, LOCK_PID_OFFSET + 4);
70
+ if (!head || head.subarray(0, 4).toString('latin1') !== LOCK_MAGIC)
71
+ return null;
72
+ const pid = head.readUInt32LE(LOCK_PID_OFFSET);
73
+ return pid > 0 ? pid : null;
74
+ }
75
+ /**
76
+ * True when the store's lock is held by a process that is still running.
77
+ *
78
+ * Deliberately conservative: an unreadable or pid-less lock reports false (the
79
+ * caller's open already failed, so there is nothing to protect), while a live
80
+ * pid reports true and blocks recovery. Pid reuse can only produce a false
81
+ * "alive", which fails safe — we leave the store alone.
82
+ */
83
+ export function isLockHeldByLiveProcess(rvfPath) {
84
+ const pid = readLockOwnerPid(rvfPath);
85
+ if (pid === null)
86
+ return false;
87
+ return pid !== process.pid && isPidAlive(pid);
88
+ }
89
+ /**
90
+ * Move an unusable store and its sidecars aside so the next create succeeds.
91
+ * Returns the quarantine base path, or null if nothing was quarantined.
92
+ *
93
+ * Only call this once open *and* create have both failed — that is the proof
94
+ * the file is unusable. The store is a derived cache, rebuilt from the unified
95
+ * DB, so quarantining is recoverable; we move rather than delete because the
96
+ * bytes may hold writes that never reached SQLite, and they are the only
97
+ * evidence if this recurs.
98
+ */
99
+ export function quarantineUnusableStore(rvfPath, reason) {
100
+ if (!existsSync(rvfPath))
101
+ return null;
102
+ // Never pull a store out from under a live peer.
103
+ if (isLockHeldByLiveProcess(rvfPath)) {
104
+ console.warn(`[RVF] ${rvfPath} is unusable but its lock is held by a live process — ` +
105
+ 'leaving it alone and degrading to SQLite for this run.');
106
+ return null;
107
+ }
108
+ // Keyed by pid, not a timestamp: a crash-loop quarantining the same file
109
+ // repeatedly overwrites its own copy instead of filling .agentic-qe/ with
110
+ // one corrupt store per startup.
111
+ const quarantineBase = `${rvfPath}.corrupt-${process.pid}`;
112
+ for (const sidecar of STORE_SIDECAR_SUFFIXES) {
113
+ const from = `${rvfPath}${sidecar}`;
114
+ if (!existsSync(from))
115
+ continue;
116
+ try {
117
+ renameSync(from, `${quarantineBase}${sidecar}`);
118
+ }
119
+ catch {
120
+ // A failed quarantine must not throw and take down the caller; the
121
+ // caller's retry will simply fail again and degrade as before.
122
+ }
123
+ }
124
+ // The store is gone, so its lock — stale by definition here — goes with it.
125
+ try {
126
+ if (existsSync(`${rvfPath}.lock`))
127
+ unlinkSync(`${rvfPath}.lock`);
128
+ }
129
+ catch {
130
+ // best-effort
131
+ }
132
+ console.warn(`[RVF] Quarantined unusable store ${rvfPath} → ${quarantineBase} (${reason}). ` +
133
+ 'It is a derived cache and will be rebuilt from the unified DB. ' +
134
+ 'Please report a recurrence with the quarantined files (issue #563).');
135
+ return quarantineBase;
136
+ }
137
+ //# sourceMappingURL=rvf-store-integrity.js.map
@@ -13,6 +13,9 @@
13
13
  // Issue #516: lightweight, sqlite-free project-root resolver (static import so it
14
14
  // resolves under the test runner; avoids pulling unified-memory's sqlite graph).
15
15
  import { findProjectRoot } from '../../kernel/project-root.js';
16
+ // Issue #563: static import — this module is fs-only, and a require() here
17
+ // would not resolve under the test runner.
18
+ import { quarantineUnusableStore, isLockHeldByLiveProcess, readLockOwnerPid, } from './rvf-store-integrity.js';
16
19
  let sharedAdapter = null;
17
20
  let initAttempted = false;
18
21
  // ---------------------------------------------------------------------------
@@ -131,16 +134,23 @@ function openOrCreateRvf(openFn, createFn, rvfPath, dimensions) {
131
134
  // .lock that subsequent invocations interpret as `LockHeld`. Since AQE
132
135
  // CLI is overwhelmingly single-shot serial, the realistic case is "the
133
136
  // prior process is dead and the lock is stale". We unlink the .lock and
134
- // retry open exactly once. If a genuinely-live peer existed, it still
135
- // holds the file open — but the binding's lock is content-based (lock
136
- // file presence), so this is a best-effort cooperative recovery rather
137
- // than an OS-level lock break.
137
+ // retry open exactly once.
138
+ //
139
+ // Issue #563: the lock record turns out to carry its owner's pid (u32 LE at
140
+ // offset 4, after the `FLVR` magic), so "is it stale?" is now a check rather
141
+ // than an assumption. This previously unlinked the lock unconditionally,
142
+ // which breaks a genuinely-live peer — the one case the old comment admitted
143
+ // it could not distinguish.
138
144
  if (!opened && isLockHeld(openErr)) {
139
145
  try {
140
146
  // eslint-disable-next-line @typescript-eslint/no-require-imports
141
147
  const fs = require('fs');
142
148
  const lockPath = `${rvfPath}.lock`;
143
- if (fs.existsSync(lockPath)) {
149
+ if (fs.existsSync(lockPath) && isLockHeldByLiveProcess(rvfPath)) {
150
+ console.warn(`[RVF] ${rvfPath} is locked by a live process (pid ${readLockOwnerPid(rvfPath)}) — ` +
151
+ 'not breaking the lock; degrading to SQLite for this run.');
152
+ }
153
+ else if (fs.existsSync(lockPath)) {
144
154
  fs.unlinkSync(lockPath);
145
155
  console.warn(`[RVF] Removed stale lock file at ${lockPath} (prior process exited without closing). ` +
146
156
  'Retrying open. If you see this repeatedly under live concurrency, file an issue.');
@@ -187,6 +197,14 @@ function openOrCreateRvf(openFn, createFn, rvfPath, dimensions) {
187
197
  return reopened;
188
198
  }
189
199
  catch {
200
+ // Pass 4 (#563): open failed, create failed, re-open failed. The file is
201
+ // provably unusable — the signature of an export killed mid-write, which
202
+ // used to disable the RVF backend permanently. Quarantine it (unless a
203
+ // live process holds its lock) and rebuild the derived cache.
204
+ const quarantined = quarantineUnusableStore(rvfPath, createErr instanceof Error ? createErr.message : String(createErr));
205
+ if (quarantined) {
206
+ return createFn(rvfPath, dimensions);
207
+ }
190
208
  // Fall through with the more informative original error.
191
209
  throw createErr instanceof Error ? createErr : new Error(String(createErr));
192
210
  }
@@ -11,7 +11,13 @@ import { v4 as uuidv4 } from 'uuid';
11
11
  import { findProjectRoot } from '../kernel/project-root.js';
12
12
  import { ok, err } from '../shared/types/index.js';
13
13
  import { RvfPatternStore } from './rvf-pattern-store.js';
14
- import { createRvfStore as _createRvfStore, isRvfNativeAvailable } from '../integrations/ruvector/rvf-native-adapter.js';
14
+ import { createRvfStore as _createRvfStore, openRvfStore as _openRvfStore, isRvfNativeAvailable, } from '../integrations/ruvector/rvf-native-adapter.js';
15
+ // Issue #563: static imports — a require() of a source module resolves in the
16
+ // esbuild bundle but throws under the test runner, which silently changed which
17
+ // code path tests exercised. Neither module loads the native binding at import
18
+ // time, so this costs nothing at startup.
19
+ import { quarantineUnusableStore } from '../integrations/ruvector/rvf-store-integrity.js';
20
+ import { getSharedRvfAdapter } from '../integrations/ruvector/shared-rvf-adapter.js';
15
21
  import { toErrorMessage, toError } from '../shared/error-utils.js';
16
22
  import { calculateQualityScore, shouldPromotePattern, validateQEPattern, mapQEDomainToAQE, PROMOTION_THRESHOLD, } from './qe-patterns.js';
17
23
  import { applyFilterSync } from '../integrations/ruvector/filter-adapter.js';
@@ -1419,7 +1425,9 @@ export function createPatternStore(memory, config) {
1419
1425
  // deadlock on the native lock.
1420
1426
  let useSharedAdapter = false;
1421
1427
  try {
1422
- const { getSharedRvfAdapter } = require('../integrations/ruvector/shared-rvf-adapter.js');
1428
+ // Statically imported (#563): this require() throws "Cannot find
1429
+ // module" under the test runner, so every test silently took the
1430
+ // fallback ladder below instead of this preferred path.
1423
1431
  const shared = getSharedRvfAdapter(rvfDir, mergedConfig.embeddingDimension);
1424
1432
  if (shared) {
1425
1433
  useSharedAdapter = true;
@@ -1439,11 +1447,13 @@ export function createPatternStore(memory, config) {
1439
1447
  // open first, fall back to create, retry open on create-race.
1440
1448
  // (Jordi #439 / RUFLO P020.)
1441
1449
  const store = new RvfPatternStore((path, dim) => {
1442
- // eslint-disable-next-line @typescript-eslint/no-require-imports
1443
- const { openRvfStore } = require('../integrations/ruvector/rvf-native-adapter.js');
1450
+ // Statically imported (#563): a require() here resolves in the
1451
+ // esbuild bundle but throws "Cannot find module" under the test
1452
+ // runner, so this ladder — including its corruption recovery —
1453
+ // was unreachable from any test.
1444
1454
  const tryOpen = () => {
1445
1455
  try {
1446
- return openRvfStore(path);
1456
+ return _openRvfStore(path);
1447
1457
  }
1448
1458
  catch {
1449
1459
  return null;
@@ -1467,6 +1477,14 @@ export function createPatternStore(memory, config) {
1467
1477
  adapter = tryOpen();
1468
1478
  if (adapter && adapter.dimension() === dim)
1469
1479
  return adapter;
1480
+ // Issue #563: open failed, create failed, re-open failed — the
1481
+ // store is provably unusable (an export killed mid-write leaves
1482
+ // exactly this). Without recovery, RvfPatternStore.initialize()
1483
+ // logs "vector search is DISABLED" and stays that way for the
1484
+ // life of the process.
1485
+ if (quarantineUnusableStore(path, createErr instanceof Error ? createErr.message : String(createErr))) {
1486
+ return _createRvfStore(path, dim);
1487
+ }
1470
1488
  throw createErr;
1471
1489
  }
1472
1490
  }, { rvfPath, base: mergedConfig });
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Witness-key bridge (qe-harness issue #7) — sign flywheel receipts with the ONE
3
+ * Cognitum platform identity instead of a self-generated key, so every QE receipt
4
+ * (engine campaign · flywheel promotion · coherence verdict) chains to the same
5
+ * externally-verifiable key (`QE_WITNESS_PUBLIC_KEYS_JSON` allowlist, fingerprint
6
+ * `f1ac28607da49ec1`).
7
+ *
8
+ * `createSigner` already accepts a 32-byte Ed25519 seed → deterministic keypair.
9
+ * The platform key is delivered as `QE_WITNESS_SIGNING_KEY` — a JSON
10
+ * `{ publicKey, privateKey }` of PEM strings (same shape qe-harness Stage-B reads
11
+ * from Secret Manager). We derive the seed from that private key and hand it to
12
+ * `createSigner`, reproducing the exact platform keypair.
13
+ *
14
+ * Graceful: returns null when the env var is absent/malformed, so the flywheel
15
+ * keeps its self-generated-key behaviour where the platform key isn't provided.
16
+ * Env-reading lives HERE, not in the dependency-free `receipt.ts` core.
17
+ */
18
+ import { type Signer } from './receipt.js';
19
+ /**
20
+ * Extract the raw 32-byte Ed25519 seed from a PKCS#8 private-key PEM. Throws if the
21
+ * key is not an Ed25519 PKCS#8 key (wrong curve / format).
22
+ */
23
+ export declare function seedFromPkcs8Pem(privateKeyPem: string): Buffer;
24
+ /**
25
+ * Build a {@link Signer} bound to the Cognitum platform identity from
26
+ * `QE_WITNESS_SIGNING_KEY`, or null when it is unset/malformed (graceful fallback).
27
+ * The returned signer's `keyId` equals the platform witness fingerprint, so a
28
+ * verifier can attribute the receipt to the platform via the same allowlist that
29
+ * accepts qe-harness evidence bundles.
30
+ */
31
+ export declare function platformSigner(env?: NodeJS.ProcessEnv): Signer | null;
32
+ //# sourceMappingURL=platform-signer.d.ts.map
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Witness-key bridge (qe-harness issue #7) — sign flywheel receipts with the ONE
3
+ * Cognitum platform identity instead of a self-generated key, so every QE receipt
4
+ * (engine campaign · flywheel promotion · coherence verdict) chains to the same
5
+ * externally-verifiable key (`QE_WITNESS_PUBLIC_KEYS_JSON` allowlist, fingerprint
6
+ * `f1ac28607da49ec1`).
7
+ *
8
+ * `createSigner` already accepts a 32-byte Ed25519 seed → deterministic keypair.
9
+ * The platform key is delivered as `QE_WITNESS_SIGNING_KEY` — a JSON
10
+ * `{ publicKey, privateKey }` of PEM strings (same shape qe-harness Stage-B reads
11
+ * from Secret Manager). We derive the seed from that private key and hand it to
12
+ * `createSigner`, reproducing the exact platform keypair.
13
+ *
14
+ * Graceful: returns null when the env var is absent/malformed, so the flywheel
15
+ * keeps its self-generated-key behaviour where the platform key isn't provided.
16
+ * Env-reading lives HERE, not in the dependency-free `receipt.ts` core.
17
+ */
18
+ import { createPrivateKey } from 'node:crypto';
19
+ import { createSigner } from './receipt.js';
20
+ /** DER prefix of an Ed25519 PKCS#8 private key (16 bytes) preceding the 32-byte seed. */
21
+ const ED25519_PKCS8_PREFIX = '302e020100300506032b657004220420';
22
+ /**
23
+ * Extract the raw 32-byte Ed25519 seed from a PKCS#8 private-key PEM. Throws if the
24
+ * key is not an Ed25519 PKCS#8 key (wrong curve / format).
25
+ */
26
+ export function seedFromPkcs8Pem(privateKeyPem) {
27
+ const der = createPrivateKey(privateKeyPem).export({ format: 'der', type: 'pkcs8' });
28
+ if (der.length !== 48 || der.subarray(0, 16).toString('hex') !== ED25519_PKCS8_PREFIX) {
29
+ throw new Error('not an Ed25519 PKCS#8 private key (cannot derive a 32-byte seed)');
30
+ }
31
+ return Buffer.from(der.subarray(16, 48));
32
+ }
33
+ /**
34
+ * Build a {@link Signer} bound to the Cognitum platform identity from
35
+ * `QE_WITNESS_SIGNING_KEY`, or null when it is unset/malformed (graceful fallback).
36
+ * The returned signer's `keyId` equals the platform witness fingerprint, so a
37
+ * verifier can attribute the receipt to the platform via the same allowlist that
38
+ * accepts qe-harness evidence bundles.
39
+ */
40
+ export function platformSigner(env = process.env) {
41
+ const raw = env.QE_WITNESS_SIGNING_KEY;
42
+ if (!raw)
43
+ return null;
44
+ let key;
45
+ try {
46
+ key = JSON.parse(raw);
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ if (!key.privateKey)
52
+ return null;
53
+ try {
54
+ return createSigner(seedFromPkcs8Pem(key.privateKey));
55
+ }
56
+ catch {
57
+ return null; // wrong key type / unparseable — fall back to a self-generated signer
58
+ }
59
+ }
60
+ //# sourceMappingURL=platform-signer.js.map
@@ -10,9 +10,16 @@
10
10
  * Ed25519 via Node's built-in crypto — dependency-free (ADR-118 §6).
11
11
  */
12
12
  import { generateKeyPairSync, createPrivateKey, createPublicKey, sign as edSign, verify as edVerify, createHash, } from 'node:crypto';
13
- /** Derive a stable key id from a public key PEM. */
13
+ /**
14
+ * Derive a stable key id from a public key PEM. The PEM is trimmed first so the id
15
+ * is invariant to trailing whitespace (PEM exports carry a trailing newline) AND
16
+ * matches the Cognitum platform witness fingerprint scheme — `sha256(pem.trim())`
17
+ * truncated to 16 hex (qe-harness `witness.ts` / meta-llm `qe-witness.ts`). This lets
18
+ * a flywheel receipt signed with the platform key carry the SAME id the platform
19
+ * allowlist (`QE_WITNESS_PUBLIC_KEYS_JSON`) recognizes. See platform-signer.ts.
20
+ */
14
21
  function keyIdOf(publicKeyPem) {
15
- return createHash('sha256').update(publicKeyPem).digest('hex').slice(0, 16);
22
+ return createHash('sha256').update(publicKeyPem.trim()).digest('hex').slice(0, 16);
16
23
  }
17
24
  /**
18
25
  * Create an Ed25519 signer. With a 32-byte seed (hex or Buffer) the keypair is