@remnic/core 1.1.11 → 1.1.13

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 (1462) hide show
  1. package/README.md +3 -3
  2. package/dist/access-cli.d.ts +2 -1
  3. package/dist/access-cli.js +293 -104
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +31 -62
  6. package/dist/access-http.js +53 -35
  7. package/dist/access-mcp.d.ts +31 -8
  8. package/dist/access-mcp.js +45 -34
  9. package/dist/access-schema.d.ts +197 -14
  10. package/dist/access-schema.js +16 -5
  11. package/dist/access-service-DcCDmNYC.d.ts +1542 -0
  12. package/dist/access-service.d.ts +30 -9
  13. package/dist/access-service.js +42 -32
  14. package/dist/action-confidence.d.ts +83 -0
  15. package/dist/action-confidence.js +22 -0
  16. package/dist/active-memory-bridge.d.ts +1 -1
  17. package/dist/active-memory-bridge.js +2 -2
  18. package/dist/active-recall.d.ts +1 -1
  19. package/dist/active-recall.js +11 -3
  20. package/dist/active-recall.js.map +1 -1
  21. package/dist/adapters/claude-code.d.ts +24 -0
  22. package/dist/adapters/claude-code.js +9 -0
  23. package/dist/adapters/codex.d.ts +25 -0
  24. package/dist/adapters/codex.js +9 -0
  25. package/dist/adapters/hermes.d.ts +35 -0
  26. package/dist/adapters/hermes.js +9 -0
  27. package/dist/adapters/index.d.ts +6 -0
  28. package/dist/adapters/index.js +26 -0
  29. package/dist/adapters/registry.d.ts +20 -0
  30. package/dist/adapters/registry.js +13 -0
  31. package/dist/adapters/replit.d.ts +28 -0
  32. package/dist/adapters/replit.js +9 -0
  33. package/dist/adapters/types.d.ts +43 -0
  34. package/dist/adapters/types.js +8 -0
  35. package/dist/behavior-learner.d.ts +1 -1
  36. package/dist/behavior-signals.d.ts +1 -1
  37. package/dist/bootstrap.d.ts +23 -6
  38. package/dist/boxes.d.ts +7 -0
  39. package/dist/boxes.js +1 -1
  40. package/dist/briefing.d.ts +5 -3
  41. package/dist/briefing.js +10 -7
  42. package/dist/buffer-surprise-report.d.ts +1 -1
  43. package/dist/buffer-surprise-report.js +1 -1
  44. package/dist/buffer.d.ts +18 -4
  45. package/dist/buffer.js +1 -1
  46. package/dist/calibration.d.ts +1 -1
  47. package/dist/calibration.js +6 -6
  48. package/dist/capsule-cli.d.ts +4 -4
  49. package/dist/capsule-cli.js +1 -1
  50. package/dist/capsule-crypto-5CYAGVC5.js +18 -0
  51. package/dist/capsule-merge-4MGKE7C5.js +189 -0
  52. package/dist/causal-behavior.d.ts +9 -29
  53. package/dist/causal-behavior.js +6 -3
  54. package/dist/causal-behavior.js.map +1 -1
  55. package/dist/causal-chain.js +3 -2
  56. package/dist/causal-consolidation.d.ts +2 -2
  57. package/dist/causal-consolidation.js +28 -17
  58. package/dist/causal-consolidation.js.map +1 -1
  59. package/dist/causal-retrieval.js +3 -3
  60. package/dist/causal-trajectory.js +1 -1
  61. package/dist/chunk-25MQ7IHJ.js +427 -0
  62. package/dist/chunk-25MQ7IHJ.js.map +1 -0
  63. package/dist/chunk-2F2W355T.js +256 -0
  64. package/dist/chunk-2F2W355T.js.map +1 -0
  65. package/dist/chunk-2KI4QFHU.js +228 -0
  66. package/dist/chunk-2KI4QFHU.js.map +1 -0
  67. package/dist/chunk-2PRQG7PV.js +86 -0
  68. package/dist/chunk-2PRQG7PV.js.map +1 -0
  69. package/dist/chunk-2QR3XXIC.js +2272 -0
  70. package/dist/chunk-2QR3XXIC.js.map +1 -0
  71. package/dist/chunk-2WWLHTZY.js +121 -0
  72. package/dist/chunk-326G7DJK.js +2185 -0
  73. package/dist/chunk-326G7DJK.js.map +1 -0
  74. package/dist/chunk-34DQE4KF.js +174 -0
  75. package/dist/chunk-34DQE4KF.js.map +1 -0
  76. package/dist/chunk-3APJ5EVB.js +601 -0
  77. package/dist/chunk-3APJ5EVB.js.map +1 -0
  78. package/dist/chunk-3HPAPHUK.js +51 -0
  79. package/dist/chunk-3HPAPHUK.js.map +1 -0
  80. package/dist/chunk-3JXBXXM2.js +69 -0
  81. package/dist/chunk-3JXBXXM2.js.map +1 -0
  82. package/dist/chunk-3KW65B36.js +681 -0
  83. package/dist/chunk-3KW65B36.js.map +1 -0
  84. package/dist/chunk-3UXOZBHV.js +20 -0
  85. package/dist/chunk-3UXOZBHV.js.map +1 -0
  86. package/dist/chunk-3VAL7ZL2.js +266 -0
  87. package/dist/chunk-3VAL7ZL2.js.map +1 -0
  88. package/dist/chunk-3Y4P7RXM.js +31 -0
  89. package/dist/chunk-3Y4P7RXM.js.map +1 -0
  90. package/dist/chunk-47VWKCAF.js +273 -0
  91. package/dist/chunk-47VWKCAF.js.map +1 -0
  92. package/dist/chunk-4CRG46BG.js +271 -0
  93. package/dist/chunk-4RA3C3EV.js +60 -0
  94. package/dist/chunk-4RA3C3EV.js.map +1 -0
  95. package/dist/chunk-5375UYTQ.js +914 -0
  96. package/dist/chunk-5375UYTQ.js.map +1 -0
  97. package/dist/chunk-56K5QLHX.js +506 -0
  98. package/dist/chunk-56K5QLHX.js.map +1 -0
  99. package/dist/chunk-5NXIJZFX.js +180 -0
  100. package/dist/chunk-5NXIJZFX.js.map +1 -0
  101. package/dist/chunk-5RGLBDQF.js +596 -0
  102. package/dist/chunk-5RGLBDQF.js.map +1 -0
  103. package/dist/chunk-5UZXUTVO.js +9 -0
  104. package/dist/chunk-5UZXUTVO.js.map +1 -0
  105. package/dist/chunk-65PG43EQ.js +105 -0
  106. package/dist/chunk-65PG43EQ.js.map +1 -0
  107. package/dist/chunk-66DHUKLO.js +57 -0
  108. package/dist/chunk-66DHUKLO.js.map +1 -0
  109. package/dist/chunk-6FC5EGNV.js +46 -0
  110. package/dist/chunk-6FC5EGNV.js.map +1 -0
  111. package/dist/chunk-6H2TESSP.js +62 -0
  112. package/dist/chunk-6H2TESSP.js.map +1 -0
  113. package/dist/chunk-6LVVDPJ4.js +32 -0
  114. package/dist/chunk-6LVVDPJ4.js.map +1 -0
  115. package/dist/chunk-6NKAQ74D.js +2237 -0
  116. package/dist/chunk-6NKAQ74D.js.map +1 -0
  117. package/dist/chunk-6RVI47ZR.js +159 -0
  118. package/dist/chunk-6RVI47ZR.js.map +1 -0
  119. package/dist/chunk-7AAT6G4Q.js +5117 -0
  120. package/dist/chunk-7AAT6G4Q.js.map +1 -0
  121. package/dist/chunk-7DTASS5T.js +29 -0
  122. package/dist/chunk-7DTASS5T.js.map +1 -0
  123. package/dist/chunk-7IASACLB.js +596 -0
  124. package/dist/chunk-7MNMYOFP.js +32 -0
  125. package/dist/chunk-7MNMYOFP.js.map +1 -0
  126. package/dist/chunk-7N4KAIGN.js +133 -0
  127. package/dist/chunk-7N4KAIGN.js.map +1 -0
  128. package/dist/chunk-7OZ53EXP.js +101 -0
  129. package/dist/chunk-7OZ53EXP.js.map +1 -0
  130. package/dist/chunk-7XYTQGCC.js +134 -0
  131. package/dist/chunk-7XYTQGCC.js.map +1 -0
  132. package/dist/chunk-A2XUIMJ3.js +341 -0
  133. package/dist/chunk-A2XUIMJ3.js.map +1 -0
  134. package/dist/chunk-AC5LO7IU.js +308 -0
  135. package/dist/chunk-AC5LO7IU.js.map +1 -0
  136. package/dist/chunk-AGZQD76C.js +201 -0
  137. package/dist/chunk-AGZQD76C.js.map +1 -0
  138. package/dist/chunk-AH2JUU6X.js +336 -0
  139. package/dist/chunk-AH2JUU6X.js.map +1 -0
  140. package/dist/chunk-APO3DCMU.js +361 -0
  141. package/dist/chunk-APO3DCMU.js.map +1 -0
  142. package/dist/chunk-BFBF3XEF.js +283 -0
  143. package/dist/chunk-BFBF3XEF.js.map +1 -0
  144. package/dist/chunk-BJ3KMYTB.js +1974 -0
  145. package/dist/chunk-BJ3KMYTB.js.map +1 -0
  146. package/dist/chunk-C5BCH4ZS.js +317 -0
  147. package/dist/chunk-C5BCH4ZS.js.map +1 -0
  148. package/dist/chunk-CHEL3SKB.js +6758 -0
  149. package/dist/chunk-CHEL3SKB.js.map +1 -0
  150. package/dist/chunk-CQZRLNMV.js +1491 -0
  151. package/dist/chunk-CQZRLNMV.js.map +1 -0
  152. package/dist/chunk-D46YSIYX.js +892 -0
  153. package/dist/chunk-D46YSIYX.js.map +1 -0
  154. package/dist/chunk-DB5A3NHS.js +906 -0
  155. package/dist/chunk-DB5A3NHS.js.map +1 -0
  156. package/dist/chunk-DINWEURR.js +648 -0
  157. package/dist/chunk-DINWEURR.js.map +1 -0
  158. package/dist/chunk-DK5LDEQM.js +530 -0
  159. package/dist/chunk-DK5LDEQM.js.map +1 -0
  160. package/dist/chunk-DOM4GKSW.js +34 -0
  161. package/dist/chunk-DOM4GKSW.js.map +1 -0
  162. package/dist/chunk-EDTHC6UD.js +1075 -0
  163. package/dist/chunk-EDTHC6UD.js.map +1 -0
  164. package/dist/chunk-EFJ3MQ4V.js +721 -0
  165. package/dist/chunk-EHRTFRWW.js +89 -0
  166. package/dist/chunk-EHRTFRWW.js.map +1 -0
  167. package/dist/chunk-FAJ7FZYM.js +11 -0
  168. package/dist/chunk-FAJ7FZYM.js.map +1 -0
  169. package/dist/chunk-FBYESMQ2.js +570 -0
  170. package/dist/chunk-FBYESMQ2.js.map +1 -0
  171. package/dist/chunk-FDU6HUUL.js +147 -0
  172. package/dist/chunk-FF4KLI5W.js +99 -0
  173. package/dist/chunk-FF4KLI5W.js.map +1 -0
  174. package/dist/chunk-FIT6DMX6.js +310 -0
  175. package/dist/chunk-FIT6DMX6.js.map +1 -0
  176. package/dist/chunk-FJ43PRLT.js +272 -0
  177. package/dist/chunk-FJ43PRLT.js.map +1 -0
  178. package/dist/chunk-FKFMOY3N.js +32 -0
  179. package/dist/chunk-FKFMOY3N.js.map +1 -0
  180. package/dist/chunk-FLTNHQK6.js +262 -0
  181. package/dist/chunk-FLTNHQK6.js.map +1 -0
  182. package/dist/chunk-GA454ALV.js +12436 -0
  183. package/dist/chunk-GA454ALV.js.map +1 -0
  184. package/dist/chunk-GGKRUQOO.js +228 -0
  185. package/dist/chunk-GIF42EW3.js +63 -0
  186. package/dist/chunk-GIF42EW3.js.map +1 -0
  187. package/dist/chunk-GL6I6MEQ.js +647 -0
  188. package/dist/chunk-H3ME6L6D.js +709 -0
  189. package/dist/chunk-H3ME6L6D.js.map +1 -0
  190. package/dist/chunk-HHLLAQGZ.js +1 -0
  191. package/dist/chunk-HXXBL2KD.js +2040 -0
  192. package/dist/chunk-I5V2VDIW.js +219 -0
  193. package/dist/chunk-I5V2VDIW.js.map +1 -0
  194. package/dist/chunk-I6K5FBRQ.js +35 -0
  195. package/dist/chunk-I6K5FBRQ.js.map +1 -0
  196. package/dist/chunk-ICRIXAP2.js +121 -0
  197. package/dist/chunk-ICRIXAP2.js.map +1 -0
  198. package/dist/chunk-J4EB7DNW.js +11 -0
  199. package/dist/chunk-J4EB7DNW.js.map +1 -0
  200. package/dist/chunk-JLFA7DQG.js +62 -0
  201. package/dist/chunk-JLFA7DQG.js.map +1 -0
  202. package/dist/chunk-KJTKLXTH.js +9 -0
  203. package/dist/chunk-KJTKLXTH.js.map +1 -0
  204. package/dist/chunk-KLAO5DGL.js +917 -0
  205. package/dist/chunk-KLAO5DGL.js.map +1 -0
  206. package/dist/chunk-KNKUID7G.js +183 -0
  207. package/dist/chunk-KOSORCJG.js +624 -0
  208. package/dist/chunk-KOSORCJG.js.map +1 -0
  209. package/dist/chunk-KUJVMMZQ.js +1262 -0
  210. package/dist/chunk-KUJVMMZQ.js.map +1 -0
  211. package/dist/chunk-LCR46JY5.js +123 -0
  212. package/dist/chunk-LCR46JY5.js.map +1 -0
  213. package/dist/chunk-LLQ2LLWF.js +148 -0
  214. package/dist/chunk-LLQ2LLWF.js.map +1 -0
  215. package/dist/chunk-LPMVBPA3.js +236 -0
  216. package/dist/chunk-LT3NLYSI.js +50 -0
  217. package/dist/chunk-LT3NLYSI.js.map +1 -0
  218. package/dist/chunk-LUDTDZLK.js +287 -0
  219. package/dist/chunk-LUDTDZLK.js.map +1 -0
  220. package/dist/chunk-M23FSH32.js +3963 -0
  221. package/dist/chunk-M23FSH32.js.map +1 -0
  222. package/dist/chunk-MC26UJIM.js +118 -0
  223. package/dist/chunk-ME6ESPZU.js +119 -0
  224. package/dist/chunk-ME6ESPZU.js.map +1 -0
  225. package/dist/chunk-MGKYQQYF.js +272 -0
  226. package/dist/chunk-MGKYQQYF.js.map +1 -0
  227. package/dist/chunk-MJFNCJXV.js +66 -0
  228. package/dist/chunk-MJFNCJXV.js.map +1 -0
  229. package/dist/chunk-MSWG7JI6.js +237 -0
  230. package/dist/chunk-MSWG7JI6.js.map +1 -0
  231. package/dist/chunk-MT25YHYH.js +141 -0
  232. package/dist/chunk-MT25YHYH.js.map +1 -0
  233. package/dist/chunk-MT4HVDUZ.js +53 -0
  234. package/dist/chunk-MY6TPVXW.js +219 -0
  235. package/dist/chunk-N2D6GXBM.js +267 -0
  236. package/dist/chunk-N2D6GXBM.js.map +1 -0
  237. package/dist/chunk-NJ3MJQZX.js +46 -0
  238. package/dist/chunk-NJ3MJQZX.js.map +1 -0
  239. package/dist/chunk-NMZY542O.js +335 -0
  240. package/dist/chunk-NMZY542O.js.map +1 -0
  241. package/dist/chunk-NNVTUXEB.js +23 -0
  242. package/dist/chunk-NZL6GGQE.js +375 -0
  243. package/dist/chunk-NZL6GGQE.js.map +1 -0
  244. package/dist/chunk-OAZ5MFUB.js +4124 -0
  245. package/dist/chunk-OAZ5MFUB.js.map +1 -0
  246. package/dist/chunk-OIGNEXKZ.js +237 -0
  247. package/dist/chunk-OIGNEXKZ.js.map +1 -0
  248. package/dist/chunk-OZKZ2TRP.js +3729 -0
  249. package/dist/chunk-OZKZ2TRP.js.map +1 -0
  250. package/dist/chunk-P4NEIHUT.js +108 -0
  251. package/dist/chunk-P7FMDTKL.js +103 -0
  252. package/dist/chunk-P7FMDTKL.js.map +1 -0
  253. package/dist/chunk-PD6O7AXF.js +110 -0
  254. package/dist/chunk-PD6O7AXF.js.map +1 -0
  255. package/dist/chunk-PHK3HARR.js +32 -0
  256. package/dist/chunk-PHK3HARR.js.map +1 -0
  257. package/dist/chunk-PIRJPV5T.js +98 -0
  258. package/dist/chunk-PIRJPV5T.js.map +1 -0
  259. package/dist/chunk-PK7H5L6Y.js +159 -0
  260. package/dist/chunk-PK7H5L6Y.js.map +1 -0
  261. package/dist/chunk-PR5FBTFU.js +233 -0
  262. package/dist/chunk-PR5FBTFU.js.map +1 -0
  263. package/dist/chunk-PU63GXWS.js +174 -0
  264. package/dist/chunk-PU63GXWS.js.map +1 -0
  265. package/dist/chunk-PYPOFEMK.js +294 -0
  266. package/dist/chunk-PYPOFEMK.js.map +1 -0
  267. package/dist/chunk-PZIAX57I.js +124 -0
  268. package/dist/chunk-PZIAX57I.js.map +1 -0
  269. package/dist/chunk-Q7P4WJDP.js +26 -0
  270. package/dist/chunk-Q7P4WJDP.js.map +1 -0
  271. package/dist/chunk-QDZ2RLEC.js +908 -0
  272. package/dist/chunk-QDZ2RLEC.js.map +1 -0
  273. package/dist/chunk-QQUAB63I.js +63 -0
  274. package/dist/chunk-QQUAB63I.js.map +1 -0
  275. package/dist/chunk-QRNI5JBH.js +18 -0
  276. package/dist/chunk-RHY3HH7P.js +601 -0
  277. package/dist/chunk-RHY3HH7P.js.map +1 -0
  278. package/dist/chunk-RK6F44Y6.js +84 -0
  279. package/dist/chunk-RK6F44Y6.js.map +1 -0
  280. package/dist/chunk-RRF5UOBJ.js +91 -0
  281. package/dist/chunk-RXDLTSWT.js +124 -0
  282. package/dist/chunk-RXDLTSWT.js.map +1 -0
  283. package/dist/chunk-RYED3SPJ.js +42 -0
  284. package/dist/chunk-RYED3SPJ.js.map +1 -0
  285. package/dist/chunk-S7KDBTWT.js +106 -0
  286. package/dist/chunk-S7KDBTWT.js.map +1 -0
  287. package/dist/chunk-SEDEKFYQ.js +1 -0
  288. package/dist/chunk-SOAU2OE2.js +125 -0
  289. package/dist/chunk-SOAU2OE2.js.map +1 -0
  290. package/dist/chunk-TECVW3JP.js +36 -0
  291. package/dist/chunk-TECVW3JP.js.map +1 -0
  292. package/dist/chunk-TFO23QT4.js +88 -0
  293. package/dist/chunk-TFO23QT4.js.map +1 -0
  294. package/dist/chunk-TK4UEOSK.js +76 -0
  295. package/dist/chunk-TK4UEOSK.js.map +1 -0
  296. package/dist/chunk-TKWGAOLV.js +122 -0
  297. package/dist/chunk-TKWGAOLV.js.map +1 -0
  298. package/dist/chunk-TMM4S4IJ.js +597 -0
  299. package/dist/chunk-TMM4S4IJ.js.map +1 -0
  300. package/dist/chunk-TMQLARTH.js +188 -0
  301. package/dist/chunk-TMQLARTH.js.map +1 -0
  302. package/dist/chunk-TPDBFYEG.js +130 -0
  303. package/dist/chunk-TPDBFYEG.js.map +1 -0
  304. package/dist/chunk-TPMQ3G6Z.js +145 -0
  305. package/dist/chunk-TPMQ3G6Z.js.map +1 -0
  306. package/dist/chunk-TZOLIGIG.js +61 -0
  307. package/dist/chunk-TZOLIGIG.js.map +1 -0
  308. package/dist/chunk-U3PN77QT.js +113 -0
  309. package/dist/chunk-U3WSW6PZ.js +277 -0
  310. package/dist/chunk-U4SCL7B7.js +640 -0
  311. package/dist/chunk-U4SCL7B7.js.map +1 -0
  312. package/dist/chunk-UWK5OXUJ.js +156 -0
  313. package/dist/chunk-UWK5OXUJ.js.map +1 -0
  314. package/dist/chunk-UWVJF25J.js +74 -0
  315. package/dist/chunk-UXHQAFNA.js +1317 -0
  316. package/dist/chunk-UXHQAFNA.js.map +1 -0
  317. package/dist/chunk-V5OCT34X.js +1 -0
  318. package/dist/chunk-V5OCT34X.js.map +1 -0
  319. package/dist/chunk-VLXA6PI2.js +304 -0
  320. package/dist/chunk-VLXA6PI2.js.map +1 -0
  321. package/dist/chunk-VNO6ZJ35.js +500 -0
  322. package/dist/chunk-VNO6ZJ35.js.map +1 -0
  323. package/dist/chunk-VW676BEI.js +827 -0
  324. package/dist/chunk-VW676BEI.js.map +1 -0
  325. package/dist/chunk-VWT3F4IV.js +2161 -0
  326. package/dist/chunk-VWT3F4IV.js.map +1 -0
  327. package/dist/chunk-W3LR522O.js +2296 -0
  328. package/dist/chunk-W3LR522O.js.map +1 -0
  329. package/dist/chunk-W4L6CZKA.js +96 -0
  330. package/dist/chunk-W4L6CZKA.js.map +1 -0
  331. package/dist/chunk-W4RVMTHR.js +372 -0
  332. package/dist/chunk-W4RVMTHR.js.map +1 -0
  333. package/dist/chunk-WEHSQBFR.js +188 -0
  334. package/dist/chunk-WEHSQBFR.js.map +1 -0
  335. package/dist/chunk-WELDCG6C.js +380 -0
  336. package/dist/chunk-WELDCG6C.js.map +1 -0
  337. package/dist/chunk-WZYKANL3.js +2800 -0
  338. package/dist/chunk-WZYKANL3.js.map +1 -0
  339. package/dist/chunk-XIG5PDM7.js +48 -0
  340. package/dist/chunk-XJNBEDFE.js +193 -0
  341. package/dist/chunk-XJNBEDFE.js.map +1 -0
  342. package/dist/chunk-XVVIG67A.js +291 -0
  343. package/dist/chunk-XVVIG67A.js.map +1 -0
  344. package/dist/chunk-XVZ7B3HG.js +135 -0
  345. package/dist/chunk-YBPYIAA5.js +73 -0
  346. package/dist/chunk-YBPYIAA5.js.map +1 -0
  347. package/dist/chunk-Z734BLO3.js +21 -0
  348. package/dist/chunk-Z734BLO3.js.map +1 -0
  349. package/dist/chunk-ZKSK55RC.js +269 -0
  350. package/dist/chunk-ZKSK55RC.js.map +1 -0
  351. package/dist/chunk-ZTFCYYEZ.js +69 -0
  352. package/dist/chunk-ZTFCYYEZ.js.map +1 -0
  353. package/dist/chunk-ZY2MNJR6.js +329 -0
  354. package/dist/chunk-ZY2MNJR6.js.map +1 -0
  355. package/dist/cli-D3VpkVwB.d.ts +1136 -0
  356. package/dist/cli.d.ts +42 -10
  357. package/dist/cli.js +121 -58
  358. package/dist/codex-cli-fallback.d.ts +1 -0
  359. package/dist/codex-cli-fallback.js +1 -1
  360. package/dist/commitment-ledger.js +1 -1
  361. package/dist/compat/checks.d.ts +5 -0
  362. package/dist/compat/checks.js +11 -0
  363. package/dist/compat/checks.js.map +1 -0
  364. package/dist/compat/types.d.ts +30 -0
  365. package/dist/compat/types.js +1 -0
  366. package/dist/compat/types.js.map +1 -0
  367. package/dist/compounding/engine.d.ts +221 -0
  368. package/dist/compounding/engine.js +32 -0
  369. package/dist/compounding/engine.js.map +1 -0
  370. package/dist/compounding/preference-consolidator.d.ts +92 -0
  371. package/dist/compounding/preference-consolidator.js +553 -0
  372. package/dist/compounding/preference-consolidator.js.map +1 -0
  373. package/dist/compression-optimizer.d.ts +1 -1
  374. package/dist/config.d.ts +5 -3
  375. package/dist/config.js +9 -4
  376. package/dist/conflict-policy-DyJ2wd-h.d.ts +4 -0
  377. package/dist/connectors/codex-materialize-runner.d.ts +64 -0
  378. package/dist/connectors/codex-materialize-runner.js +33 -0
  379. package/dist/connectors/codex-materialize-runner.js.map +1 -0
  380. package/dist/connectors/codex-materialize.d.ts +195 -0
  381. package/dist/connectors/codex-materialize.js +38 -0
  382. package/dist/connectors/codex-materialize.js.map +1 -0
  383. package/dist/connectors/index.d.ts +444 -0
  384. package/dist/connectors/index.js +115 -0
  385. package/dist/connectors/index.js.map +1 -0
  386. package/dist/connectors-cli-CwbyjGR7.d.ts +257 -0
  387. package/dist/connectors-cli.d.ts +1 -1
  388. package/dist/consolidation-provenance-check.d.ts +4 -2
  389. package/dist/consolidation-undo.d.ts +4 -2
  390. package/dist/contradiction/index.d.ts +258 -0
  391. package/dist/contradiction/index.js +43 -0
  392. package/dist/contradiction/index.js.map +1 -0
  393. package/dist/contradiction-review-ATP4S6IC.js +30 -0
  394. package/dist/contradiction-review-ATP4S6IC.js.map +1 -0
  395. package/dist/contradiction-scan-5A4IDZV5.js +13 -0
  396. package/dist/contradiction-scan-5A4IDZV5.js.map +1 -0
  397. package/dist/conversation-index/backend.d.ts +97 -0
  398. package/dist/conversation-index/backend.js +13 -0
  399. package/dist/conversation-index/backend.js.map +1 -0
  400. package/dist/conversation-index/chunker.d.ts +16 -0
  401. package/dist/conversation-index/chunker.js +8 -0
  402. package/dist/conversation-index/chunker.js.map +1 -0
  403. package/dist/conversation-index/cleanup.d.ts +11 -0
  404. package/dist/conversation-index/cleanup.js +9 -0
  405. package/dist/conversation-index/cleanup.js.map +1 -0
  406. package/dist/conversation-index/faiss-adapter.d.ts +6 -0
  407. package/dist/conversation-index/faiss-adapter.js +16 -0
  408. package/dist/conversation-index/faiss-adapter.js.map +1 -0
  409. package/dist/conversation-index/indexer.d.ts +23 -0
  410. package/dist/conversation-index/indexer.js +15 -0
  411. package/dist/conversation-index/indexer.js.map +1 -0
  412. package/dist/conversation-index/search.d.ts +6 -0
  413. package/dist/conversation-index/search.js +11 -0
  414. package/dist/conversation-index/search.js.map +1 -0
  415. package/dist/day-summary.d.ts +1 -1
  416. package/dist/delinearize.d.ts +1 -1
  417. package/dist/direct-answer-wiring.d.ts +1 -1
  418. package/dist/direct-answer-wiring.js +1 -1
  419. package/dist/direct-answer.d.ts +1 -1
  420. package/dist/embedding-fallback.d.ts +1 -1
  421. package/dist/embedding-fallback.js +2 -2
  422. package/dist/enrichment/index.d.ts +163 -0
  423. package/dist/enrichment/index.js +18 -0
  424. package/dist/enrichment/index.js.map +1 -0
  425. package/dist/entity-retrieval.d.ts +4 -2
  426. package/dist/entity-retrieval.js +9 -6
  427. package/dist/entity-schema.d.ts +1 -1
  428. package/dist/evals.js +1 -1
  429. package/dist/event-order-recall.d.ts +17 -0
  430. package/dist/event-order-recall.js +11 -0
  431. package/dist/event-order-recall.js.map +1 -0
  432. package/dist/evidence-pack.d.ts +3 -1
  433. package/dist/evidence-pack.js +5 -3
  434. package/dist/explicit-capture.d.ts +23 -6
  435. package/dist/explicit-capture.js +2 -2
  436. package/dist/explicit-cue-recall.d.ts +4 -1
  437. package/dist/explicit-cue-recall.js +4 -2
  438. package/dist/extraction-judge-telemetry.d.ts +1 -1
  439. package/dist/extraction-judge-training.d.ts +1 -1
  440. package/dist/extraction-judge-training.js +1 -1
  441. package/dist/extraction-judge.d.ts +1 -1
  442. package/dist/extraction.d.ts +1 -1
  443. package/dist/extraction.js +11 -10
  444. package/dist/faiss-adapter-CzPghc4C.d.ts +70 -0
  445. package/dist/fallback-llm.d.ts +4 -1
  446. package/dist/fallback-llm.js +6 -6
  447. package/dist/focused-list-recall.d.ts +17 -0
  448. package/dist/focused-list-recall.js +11 -0
  449. package/dist/focused-list-recall.js.map +1 -0
  450. package/dist/graph-edge-decay-5DI5GUNL.js +207 -0
  451. package/dist/identity-continuity.d.ts +1 -1
  452. package/dist/importance.d.ts +1 -1
  453. package/dist/index-DJ9QWMw-.d.ts +35 -0
  454. package/dist/index.d.ts +107 -715
  455. package/dist/index.js +657 -2611
  456. package/dist/index.js.map +1 -1
  457. package/dist/intent.d.ts +1 -1
  458. package/dist/intent.js +1 -1
  459. package/dist/lcm/archive.d.ts +89 -0
  460. package/dist/lcm/archive.js +12 -0
  461. package/dist/lcm/archive.js.map +1 -0
  462. package/dist/lcm/dag.d.ts +48 -0
  463. package/dist/lcm/dag.js +8 -0
  464. package/dist/lcm/dag.js.map +1 -0
  465. package/dist/lcm/engine.d.ts +116 -0
  466. package/dist/lcm/engine.js +20 -0
  467. package/dist/lcm/engine.js.map +1 -0
  468. package/dist/lcm/index.d.ts +12 -0
  469. package/dist/lcm/index.js +44 -0
  470. package/dist/lcm/index.js.map +1 -0
  471. package/dist/lcm/queue.d.ts +62 -0
  472. package/dist/lcm/queue.js +8 -0
  473. package/dist/lcm/queue.js.map +1 -0
  474. package/dist/lcm/recall.d.ts +20 -0
  475. package/dist/lcm/recall.js +8 -0
  476. package/dist/lcm/recall.js.map +1 -0
  477. package/dist/lcm/schema.d.ts +16 -0
  478. package/dist/lcm/schema.js +14 -0
  479. package/dist/lcm/schema.js.map +1 -0
  480. package/dist/lcm/summarizer.d.ts +38 -0
  481. package/dist/lcm/summarizer.js +12 -0
  482. package/dist/lcm/summarizer.js.map +1 -0
  483. package/dist/lcm/tools.d.ts +29 -0
  484. package/dist/lcm/tools.js +8 -0
  485. package/dist/lcm/tools.js.map +1 -0
  486. package/dist/lifecycle.d.ts +1 -1
  487. package/dist/live-connectors-runner.d.ts +1 -1
  488. package/dist/live-connectors-runner.js +5 -5
  489. package/dist/local-llm.d.ts +8 -4
  490. package/dist/local-llm.js +3 -3
  491. package/dist/maintenance/archive-observations.d.ts +18 -0
  492. package/dist/maintenance/archive-observations.js +8 -0
  493. package/dist/maintenance/archive-observations.js.map +1 -0
  494. package/dist/maintenance/backup-stamp.d.ts +3 -0
  495. package/dist/maintenance/backup-stamp.js +8 -0
  496. package/dist/maintenance/backup-stamp.js.map +1 -0
  497. package/dist/maintenance/memory-governance-cron.d.ts +85 -0
  498. package/dist/maintenance/memory-governance-cron.js +22 -0
  499. package/dist/maintenance/memory-governance-cron.js.map +1 -0
  500. package/dist/maintenance/memory-governance.d.ts +137 -0
  501. package/dist/maintenance/memory-governance.js +40 -0
  502. package/dist/maintenance/memory-governance.js.map +1 -0
  503. package/dist/maintenance/migrate-observations.d.ts +18 -0
  504. package/dist/maintenance/migrate-observations.js +9 -0
  505. package/dist/maintenance/migrate-observations.js.map +1 -0
  506. package/dist/maintenance/observation-ledger-utils.d.ts +10 -0
  507. package/dist/maintenance/observation-ledger-utils.js +10 -0
  508. package/dist/maintenance/observation-ledger-utils.js.map +1 -0
  509. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +15 -0
  510. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +28 -0
  511. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js.map +1 -0
  512. package/dist/maintenance/rebuild-memory-projection.d.ts +77 -0
  513. package/dist/maintenance/rebuild-memory-projection.js +35 -0
  514. package/dist/maintenance/rebuild-memory-projection.js.map +1 -0
  515. package/dist/maintenance/rebuild-observations.d.ts +17 -0
  516. package/dist/maintenance/rebuild-observations.js +9 -0
  517. package/dist/maintenance/rebuild-observations.js.map +1 -0
  518. package/dist/mcp-memory-inspector-app.d.ts +124 -0
  519. package/dist/mcp-memory-inspector-app.js +20 -0
  520. package/dist/mcp-memory-inspector-app.js.map +1 -0
  521. package/dist/memory-action-policy.d.ts +1 -1
  522. package/dist/memory-cache.d.ts +1 -1
  523. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  524. package/dist/memory-projection-store.d.ts +108 -3
  525. package/dist/memory-projection-store.js +2 -1
  526. package/dist/memory-provenance.d.ts +57 -0
  527. package/dist/memory-provenance.js +13 -0
  528. package/dist/memory-provenance.js.map +1 -0
  529. package/dist/memory-worth-outcomes.d.ts +4 -2
  530. package/dist/migrate/from-engram.d.ts +24 -0
  531. package/dist/migrate/from-engram.js +12 -0
  532. package/dist/migrate/from-engram.js.map +1 -0
  533. package/dist/models-json.d.ts +1 -1
  534. package/dist/namespaces/migrate.d.ts +50 -0
  535. package/dist/namespaces/migrate.js +50 -0
  536. package/dist/namespaces/migrate.js.map +1 -0
  537. package/dist/namespaces/principal.d.ts +17 -0
  538. package/dist/namespaces/principal.js +16 -0
  539. package/dist/namespaces/principal.js.map +1 -0
  540. package/dist/namespaces/search.d.ts +46 -0
  541. package/dist/namespaces/search.js +28 -0
  542. package/dist/namespaces/search.js.map +1 -0
  543. package/dist/namespaces/storage.d.ts +32 -0
  544. package/dist/namespaces/storage.js +28 -0
  545. package/dist/namespaces/storage.js.map +1 -0
  546. package/dist/native-knowledge.d.ts +1 -1
  547. package/dist/network/tailscale.d.ts +41 -0
  548. package/dist/network/tailscale.js +9 -0
  549. package/dist/network/tailscale.js.map +1 -0
  550. package/dist/network/webdav.d.ts +39 -0
  551. package/dist/network/webdav.js +10 -0
  552. package/dist/network/webdav.js.map +1 -0
  553. package/dist/objective-state-writers.d.ts +1 -1
  554. package/dist/objective-state-writers.js +2 -2
  555. package/dist/operator-toolkit.d.ts +4 -2
  556. package/dist/operator-toolkit.js +35 -17
  557. package/dist/opik-exporter.js +2 -2
  558. package/dist/opik-exporter.js.map +1 -1
  559. package/dist/orchestrator-DuWl9Hwx.d.ts +1244 -0
  560. package/dist/orchestrator.d.ts +24 -7
  561. package/dist/orchestrator.js +107 -65
  562. package/dist/path-MR5JPYOP.js +9 -0
  563. package/dist/path-MR5JPYOP.js.map +1 -0
  564. package/dist/patterns-cli.d.ts +1 -1
  565. package/dist/policy-runtime.d.ts +1 -1
  566. package/dist/qmd-recall-cache.d.ts +2 -2
  567. package/dist/qmd.d.ts +103 -4
  568. package/dist/qmd.js +23 -5
  569. package/dist/recall-disclosure-escalation.d.ts +1 -1
  570. package/dist/recall-explain-renderer.d.ts +3 -1
  571. package/dist/recall-explain-renderer.js +5 -3
  572. package/dist/recall-state.d.ts +1 -1
  573. package/dist/recall-tag-filter.d.ts +3 -1
  574. package/dist/recall-xray-cli.d.ts +3 -1
  575. package/dist/recall-xray-cli.js +6 -4
  576. package/dist/recall-xray-renderer.d.ts +3 -1
  577. package/dist/recall-xray-renderer.js +5 -3
  578. package/dist/recall-xray.d.ts +8 -1
  579. package/dist/recall-xray.js +4 -2
  580. package/dist/replay/normalizers/chatgpt.d.ts +6 -0
  581. package/dist/replay/normalizers/chatgpt.js +11 -0
  582. package/dist/replay/normalizers/chatgpt.js.map +1 -0
  583. package/dist/replay/normalizers/claude.d.ts +6 -0
  584. package/dist/replay/normalizers/claude.js +11 -0
  585. package/dist/replay/normalizers/claude.js.map +1 -0
  586. package/dist/replay/normalizers/openclaw.d.ts +6 -0
  587. package/dist/replay/normalizers/openclaw.js +11 -0
  588. package/dist/replay/normalizers/openclaw.js.map +1 -0
  589. package/dist/replay/normalizers/shared.d.ts +16 -0
  590. package/dist/replay/normalizers/shared.js +14 -0
  591. package/dist/replay/normalizers/shared.js.map +1 -0
  592. package/dist/replay/runner.d.ts +35 -0
  593. package/dist/replay/runner.js +16 -0
  594. package/dist/replay/runner.js.map +1 -0
  595. package/dist/replay/types.d.ts +57 -0
  596. package/dist/replay/types.js +19 -0
  597. package/dist/replay/types.js.map +1 -0
  598. package/dist/resolution-B7FNQSSP.js +12 -0
  599. package/dist/resolution-B7FNQSSP.js.map +1 -0
  600. package/dist/resolve-auth-token.d.ts +1 -1
  601. package/dist/resolve-provider-secret.js +2 -2
  602. package/dist/response-guidance-recall.d.ts +18 -0
  603. package/dist/response-guidance-recall.js +11 -0
  604. package/dist/response-guidance-recall.js.map +1 -0
  605. package/dist/resume-bundles.js +7 -5
  606. package/dist/retrieval-agents.d.ts +2 -2
  607. package/dist/retrieval-tiers.d.ts +1 -1
  608. package/dist/routing/engine.d.ts +35 -0
  609. package/dist/routing/engine.js +16 -0
  610. package/dist/routing/engine.js.map +1 -0
  611. package/dist/routing/store.d.ts +27 -0
  612. package/dist/routing/store.js +10 -0
  613. package/dist/routing/store.js.map +1 -0
  614. package/dist/runtime/better-sqlite.d.ts +8 -0
  615. package/dist/runtime/better-sqlite.js +10 -0
  616. package/dist/runtime/better-sqlite.js.map +1 -0
  617. package/dist/runtime/child-process.d.ts +32 -0
  618. package/dist/runtime/child-process.js +10 -0
  619. package/dist/runtime/child-process.js.map +1 -0
  620. package/dist/runtime/env.d.ts +5 -0
  621. package/dist/runtime/env.js +12 -0
  622. package/dist/runtime/env.js.map +1 -0
  623. package/dist/sdk-compat.js +1 -1
  624. package/dist/search/document-scanner.d.ts +22 -0
  625. package/dist/search/document-scanner.js +8 -0
  626. package/dist/search/document-scanner.js.map +1 -0
  627. package/dist/search/embed-helper.d.ts +35 -0
  628. package/dist/search/embed-helper.js +9 -0
  629. package/dist/search/embed-helper.js.map +1 -0
  630. package/dist/search/factory.d.ts +32 -0
  631. package/dist/search/factory.js +29 -0
  632. package/dist/search/factory.js.map +1 -0
  633. package/dist/search/index.d.ts +15 -0
  634. package/dist/search/index.js +50 -0
  635. package/dist/search/index.js.map +1 -0
  636. package/dist/search/lancedb-backend.d.ts +51 -0
  637. package/dist/search/lancedb-backend.js +10 -0
  638. package/dist/search/lancedb-backend.js.map +1 -0
  639. package/dist/search/meilisearch-backend.d.ts +48 -0
  640. package/dist/search/meilisearch-backend.js +10 -0
  641. package/dist/search/meilisearch-backend.js.map +1 -0
  642. package/dist/search/noop-backend.d.ts +26 -0
  643. package/dist/search/noop-backend.js +8 -0
  644. package/dist/search/noop-backend.js.map +1 -0
  645. package/dist/search/orama-backend.d.ts +53 -0
  646. package/dist/search/orama-backend.js +10 -0
  647. package/dist/search/orama-backend.js.map +1 -0
  648. package/dist/search/port.d.ts +61 -0
  649. package/dist/search/port.js +1 -0
  650. package/dist/search/port.js.map +1 -0
  651. package/dist/search/remote-backend.d.ts +39 -0
  652. package/dist/search/remote-backend.js +9 -0
  653. package/dist/search/remote-backend.js.map +1 -0
  654. package/dist/secure-store/index.d.ts +890 -0
  655. package/dist/secure-store/index.js +156 -0
  656. package/dist/secure-store/index.js.map +1 -0
  657. package/dist/semantic-VwGI14Ok.d.ts +69 -0
  658. package/dist/semantic-consolidation-4HkHWgeI.d.ts +180 -0
  659. package/dist/semantic-consolidation.d.ts +3 -3
  660. package/dist/semantic-consolidation.js +15 -8
  661. package/dist/semantic-rule-promotion.js +9 -6
  662. package/dist/semantic-rule-verifier.d.ts +1 -1
  663. package/dist/semantic-rule-verifier.js +10 -7
  664. package/dist/session-observer-bands.d.ts +1 -1
  665. package/dist/session-observer-state.d.ts +1 -1
  666. package/dist/shared-context/manager.d.ts +131 -0
  667. package/dist/shared-context/manager.js +15 -0
  668. package/dist/shared-context/manager.js.map +1 -0
  669. package/dist/signal.d.ts +1 -1
  670. package/dist/skills-registry.js +13 -1
  671. package/dist/skills-registry.js.map +1 -1
  672. package/dist/state-store-VZU2IA53.js +16 -0
  673. package/dist/state-store-VZU2IA53.js.map +1 -0
  674. package/dist/storage-paths.d.ts +9 -0
  675. package/dist/storage-paths.js +20 -0
  676. package/dist/storage-paths.js.map +1 -0
  677. package/dist/storage.d.ts +6 -2
  678. package/dist/storage.js +8 -5
  679. package/dist/summarizer.d.ts +6 -1
  680. package/dist/summarizer.js +11 -10
  681. package/dist/summary-snapshot.d.ts +1 -1
  682. package/dist/summary-snapshot.js +2 -1
  683. package/dist/surfaces/dreams.d.ts +16 -0
  684. package/dist/surfaces/dreams.js +282 -0
  685. package/dist/surfaces/dreams.js.map +1 -0
  686. package/dist/surfaces/heartbeat.d.ts +17 -0
  687. package/dist/surfaces/heartbeat.js +265 -0
  688. package/dist/surfaces/heartbeat.js.map +1 -0
  689. package/dist/targeted-fact-recall.d.ts +17 -0
  690. package/dist/targeted-fact-recall.js +11 -0
  691. package/dist/targeted-fact-recall.js.map +1 -0
  692. package/dist/telemetry-transcript.d.ts +7 -0
  693. package/dist/telemetry-transcript.js +16 -0
  694. package/dist/telemetry-transcript.js.map +1 -0
  695. package/dist/temporal-supersession.d.ts +4 -2
  696. package/dist/temporal-supersession.js +2 -1
  697. package/dist/temporal-validity.d.ts +1 -1
  698. package/dist/threading.d.ts +6 -1
  699. package/dist/threading.js +2 -1
  700. package/dist/tier-migration.d.ts +5 -3
  701. package/dist/tier-routing.d.ts +1 -1
  702. package/dist/tokens.js +2 -2
  703. package/dist/topics.d.ts +1 -1
  704. package/dist/transcript.d.ts +16 -2
  705. package/dist/transcript.js +2 -1
  706. package/dist/transfer/autodetect.d.ts +4 -0
  707. package/dist/transfer/autodetect.js +15 -0
  708. package/dist/transfer/autodetect.js.map +1 -0
  709. package/dist/transfer/backup.d.ts +21 -0
  710. package/dist/transfer/backup.js +17 -0
  711. package/dist/transfer/backup.js.map +1 -0
  712. package/dist/transfer/capsule-export.d.ts +113 -0
  713. package/dist/transfer/capsule-export.js +19 -0
  714. package/dist/transfer/capsule-export.js.map +1 -0
  715. package/dist/transfer/capsule-import.d.ts +124 -0
  716. package/dist/transfer/capsule-import.js +16 -0
  717. package/dist/transfer/capsule-import.js.map +1 -0
  718. package/dist/transfer/constants.d.ts +13 -0
  719. package/dist/transfer/constants.js +12 -0
  720. package/dist/transfer/constants.js.map +1 -0
  721. package/dist/transfer/export-json.d.ts +11 -0
  722. package/dist/transfer/export-json.js +11 -0
  723. package/dist/transfer/export-json.js.map +1 -0
  724. package/dist/transfer/export-md.d.ts +10 -0
  725. package/dist/transfer/export-md.js +13 -0
  726. package/dist/transfer/export-md.js.map +1 -0
  727. package/dist/transfer/export-sqlite.d.ts +9 -0
  728. package/dist/transfer/export-sqlite.js +12 -0
  729. package/dist/transfer/export-sqlite.js.map +1 -0
  730. package/dist/transfer/fs-utils.d.ts +61 -0
  731. package/dist/transfer/fs-utils.js +40 -0
  732. package/dist/transfer/fs-utils.js.map +1 -0
  733. package/dist/transfer/import-json.d.ts +16 -0
  734. package/dist/transfer/import-json.js +13 -0
  735. package/dist/transfer/import-json.js.map +1 -0
  736. package/dist/transfer/import-md.d.ts +14 -0
  737. package/dist/transfer/import-md.js +11 -0
  738. package/dist/transfer/import-md.js.map +1 -0
  739. package/dist/transfer/import-sqlite.d.ts +14 -0
  740. package/dist/transfer/import-sqlite.js +12 -0
  741. package/dist/transfer/import-sqlite.js.map +1 -0
  742. package/dist/transfer/sqlite-schema.d.ts +4 -0
  743. package/dist/transfer/sqlite-schema.js +10 -0
  744. package/dist/transfer/sqlite-schema.js.map +1 -0
  745. package/dist/transfer/types.d.ts +916 -0
  746. package/dist/transfer/types.js +30 -0
  747. package/dist/transfer/types.js.map +1 -0
  748. package/dist/trust-zones.d.ts +3 -2
  749. package/dist/trust-zones.js +1 -1
  750. package/dist/types.d.ts +88 -3
  751. package/dist/types.js +1 -1
  752. package/dist/user-model.d.ts +37 -0
  753. package/dist/user-model.js +28 -0
  754. package/dist/user-model.js.map +1 -0
  755. package/dist/utility-runtime.d.ts +1 -1
  756. package/dist/verified-recall.js +11 -8
  757. package/dist/work/board.d.ts +43 -0
  758. package/dist/work/board.js +14 -0
  759. package/dist/work/board.js.map +1 -0
  760. package/dist/work/boundary.d.ts +8 -0
  761. package/dist/work/boundary.js +14 -0
  762. package/dist/work/boundary.js.map +1 -0
  763. package/dist/work/storage.d.ts +39 -0
  764. package/dist/work/storage.js +11 -0
  765. package/dist/work/storage.js.map +1 -0
  766. package/dist/work/types.d.ts +75 -0
  767. package/dist/work/types.js +1 -0
  768. package/dist/work/types.js.map +1 -0
  769. package/package.json +2767 -6
  770. package/scripts/faiss_index.py +816 -0
  771. package/scripts/faiss_requirements.txt +3 -0
  772. package/skills/remnic-entities/SKILL.md +51 -0
  773. package/skills/remnic-memory-workflow/SKILL.md +61 -0
  774. package/skills/remnic-recall/SKILL.md +51 -0
  775. package/skills/remnic-remember/SKILL.md +56 -0
  776. package/skills/remnic-search/SKILL.md +51 -0
  777. package/skills/remnic-status/SKILL.md +51 -0
  778. package/src/abort-error.test.ts +49 -0
  779. package/src/abort-error.ts +46 -0
  780. package/src/abstraction-nodes.ts +162 -0
  781. package/src/access-audit.test.ts +178 -0
  782. package/src/access-audit.ts +125 -0
  783. package/src/access-cli.test.ts +439 -0
  784. package/src/access-cli.ts +438 -0
  785. package/src/access-http.test.ts +225 -0
  786. package/src/access-http.ts +1899 -0
  787. package/src/access-idempotency.ts +232 -0
  788. package/src/access-mcp.test.ts +568 -0
  789. package/src/access-mcp.ts +3056 -0
  790. package/src/access-schema-pi.test.ts +60 -0
  791. package/src/access-schema.ts +522 -0
  792. package/src/access-service-namespace.test.ts +123 -0
  793. package/src/access-service.ts +5629 -0
  794. package/src/action-confidence.test.ts +206 -0
  795. package/src/action-confidence.ts +466 -0
  796. package/src/active-memory-bridge.test.ts +285 -0
  797. package/src/active-memory-bridge.ts +217 -0
  798. package/src/active-recall.test.ts +484 -0
  799. package/src/active-recall.ts +459 -0
  800. package/src/adapters/claude-code.ts +56 -0
  801. package/src/adapters/codex.ts +57 -0
  802. package/src/adapters/hermes.ts +64 -0
  803. package/src/adapters/index.ts +6 -0
  804. package/src/adapters/registry.ts +41 -0
  805. package/src/adapters/replit.ts +55 -0
  806. package/src/adapters/types.ts +51 -0
  807. package/src/behavior-learner.ts +144 -0
  808. package/src/behavior-signals.ts +73 -0
  809. package/src/binary-lifecycle/backend.ts +117 -0
  810. package/src/binary-lifecycle/index.ts +35 -0
  811. package/src/binary-lifecycle/manifest.ts +79 -0
  812. package/src/binary-lifecycle/pipeline.ts +352 -0
  813. package/src/binary-lifecycle/scanner.ts +89 -0
  814. package/src/binary-lifecycle/types.ts +89 -0
  815. package/src/bootstrap.ts +178 -0
  816. package/src/boxes.ts +521 -0
  817. package/src/briefing.test.ts +1535 -0
  818. package/src/briefing.ts +1382 -0
  819. package/src/buffer-session.test.ts +443 -0
  820. package/src/buffer-surprise-report.ts +176 -0
  821. package/src/buffer-surprise-telemetry.test.ts +606 -0
  822. package/src/buffer-surprise-trigger.test.ts +766 -0
  823. package/src/buffer-surprise.test.ts +339 -0
  824. package/src/buffer-surprise.ts +203 -0
  825. package/src/buffer.ts +900 -0
  826. package/src/bulk-import/cli-command.test.ts +204 -0
  827. package/src/bulk-import/index.ts +34 -0
  828. package/src/bulk-import/pipeline.test.ts +445 -0
  829. package/src/bulk-import/pipeline.ts +178 -0
  830. package/src/bulk-import/registry.test.ts +151 -0
  831. package/src/bulk-import/registry.ts +72 -0
  832. package/src/bulk-import/types.test.ts +272 -0
  833. package/src/bulk-import/types.ts +145 -0
  834. package/src/calibration.ts +394 -0
  835. package/src/capsule-cli.test.ts +398 -0
  836. package/src/capsule-cli.ts +565 -0
  837. package/src/causal-behavior.ts +308 -0
  838. package/src/causal-chain.ts +419 -0
  839. package/src/causal-consolidation.ts +370 -0
  840. package/src/causal-retrieval.ts +286 -0
  841. package/src/causal-trajectory-graph.ts +60 -0
  842. package/src/causal-trajectory.ts +303 -0
  843. package/src/chunking.ts +220 -0
  844. package/src/citations.ts +232 -0
  845. package/src/cli.ts +9403 -0
  846. package/src/codex-cli-fallback.ts +162 -0
  847. package/src/codex-thread-key.ts +1 -0
  848. package/src/coding/access-coding-context.test.ts +197 -0
  849. package/src/coding/coding-branch-scope.test.ts +281 -0
  850. package/src/coding/coding-namespace.test.ts +360 -0
  851. package/src/coding/coding-namespace.ts +412 -0
  852. package/src/coding/coding-orchestrator.test.ts +249 -0
  853. package/src/coding/git-context.test.ts +507 -0
  854. package/src/coding/git-context.ts +336 -0
  855. package/src/coding/mcp-set-coding-context.test.ts +174 -0
  856. package/src/coding/review-context.test.ts +316 -0
  857. package/src/coding/review-context.ts +349 -0
  858. package/src/coding/wire-coding-context.test.ts +468 -0
  859. package/src/commitment-ledger.test.ts +78 -0
  860. package/src/commitment-ledger.ts +337 -0
  861. package/src/compat/checks.test.ts +206 -0
  862. package/src/compat/checks.ts +716 -0
  863. package/src/compat/types.ts +33 -0
  864. package/src/compounding/engine.ts +1686 -0
  865. package/src/compounding/preference-consolidator.ts +778 -0
  866. package/src/compression-optimizer.ts +312 -0
  867. package/src/config.test.ts +930 -0
  868. package/src/config.ts +3807 -0
  869. package/src/connectors/codex/instructions.md +160 -0
  870. package/src/connectors/codex/resources/namespace-cheatsheet.md +48 -0
  871. package/src/connectors/codex-marketplace.ts +500 -0
  872. package/src/connectors/codex-materialize-runner.ts +212 -0
  873. package/src/connectors/codex-materialize.ts +983 -0
  874. package/src/connectors/coerce.ts +62 -0
  875. package/src/connectors/index.test.ts +1570 -0
  876. package/src/connectors/index.ts +3222 -0
  877. package/src/connectors/live/framework.ts +164 -0
  878. package/src/connectors/live/github.test.ts +1218 -0
  879. package/src/connectors/live/github.ts +1068 -0
  880. package/src/connectors/live/gmail.test.ts +1706 -0
  881. package/src/connectors/live/gmail.ts +1293 -0
  882. package/src/connectors/live/google-drive.test.ts +696 -0
  883. package/src/connectors/live/google-drive.ts +724 -0
  884. package/src/connectors/live/index.ts +101 -0
  885. package/src/connectors/live/live-connectors.test.ts +689 -0
  886. package/src/connectors/live/notion.test.ts +1109 -0
  887. package/src/connectors/live/notion.ts +978 -0
  888. package/src/connectors/live/registry.ts +103 -0
  889. package/src/connectors/live/state-store.ts +399 -0
  890. package/src/connectors/live/transient-errors.ts +150 -0
  891. package/src/connectors/weclone-installer.test.ts +850 -0
  892. package/src/connectors-cli.ts +513 -0
  893. package/src/console/state.test.ts +224 -0
  894. package/src/console/state.ts +514 -0
  895. package/src/console/trace.test.ts +813 -0
  896. package/src/console/trace.ts +603 -0
  897. package/src/console/tui.test.ts +582 -0
  898. package/src/console/tui.ts +508 -0
  899. package/src/consolidation-operator.ts +182 -0
  900. package/src/consolidation-provenance-check.ts +551 -0
  901. package/src/consolidation-undo.ts +718 -0
  902. package/src/contradiction/contradiction-judge.test.ts +189 -0
  903. package/src/contradiction/contradiction-judge.ts +333 -0
  904. package/src/contradiction/contradiction-review.ts +574 -0
  905. package/src/contradiction/contradiction-scan.ts +504 -0
  906. package/src/contradiction/contradiction.test.ts +2230 -0
  907. package/src/contradiction/index.ts +37 -0
  908. package/src/contradiction/resolution.ts +383 -0
  909. package/src/conversation-index/backend.ts +323 -0
  910. package/src/conversation-index/chunker.ts +47 -0
  911. package/src/conversation-index/cleanup.ts +53 -0
  912. package/src/conversation-index/faiss-adapter.ts +384 -0
  913. package/src/conversation-index/indexer.test.ts +164 -0
  914. package/src/conversation-index/indexer.ts +192 -0
  915. package/src/conversation-index/search.ts +37 -0
  916. package/src/cross-namespace-budget.test.ts +275 -0
  917. package/src/cross-namespace-budget.ts +365 -0
  918. package/src/cue-anchors.ts +163 -0
  919. package/src/curation/index.ts +544 -0
  920. package/src/dashboard-runtime.ts +337 -0
  921. package/src/day-summary.ts +122 -0
  922. package/src/dedup/index.ts +330 -0
  923. package/src/dedup/semantic.test.ts +1577 -0
  924. package/src/dedup/semantic.ts +148 -0
  925. package/src/delinearize.ts +193 -0
  926. package/src/direct-answer-wiring.test.ts +473 -0
  927. package/src/direct-answer-wiring.ts +180 -0
  928. package/src/direct-answer.test.ts +484 -0
  929. package/src/direct-answer.ts +273 -0
  930. package/src/embedding-fallback.ts +565 -0
  931. package/src/enrichment/audit.ts +89 -0
  932. package/src/enrichment/index.ts +27 -0
  933. package/src/enrichment/pipeline.ts +197 -0
  934. package/src/enrichment/provider-registry.ts +85 -0
  935. package/src/enrichment/types.ts +100 -0
  936. package/src/enrichment/web-search-provider.ts +63 -0
  937. package/src/entity-retrieval.ts +774 -0
  938. package/src/entity-schema.ts +239 -0
  939. package/src/evals.ts +1312 -0
  940. package/src/event-order-recall.test.ts +4164 -0
  941. package/src/event-order-recall.ts +2802 -0
  942. package/src/evidence-pack.test.ts +89 -0
  943. package/src/evidence-pack.ts +388 -0
  944. package/src/explicit-capture.ts +530 -0
  945. package/src/explicit-cue-recall.test.ts +3019 -0
  946. package/src/explicit-cue-recall.ts +5545 -0
  947. package/src/extraction-judge-telemetry.ts +234 -0
  948. package/src/extraction-judge-training.ts +221 -0
  949. package/src/extraction-judge.ts +846 -0
  950. package/src/extraction-timeout.test.ts +265 -0
  951. package/src/extraction.ts +2719 -0
  952. package/src/fallback-llm.test.ts +1060 -0
  953. package/src/fallback-llm.ts +918 -0
  954. package/src/focused-list-recall.test.ts +734 -0
  955. package/src/focused-list-recall.ts +1160 -0
  956. package/src/graph-dashboard-diff.ts +35 -0
  957. package/src/graph-dashboard-key.ts +5 -0
  958. package/src/graph-dashboard-parser.ts +104 -0
  959. package/src/graph-edge-reinforcement.ts +192 -0
  960. package/src/graph-events.ts +151 -0
  961. package/src/graph-recall.test.ts +164 -0
  962. package/src/graph-recall.ts +189 -0
  963. package/src/graph-retrieval.test.ts +809 -0
  964. package/src/graph-retrieval.ts +823 -0
  965. package/src/graph-snapshot.ts +329 -0
  966. package/src/graph.ts +813 -0
  967. package/src/harmonic-retrieval.ts +223 -0
  968. package/src/himem.ts +154 -0
  969. package/src/hygiene.ts +87 -0
  970. package/src/identity-continuity.ts +333 -0
  971. package/src/importance.ts +328 -0
  972. package/src/importers/base.test.ts +294 -0
  973. package/src/importers/base.ts +436 -0
  974. package/src/importers/index.ts +21 -0
  975. package/src/index.ts +1204 -0
  976. package/src/intent.ts +154 -0
  977. package/src/json-extract.ts +85 -0
  978. package/src/json-store.ts +42 -0
  979. package/src/lcm/archive.ts +617 -0
  980. package/src/lcm/dag.ts +199 -0
  981. package/src/lcm/engine.ts +645 -0
  982. package/src/lcm/index.ts +7 -0
  983. package/src/lcm/queue.test.ts +178 -0
  984. package/src/lcm/queue.ts +200 -0
  985. package/src/lcm/recall.ts +117 -0
  986. package/src/lcm/schema.ts +154 -0
  987. package/src/lcm/summarizer.ts +235 -0
  988. package/src/lcm/tools.ts +191 -0
  989. package/src/lcm-engine.test.ts +660 -0
  990. package/src/legacy-hook-compat.test.ts +20 -0
  991. package/src/legacy-hook-compat.ts +45 -0
  992. package/src/lifecycle.ts +289 -0
  993. package/src/live-connectors-runner.ts +385 -0
  994. package/src/local-llm-qos.test.ts +303 -0
  995. package/src/local-llm-thinking.test.ts +292 -0
  996. package/src/local-llm.ts +1464 -0
  997. package/src/logger.ts +49 -0
  998. package/src/maintenance/archive-observations.ts +147 -0
  999. package/src/maintenance/backup-stamp.ts +3 -0
  1000. package/src/maintenance/dreams-ledger.ts +516 -0
  1001. package/src/maintenance/first-start-migration.ts +362 -0
  1002. package/src/maintenance/forget.test.ts +206 -0
  1003. package/src/maintenance/forget.ts +126 -0
  1004. package/src/maintenance/graph-edge-decay.test.ts +409 -0
  1005. package/src/maintenance/graph-edge-decay.ts +394 -0
  1006. package/src/maintenance/memory-governance-cron.ts +447 -0
  1007. package/src/maintenance/memory-governance.ts +1039 -0
  1008. package/src/maintenance/migrate-observations.ts +216 -0
  1009. package/src/maintenance/observation-ledger-utils.ts +54 -0
  1010. package/src/maintenance/pattern-reinforcement.test.ts +875 -0
  1011. package/src/maintenance/pattern-reinforcement.ts +369 -0
  1012. package/src/maintenance/purge.ts +334 -0
  1013. package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +78 -0
  1014. package/src/maintenance/rebuild-memory-projection.ts +1234 -0
  1015. package/src/maintenance/rebuild-observations.ts +178 -0
  1016. package/src/maintenance/tier-stats.test.ts +378 -0
  1017. package/src/maintenance/tier-stats.ts +222 -0
  1018. package/src/mcp-memory-inspector-app.ts +421 -0
  1019. package/src/memory-action-policy.ts +80 -0
  1020. package/src/memory-cache.ts +208 -0
  1021. package/src/memory-extension/claude-code-publisher.ts +51 -0
  1022. package/src/memory-extension/codex-publisher.ts +149 -0
  1023. package/src/memory-extension/hermes-publisher.ts +51 -0
  1024. package/src/memory-extension/index.ts +100 -0
  1025. package/src/memory-extension/shared-instructions.ts +133 -0
  1026. package/src/memory-extension/types.ts +86 -0
  1027. package/src/memory-extension-host/host-discovery.ts +276 -0
  1028. package/src/memory-extension-host/index.ts +14 -0
  1029. package/src/memory-extension-host/render-extensions-block.ts +73 -0
  1030. package/src/memory-extension-host/types.ts +21 -0
  1031. package/src/memory-lifecycle-ledger-utils.ts +116 -0
  1032. package/src/memory-projection-format.ts +11 -0
  1033. package/src/memory-projection-store.ts +951 -0
  1034. package/src/memory-provenance.test.ts +196 -0
  1035. package/src/memory-provenance.ts +484 -0
  1036. package/src/memory-worth-bench.test.ts +71 -0
  1037. package/src/memory-worth-bench.ts +265 -0
  1038. package/src/memory-worth-filter.test.ts +209 -0
  1039. package/src/memory-worth-filter.ts +204 -0
  1040. package/src/memory-worth-frontmatter.test.ts +311 -0
  1041. package/src/memory-worth-outcomes.test.ts +316 -0
  1042. package/src/memory-worth-outcomes.ts +286 -0
  1043. package/src/memory-worth.test.ts +317 -0
  1044. package/src/memory-worth.ts +215 -0
  1045. package/src/message-parts/index.ts +806 -0
  1046. package/src/message-parts/message-parts.test.ts +421 -0
  1047. package/src/migrate/from-engram.ts +789 -0
  1048. package/src/model-registry.ts +313 -0
  1049. package/src/models-json.ts +76 -0
  1050. package/src/namespaces/migrate.ts +187 -0
  1051. package/src/namespaces/path.ts +25 -0
  1052. package/src/namespaces/principal.test.ts +195 -0
  1053. package/src/namespaces/principal.ts +86 -0
  1054. package/src/namespaces/search.test.ts +105 -0
  1055. package/src/namespaces/search.ts +233 -0
  1056. package/src/namespaces/storage.ts +74 -0
  1057. package/src/native-knowledge.ts +1823 -0
  1058. package/src/negative.ts +72 -0
  1059. package/src/network/tailscale.ts +179 -0
  1060. package/src/network/webdav.ts +385 -0
  1061. package/src/objective-state-writers.ts +951 -0
  1062. package/src/objective-state.ts +320 -0
  1063. package/src/onboarding/index.ts +529 -0
  1064. package/src/openai-chat-compat.ts +56 -0
  1065. package/src/operator-toolkit.ts +2132 -0
  1066. package/src/opik-exporter.test.ts +72 -0
  1067. package/src/opik-exporter.ts +587 -0
  1068. package/src/orchestrator-extraction-queue.test.ts +197 -0
  1069. package/src/orchestrator-flush.test.ts +1171 -0
  1070. package/src/orchestrator-pattern-reinforcement.test.ts +128 -0
  1071. package/src/orchestrator-source-attribution.test.ts +701 -0
  1072. package/src/orchestrator.ts +16368 -0
  1073. package/src/page-versioning.ts +450 -0
  1074. package/src/patterns-cli.ts +574 -0
  1075. package/src/peers/index.ts +54 -0
  1076. package/src/peers/migrate-from-identity-anchor.test.ts +291 -0
  1077. package/src/peers/migrate-from-identity-anchor.ts +350 -0
  1078. package/src/peers/peers.test.ts +419 -0
  1079. package/src/peers/profile-reasoner.ts +694 -0
  1080. package/src/peers/storage.ts +1350 -0
  1081. package/src/peers/types.ts +138 -0
  1082. package/src/plugin-id.ts +84 -0
  1083. package/src/policy-runtime.ts +209 -0
  1084. package/src/procedural/procedure-miner.ts +150 -0
  1085. package/src/procedural/procedure-recall.ts +93 -0
  1086. package/src/procedural/procedure-stats.ts +213 -0
  1087. package/src/procedural/procedure-types.ts +132 -0
  1088. package/src/procedural/reinforcement-core.test.ts +132 -0
  1089. package/src/procedural/reinforcement-core.ts +73 -0
  1090. package/src/profiling.test.ts +263 -0
  1091. package/src/profiling.ts +435 -0
  1092. package/src/projection/index.ts +398 -0
  1093. package/src/qmd-recall-cache.test.ts +138 -0
  1094. package/src/qmd-recall-cache.ts +111 -0
  1095. package/src/qmd.test.ts +257 -0
  1096. package/src/qmd.ts +2614 -0
  1097. package/src/reasoning-trace-recall.ts +201 -0
  1098. package/src/reasoning-trace-types.ts +235 -0
  1099. package/src/recall-audit-anomaly.test.ts +246 -0
  1100. package/src/recall-audit-anomaly.ts +297 -0
  1101. package/src/recall-audit.test.ts +51 -0
  1102. package/src/recall-audit.ts +72 -0
  1103. package/src/recall-budget-config.test.ts +87 -0
  1104. package/src/recall-disclosure-escalation.test.ts +196 -0
  1105. package/src/recall-disclosure-escalation.ts +158 -0
  1106. package/src/recall-disclosure-shaping.test.ts +146 -0
  1107. package/src/recall-disclosure.test.ts +214 -0
  1108. package/src/recall-explain-renderer.test.ts +140 -0
  1109. package/src/recall-explain-renderer.ts +356 -0
  1110. package/src/recall-mmr.test.ts +808 -0
  1111. package/src/recall-mmr.ts +607 -0
  1112. package/src/recall-qos.test.ts +85 -0
  1113. package/src/recall-qos.ts +82 -0
  1114. package/src/recall-query-policy.ts +221 -0
  1115. package/src/recall-state.test.ts +233 -0
  1116. package/src/recall-state.ts +456 -0
  1117. package/src/recall-tag-filter.ts +143 -0
  1118. package/src/recall-tokenization.ts +35 -0
  1119. package/src/recall-xray-cli.test.ts +118 -0
  1120. package/src/recall-xray-cli.ts +100 -0
  1121. package/src/recall-xray-disclosure-telemetry.test.ts +183 -0
  1122. package/src/recall-xray-renderer.test.ts +539 -0
  1123. package/src/recall-xray-renderer.ts +487 -0
  1124. package/src/recall-xray.test.ts +503 -0
  1125. package/src/recall-xray.ts +621 -0
  1126. package/src/reconstruct.ts +41 -0
  1127. package/src/release-changelog.ts +35 -0
  1128. package/src/relevance.ts +67 -0
  1129. package/src/replay/normalizers/chatgpt.ts +133 -0
  1130. package/src/replay/normalizers/claude.ts +102 -0
  1131. package/src/replay/normalizers/openclaw.ts +119 -0
  1132. package/src/replay/normalizers/shared.ts +69 -0
  1133. package/src/replay/runner.ts +197 -0
  1134. package/src/replay/types.ts +143 -0
  1135. package/src/rerank.test.ts +48 -0
  1136. package/src/rerank.ts +176 -0
  1137. package/src/resolve-auth-token.test.ts +226 -0
  1138. package/src/resolve-auth-token.ts +151 -0
  1139. package/src/resolve-provider-secret.test.ts +187 -0
  1140. package/src/resolve-provider-secret.ts +410 -0
  1141. package/src/response-guidance-recall.test.ts +3952 -0
  1142. package/src/response-guidance-recall.ts +4431 -0
  1143. package/src/resume-bundles.ts +415 -0
  1144. package/src/retrieval-agents.ts +623 -0
  1145. package/src/retrieval-tiers.ts +25 -0
  1146. package/src/retrieval.ts +104 -0
  1147. package/src/review/index.test.ts +201 -0
  1148. package/src/review/index.ts +536 -0
  1149. package/src/routing/engine.ts +162 -0
  1150. package/src/routing/store.ts +321 -0
  1151. package/src/runtime/better-sqlite.test.ts +32 -0
  1152. package/src/runtime/better-sqlite.ts +76 -0
  1153. package/src/runtime/child-process.ts +67 -0
  1154. package/src/runtime/env.ts +48 -0
  1155. package/src/sanitize.ts +58 -0
  1156. package/src/schemas.ts +449 -0
  1157. package/src/sdk-compat.ts +87 -0
  1158. package/src/search/document-scanner.ts +96 -0
  1159. package/src/search/embed-helper.ts +142 -0
  1160. package/src/search/factory.ts +189 -0
  1161. package/src/search/index.ts +10 -0
  1162. package/src/search/lancedb-backend.ts +342 -0
  1163. package/src/search/meilisearch-backend.ts +232 -0
  1164. package/src/search/noop-backend.ts +57 -0
  1165. package/src/search/orama-backend.ts +358 -0
  1166. package/src/search/port.ts +86 -0
  1167. package/src/search/remote-backend.ts +124 -0
  1168. package/src/secure-store/cipher.ts +271 -0
  1169. package/src/secure-store/cli-handlers.ts +355 -0
  1170. package/src/secure-store/cli-renderer.ts +131 -0
  1171. package/src/secure-store/header.ts +373 -0
  1172. package/src/secure-store/index.ts +137 -0
  1173. package/src/secure-store/kdf.ts +263 -0
  1174. package/src/secure-store/keyring.ts +106 -0
  1175. package/src/secure-store/metadata.ts +394 -0
  1176. package/src/secure-store/passphrase-reader.ts +252 -0
  1177. package/src/secure-store/secure-fs.ts +571 -0
  1178. package/src/secure-store/secure-store.test.ts +755 -0
  1179. package/src/semantic-chunking.ts +545 -0
  1180. package/src/semantic-consolidation.test.ts +182 -0
  1181. package/src/semantic-consolidation.ts +432 -0
  1182. package/src/semantic-rule-promotion.ts +183 -0
  1183. package/src/semantic-rule-verifier.ts +160 -0
  1184. package/src/session-integrity.ts +569 -0
  1185. package/src/session-observer-bands.ts +11 -0
  1186. package/src/session-observer-state.ts +346 -0
  1187. package/src/session-toggles.test.ts +96 -0
  1188. package/src/session-toggles.ts +159 -0
  1189. package/src/shared-context/manager.ts +810 -0
  1190. package/src/signal.ts +84 -0
  1191. package/src/skills-registry.test.ts +277 -0
  1192. package/src/skills-registry.ts +120 -0
  1193. package/src/source-attribution-roundtrip.test.ts +215 -0
  1194. package/src/source-attribution.test.ts +1425 -0
  1195. package/src/source-attribution.ts +639 -0
  1196. package/src/spaces/index.ts +627 -0
  1197. package/src/storage-paths.ts +117 -0
  1198. package/src/storage.ts +6657 -0
  1199. package/src/store-contract.ts +55 -0
  1200. package/src/summarizer.ts +844 -0
  1201. package/src/summary-snapshot.test.ts +681 -0
  1202. package/src/summary-snapshot.ts +238 -0
  1203. package/src/surfaces/dreams.test.ts +394 -0
  1204. package/src/surfaces/dreams.ts +346 -0
  1205. package/src/surfaces/heartbeat.test.ts +415 -0
  1206. package/src/surfaces/heartbeat.ts +325 -0
  1207. package/src/sync/index.ts +308 -0
  1208. package/src/targeted-fact-recall.test.ts +1694 -0
  1209. package/src/targeted-fact-recall.ts +2905 -0
  1210. package/src/taxonomy/default-taxonomy.ts +87 -0
  1211. package/src/taxonomy/index.ts +26 -0
  1212. package/src/taxonomy/resolver-doc-generator.ts +57 -0
  1213. package/src/taxonomy/resolver.ts +184 -0
  1214. package/src/taxonomy/taxonomy-loader.ts +186 -0
  1215. package/src/taxonomy/types.ts +48 -0
  1216. package/src/telemetry-transcript.ts +70 -0
  1217. package/src/temporal-index.ts +890 -0
  1218. package/src/temporal-supersession.test.ts +2703 -0
  1219. package/src/temporal-supersession.ts +493 -0
  1220. package/src/temporal-validity.test.ts +448 -0
  1221. package/src/temporal-validity.ts +123 -0
  1222. package/src/threading.ts +395 -0
  1223. package/src/tier-migration.ts +124 -0
  1224. package/src/tier-routing.ts +102 -0
  1225. package/src/tmt.ts +462 -0
  1226. package/src/tokens.test.ts +178 -0
  1227. package/src/tokens.ts +279 -0
  1228. package/src/topics.ts +147 -0
  1229. package/src/training-export/cli-date-validation.test.ts +258 -0
  1230. package/src/training-export/converter.test.ts +452 -0
  1231. package/src/training-export/converter.ts +319 -0
  1232. package/src/training-export/date-parse.ts +117 -0
  1233. package/src/training-export/index.ts +26 -0
  1234. package/src/training-export/registry.test.ts +85 -0
  1235. package/src/training-export/registry.ts +57 -0
  1236. package/src/training-export/types.ts +31 -0
  1237. package/src/transcript.ts +1179 -0
  1238. package/src/transfer/autodetect.ts +30 -0
  1239. package/src/transfer/backup.ts +138 -0
  1240. package/src/transfer/capsule-crypto.ts +485 -0
  1241. package/src/transfer/capsule-encrypt.test.ts +690 -0
  1242. package/src/transfer/capsule-export.ts +543 -0
  1243. package/src/transfer/capsule-fork.ts +375 -0
  1244. package/src/transfer/capsule-import.ts +564 -0
  1245. package/src/transfer/capsule-merge.ts +433 -0
  1246. package/src/transfer/conflict-policy.ts +16 -0
  1247. package/src/transfer/constants.ts +13 -0
  1248. package/src/transfer/exclusions.ts +37 -0
  1249. package/src/transfer/export-json.ts +65 -0
  1250. package/src/transfer/export-md.ts +59 -0
  1251. package/src/transfer/export-sqlite.ts +52 -0
  1252. package/src/transfer/fs-utils.ts +269 -0
  1253. package/src/transfer/import-json.ts +108 -0
  1254. package/src/transfer/import-md.ts +84 -0
  1255. package/src/transfer/import-sqlite.ts +100 -0
  1256. package/src/transfer/integrity.ts +71 -0
  1257. package/src/transfer/sqlite-schema.ts +16 -0
  1258. package/src/transfer/types.ts +297 -0
  1259. package/src/trust-zones.ts +1186 -0
  1260. package/src/types.ts +3074 -0
  1261. package/src/user-model.test.ts +124 -0
  1262. package/src/user-model.ts +162 -0
  1263. package/src/utility-learner.ts +353 -0
  1264. package/src/utility-runtime.ts +88 -0
  1265. package/src/utility-telemetry.ts +215 -0
  1266. package/src/utils/category-dir.ts +44 -0
  1267. package/src/utils/errno.ts +6 -0
  1268. package/src/utils/iso-timestamp.test.ts +37 -0
  1269. package/src/utils/iso-timestamp.ts +164 -0
  1270. package/src/utils/path.ts +26 -0
  1271. package/src/verified-recall.ts +138 -0
  1272. package/src/version-utils.test.ts +10 -0
  1273. package/src/version-utils.ts +9 -0
  1274. package/src/whitespace.ts +10 -0
  1275. package/src/work/board.ts +359 -0
  1276. package/src/work/boundary.ts +107 -0
  1277. package/src/work/storage.ts +436 -0
  1278. package/src/work/types.ts +82 -0
  1279. package/src/work-product-ledger.ts +265 -0
  1280. package/dist/access-service-BkXt3di1.d.ts +0 -2039
  1281. package/dist/capsule-crypto-SJS5VVAP.js +0 -18
  1282. package/dist/capsule-export-LLEVB2RG.js +0 -17
  1283. package/dist/capsule-import-UW45R2MZ.js +0 -16
  1284. package/dist/capsule-merge-DI7PNQ2H.js +0 -189
  1285. package/dist/chunk-2LGMW3DJ.js +0 -111
  1286. package/dist/chunk-2YMTO4ZJ.js +0 -265
  1287. package/dist/chunk-2YMTO4ZJ.js.map +0 -1
  1288. package/dist/chunk-363MWCD3.js +0 -9683
  1289. package/dist/chunk-363MWCD3.js.map +0 -1
  1290. package/dist/chunk-36CTNQY7.js +0 -1554
  1291. package/dist/chunk-36CTNQY7.js.map +0 -1
  1292. package/dist/chunk-457A4P3L.js +0 -119
  1293. package/dist/chunk-457A4P3L.js.map +0 -1
  1294. package/dist/chunk-4DXC6HQQ.js +0 -1837
  1295. package/dist/chunk-4DXC6HQQ.js.map +0 -1
  1296. package/dist/chunk-4IS4SXIQ.js +0 -2040
  1297. package/dist/chunk-57QNCUEZ.js +0 -1914
  1298. package/dist/chunk-57QNCUEZ.js.map +0 -1
  1299. package/dist/chunk-6AUUAZEX.js +0 -150
  1300. package/dist/chunk-6AUUAZEX.js.map +0 -1
  1301. package/dist/chunk-6TBWYBJ3.js +0 -236
  1302. package/dist/chunk-6XA7UN4Z.js +0 -135
  1303. package/dist/chunk-6Z6UH6TK.js +0 -2129
  1304. package/dist/chunk-6Z6UH6TK.js.map +0 -1
  1305. package/dist/chunk-74EMIVE4.js +0 -329
  1306. package/dist/chunk-74EMIVE4.js.map +0 -1
  1307. package/dist/chunk-74WWN7ZW.js +0 -82
  1308. package/dist/chunk-74WWN7ZW.js.map +0 -1
  1309. package/dist/chunk-767ODGE6.js +0 -183
  1310. package/dist/chunk-A4ACKWIW.js +0 -289
  1311. package/dist/chunk-A4ACKWIW.js.map +0 -1
  1312. package/dist/chunk-ASAITVLA.js +0 -64
  1313. package/dist/chunk-ASAITVLA.js.map +0 -1
  1314. package/dist/chunk-C5HUWVH2.js +0 -891
  1315. package/dist/chunk-C5HUWVH2.js.map +0 -1
  1316. package/dist/chunk-D54LZC5L.js +0 -147
  1317. package/dist/chunk-DF3RVK3X.js +0 -119
  1318. package/dist/chunk-DF3RVK3X.js.map +0 -1
  1319. package/dist/chunk-E6K4NIEU.js +0 -747
  1320. package/dist/chunk-E6K4NIEU.js.map +0 -1
  1321. package/dist/chunk-EEQLFRUM.js +0 -89
  1322. package/dist/chunk-EQINRHYR.js +0 -672
  1323. package/dist/chunk-EQINRHYR.js.map +0 -1
  1324. package/dist/chunk-ETOW6ACV.js +0 -158
  1325. package/dist/chunk-ETOW6ACV.js.map +0 -1
  1326. package/dist/chunk-EYNQTST2.js +0 -721
  1327. package/dist/chunk-FYIYMQ5N.js +0 -221
  1328. package/dist/chunk-FYIYMQ5N.js.map +0 -1
  1329. package/dist/chunk-G2WADRQ3.js +0 -219
  1330. package/dist/chunk-G4SK7DSQ.js +0 -121
  1331. package/dist/chunk-GGD5W7TB.js +0 -105
  1332. package/dist/chunk-GGD5W7TB.js.map +0 -1
  1333. package/dist/chunk-GVPWB7EY.js +0 -390
  1334. package/dist/chunk-GVPWB7EY.js.map +0 -1
  1335. package/dist/chunk-HJYHRE4S.js +0 -647
  1336. package/dist/chunk-I6BQZSML.js +0 -1451
  1337. package/dist/chunk-I6BQZSML.js.map +0 -1
  1338. package/dist/chunk-IBX3VFOM.js +0 -446
  1339. package/dist/chunk-IBX3VFOM.js.map +0 -1
  1340. package/dist/chunk-IXEJRKCZ.js +0 -18
  1341. package/dist/chunk-JBMSGZEQ.js +0 -441
  1342. package/dist/chunk-JBMSGZEQ.js.map +0 -1
  1343. package/dist/chunk-JRNQ3RNA.js +0 -284
  1344. package/dist/chunk-JRNQ3RNA.js.map +0 -1
  1345. package/dist/chunk-K6WK37A6.js +0 -865
  1346. package/dist/chunk-K6WK37A6.js.map +0 -1
  1347. package/dist/chunk-KBYWQWSB.js +0 -271
  1348. package/dist/chunk-KUHRUM6B.js +0 -14397
  1349. package/dist/chunk-KUHRUM6B.js.map +0 -1
  1350. package/dist/chunk-KWBPHZUU.js +0 -83
  1351. package/dist/chunk-KWBPHZUU.js.map +0 -1
  1352. package/dist/chunk-LIO5X3CM.js +0 -596
  1353. package/dist/chunk-MARWOCVP.js +0 -48
  1354. package/dist/chunk-MCC6KDQF.js +0 -5095
  1355. package/dist/chunk-MCC6KDQF.js.map +0 -1
  1356. package/dist/chunk-N5AKDXAI.js +0 -74
  1357. package/dist/chunk-NN3LPQ5D.js +0 -936
  1358. package/dist/chunk-NN3LPQ5D.js.map +0 -1
  1359. package/dist/chunk-O4XJUPSF.js +0 -533
  1360. package/dist/chunk-O4XJUPSF.js.map +0 -1
  1361. package/dist/chunk-OA3L7BFR.js +0 -183
  1362. package/dist/chunk-OA3L7BFR.js.map +0 -1
  1363. package/dist/chunk-OR64ZGRZ.js +0 -23
  1364. package/dist/chunk-P73JTV34.js +0 -275
  1365. package/dist/chunk-P73JTV34.js.map +0 -1
  1366. package/dist/chunk-P77UEOU2.js +0 -1521
  1367. package/dist/chunk-P77UEOU2.js.map +0 -1
  1368. package/dist/chunk-PB5KW5PL.js +0 -118
  1369. package/dist/chunk-PHNGXFQ6.js +0 -623
  1370. package/dist/chunk-PHNGXFQ6.js.map +0 -1
  1371. package/dist/chunk-QIGOEM65.js +0 -228
  1372. package/dist/chunk-RXTFCYQF.js +0 -108
  1373. package/dist/chunk-S2JJBLJG.js +0 -2101
  1374. package/dist/chunk-S2JJBLJG.js.map +0 -1
  1375. package/dist/chunk-S3IP6R6K.js +0 -219
  1376. package/dist/chunk-S3IP6R6K.js.map +0 -1
  1377. package/dist/chunk-SRBJUAMP.js +0 -403
  1378. package/dist/chunk-SRBJUAMP.js.map +0 -1
  1379. package/dist/chunk-URB2WSKZ.js +0 -350
  1380. package/dist/chunk-URB2WSKZ.js.map +0 -1
  1381. package/dist/chunk-VQXK37XA.js +0 -26
  1382. package/dist/chunk-VQXK37XA.js.map +0 -1
  1383. package/dist/chunk-VTU2B4VF.js +0 -146
  1384. package/dist/chunk-VTU2B4VF.js.map +0 -1
  1385. package/dist/chunk-VX2IUQFE.js +0 -613
  1386. package/dist/chunk-VX2IUQFE.js.map +0 -1
  1387. package/dist/chunk-WGK4VHGP.js +0 -4292
  1388. package/dist/chunk-WGK4VHGP.js.map +0 -1
  1389. package/dist/chunk-WTFWLUSX.js +0 -827
  1390. package/dist/chunk-WTFWLUSX.js.map +0 -1
  1391. package/dist/chunk-XJKFSSDW.js +0 -726
  1392. package/dist/chunk-XJKFSSDW.js.map +0 -1
  1393. package/dist/chunk-XMHBH5H6.js +0 -283
  1394. package/dist/chunk-XMHBH5H6.js.map +0 -1
  1395. package/dist/chunk-XMVFHBHT.js +0 -277
  1396. package/dist/chunk-Y5KDIOKF.js +0 -2403
  1397. package/dist/chunk-Y5KDIOKF.js.map +0 -1
  1398. package/dist/chunk-YNB73F22.js +0 -137
  1399. package/dist/chunk-YNB73F22.js.map +0 -1
  1400. package/dist/chunk-Z2E7VW55.js +0 -335
  1401. package/dist/chunk-Z2E7VW55.js.map +0 -1
  1402. package/dist/chunk-Z5S5HNGY.js +0 -2280
  1403. package/dist/chunk-Z5S5HNGY.js.map +0 -1
  1404. package/dist/chunk-ZL4S7ARC.js +0 -53
  1405. package/dist/chunk-ZTSE2ZJ6.js +0 -190
  1406. package/dist/chunk-ZTSE2ZJ6.js.map +0 -1
  1407. package/dist/cli-Cvy2SNhF.d.ts +0 -1259
  1408. package/dist/codex-materialize-CQlLTzke.d.ts +0 -139
  1409. package/dist/connectors-cli-DFGtY2DB.d.ts +0 -257
  1410. package/dist/contradiction-review-5LTTVDQV.js +0 -22
  1411. package/dist/contradiction-scan-3Z6YW7YA.js +0 -413
  1412. package/dist/contradiction-scan-3Z6YW7YA.js.map +0 -1
  1413. package/dist/engine-FOC3IJLA.js +0 -28
  1414. package/dist/fs-utils-IRVUFB6G.js +0 -30
  1415. package/dist/graph-edge-decay-PWB63GRE.js +0 -207
  1416. package/dist/index-1qIcnbG1.d.ts +0 -34
  1417. package/dist/memory-governance-F3QOJGEY.js +0 -37
  1418. package/dist/memory-projection-store-CY8TU40w.d.ts +0 -222
  1419. package/dist/orchestrator-AOQMo7QI.d.ts +0 -1784
  1420. package/dist/path-RMTY5Y5A.js +0 -9
  1421. package/dist/port-B6VEDIkC.d.ts +0 -53
  1422. package/dist/resolution-YGIBORXI.js +0 -101
  1423. package/dist/resolution-YGIBORXI.js.map +0 -1
  1424. package/dist/secure-store-4R2GSO7S.js +0 -156
  1425. package/dist/semantic-consolidation-ByBXb-sf.d.ts +0 -180
  1426. package/dist/state-store-3EH7HYIN.js +0 -16
  1427. package/dist/types-V3FJ26TF.js +0 -30
  1428. /package/dist/{capsule-crypto-SJS5VVAP.js.map → action-confidence.js.map} +0 -0
  1429. /package/dist/{capsule-export-LLEVB2RG.js.map → adapters/claude-code.js.map} +0 -0
  1430. /package/dist/{capsule-import-UW45R2MZ.js.map → adapters/codex.js.map} +0 -0
  1431. /package/dist/{contradiction-review-5LTTVDQV.js.map → adapters/hermes.js.map} +0 -0
  1432. /package/dist/{engine-FOC3IJLA.js.map → adapters/index.js.map} +0 -0
  1433. /package/dist/{fs-utils-IRVUFB6G.js.map → adapters/registry.js.map} +0 -0
  1434. /package/dist/{memory-governance-F3QOJGEY.js.map → adapters/replit.js.map} +0 -0
  1435. /package/dist/{path-RMTY5Y5A.js.map → adapters/types.js.map} +0 -0
  1436. /package/dist/{secure-store-4R2GSO7S.js.map → capsule-crypto-5CYAGVC5.js.map} +0 -0
  1437. /package/dist/{capsule-merge-DI7PNQ2H.js.map → capsule-merge-4MGKE7C5.js.map} +0 -0
  1438. /package/dist/{chunk-G4SK7DSQ.js.map → chunk-2WWLHTZY.js.map} +0 -0
  1439. /package/dist/{chunk-KBYWQWSB.js.map → chunk-4CRG46BG.js.map} +0 -0
  1440. /package/dist/{chunk-LIO5X3CM.js.map → chunk-7IASACLB.js.map} +0 -0
  1441. /package/dist/{chunk-EYNQTST2.js.map → chunk-EFJ3MQ4V.js.map} +0 -0
  1442. /package/dist/{chunk-D54LZC5L.js.map → chunk-FDU6HUUL.js.map} +0 -0
  1443. /package/dist/{chunk-QIGOEM65.js.map → chunk-GGKRUQOO.js.map} +0 -0
  1444. /package/dist/{chunk-HJYHRE4S.js.map → chunk-GL6I6MEQ.js.map} +0 -0
  1445. /package/dist/{state-store-3EH7HYIN.js.map → chunk-HHLLAQGZ.js.map} +0 -0
  1446. /package/dist/{chunk-4IS4SXIQ.js.map → chunk-HXXBL2KD.js.map} +0 -0
  1447. /package/dist/{chunk-767ODGE6.js.map → chunk-KNKUID7G.js.map} +0 -0
  1448. /package/dist/{chunk-6TBWYBJ3.js.map → chunk-LPMVBPA3.js.map} +0 -0
  1449. /package/dist/{chunk-PB5KW5PL.js.map → chunk-MC26UJIM.js.map} +0 -0
  1450. /package/dist/{chunk-ZL4S7ARC.js.map → chunk-MT4HVDUZ.js.map} +0 -0
  1451. /package/dist/{chunk-G2WADRQ3.js.map → chunk-MY6TPVXW.js.map} +0 -0
  1452. /package/dist/{chunk-OR64ZGRZ.js.map → chunk-NNVTUXEB.js.map} +0 -0
  1453. /package/dist/{chunk-RXTFCYQF.js.map → chunk-P4NEIHUT.js.map} +0 -0
  1454. /package/dist/{chunk-IXEJRKCZ.js.map → chunk-QRNI5JBH.js.map} +0 -0
  1455. /package/dist/{chunk-EEQLFRUM.js.map → chunk-RRF5UOBJ.js.map} +0 -0
  1456. /package/dist/{types-V3FJ26TF.js.map → chunk-SEDEKFYQ.js.map} +0 -0
  1457. /package/dist/{chunk-2LGMW3DJ.js.map → chunk-U3PN77QT.js.map} +0 -0
  1458. /package/dist/{chunk-XMVFHBHT.js.map → chunk-U3WSW6PZ.js.map} +0 -0
  1459. /package/dist/{chunk-N5AKDXAI.js.map → chunk-UWVJF25J.js.map} +0 -0
  1460. /package/dist/{chunk-MARWOCVP.js.map → chunk-XIG5PDM7.js.map} +0 -0
  1461. /package/dist/{chunk-6XA7UN4Z.js.map → chunk-XVZ7B3HG.js.map} +0 -0
  1462. /package/dist/{graph-edge-decay-PWB63GRE.js.map → graph-edge-decay-5DI5GUNL.js.map} +0 -0
@@ -0,0 +1,1218 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import {
5
+ GITHUB_CONNECTOR_ID,
6
+ GITHUB_CURSOR_KIND,
7
+ GITHUB_DEFAULT_POLL_INTERVAL_MS,
8
+ createGitHubConnector,
9
+ isTransientGitHubError,
10
+ validateGitHubConfig,
11
+ type GitHubComment,
12
+ type GitHubFetchFn,
13
+ type GitHubSyncResult,
14
+ } from "./github.js";
15
+ import type { ConnectorCursor } from "./framework.js";
16
+
17
+ /**
18
+ * Tests for the GitHub connector (#683 PR 5/6). All GitHub API calls are
19
+ * stubbed via the `fetchFn` test hook — the suite never touches the network.
20
+ *
21
+ * Per CLAUDE.md privacy rules: no real tokens, no real usernames, no real
22
+ * repo names. All inputs are obviously synthetic.
23
+ */
24
+
25
+ // ---------------------------------------------------------------------------
26
+ // Synthetic test data
27
+ // ---------------------------------------------------------------------------
28
+
29
+ const SYNTHETIC_TOKEN = "ghp_synthetic_token_DO_NOT_USE_0000000000000000";
30
+ const SYNTHETIC_LOGIN = "synthetic-user";
31
+ const REPO_A = "synthetic-org/repo-alpha";
32
+ const REPO_B = "synthetic-org/repo-beta";
33
+
34
+ const SYNTHETIC_CONFIG = Object.freeze({
35
+ token: SYNTHETIC_TOKEN,
36
+ userLogin: SYNTHETIC_LOGIN,
37
+ repos: [REPO_A],
38
+ });
39
+
40
+ function makeComment(
41
+ id: number,
42
+ login: string,
43
+ body: string,
44
+ updatedAt: string,
45
+ htmlUrl?: string,
46
+ ): GitHubComment {
47
+ return {
48
+ id,
49
+ body,
50
+ user: { login },
51
+ created_at: updatedAt,
52
+ updated_at: updatedAt,
53
+ html_url: htmlUrl ?? `https://github.com/${REPO_A}/issues/1#issuecomment-${id}`,
54
+ };
55
+ }
56
+
57
+ // ---------------------------------------------------------------------------
58
+ // Mock fetch builder
59
+ // ---------------------------------------------------------------------------
60
+
61
+ type HandlerEntry = {
62
+ match: (url: string) => boolean;
63
+ respond: (url: string) => { status: number; data: unknown };
64
+ };
65
+
66
+ function makeFetch(handlers: HandlerEntry[]): GitHubFetchFn {
67
+ return async (url) => {
68
+ for (const handler of handlers) {
69
+ if (handler.match(url)) {
70
+ const { status, data } = handler.respond(url);
71
+ return {
72
+ ok: status >= 200 && status < 300,
73
+ status,
74
+ headers: {
75
+ get: (_name: string) => null,
76
+ },
77
+ json: async () => data,
78
+ };
79
+ }
80
+ }
81
+ throw new Error(`fetch stub: no handler for ${url}`);
82
+ };
83
+ }
84
+
85
+ /** Returns an empty array for all API calls. */
86
+ function emptyFetch(): GitHubFetchFn {
87
+ return makeFetch([
88
+ {
89
+ match: () => true,
90
+ respond: () => ({ status: 200, data: [] }),
91
+ },
92
+ ]);
93
+ }
94
+
95
+ function makeGitHubCursor(watermarks: Record<string, string>): ConnectorCursor {
96
+ return {
97
+ kind: GITHUB_CURSOR_KIND,
98
+ value: JSON.stringify({ watermarks }),
99
+ updatedAt: "2026-04-25T00:00:00.000Z",
100
+ };
101
+ }
102
+
103
+ // ---------------------------------------------------------------------------
104
+ // Config validation
105
+ // ---------------------------------------------------------------------------
106
+
107
+ test("validateGitHubConfig accepts a minimal valid config", () => {
108
+ const cfg = validateGitHubConfig({
109
+ token: SYNTHETIC_TOKEN,
110
+ userLogin: SYNTHETIC_LOGIN,
111
+ });
112
+ assert.equal(cfg.token, SYNTHETIC_TOKEN);
113
+ assert.equal(cfg.userLogin, SYNTHETIC_LOGIN);
114
+ assert.deepEqual([...cfg.repos], []);
115
+ assert.equal(cfg.pollIntervalMs, GITHUB_DEFAULT_POLL_INTERVAL_MS);
116
+ assert.equal(cfg.includeDiscussions, false);
117
+ });
118
+
119
+ test("validateGitHubConfig rejects non-object input", () => {
120
+ assert.throws(() => validateGitHubConfig(null), /must be an object/);
121
+ assert.throws(() => validateGitHubConfig([]), /must be an object/);
122
+ assert.throws(() => validateGitHubConfig("nope"), /must be an object/);
123
+ });
124
+
125
+ test("validateGitHubConfig rejects missing or empty token", () => {
126
+ assert.throws(() => validateGitHubConfig({ userLogin: SYNTHETIC_LOGIN }), /token must be a string/);
127
+ assert.throws(
128
+ () => validateGitHubConfig({ token: "", userLogin: SYNTHETIC_LOGIN }),
129
+ /token must be non-empty/,
130
+ );
131
+ assert.throws(
132
+ () => validateGitHubConfig({ token: " ", userLogin: SYNTHETIC_LOGIN }),
133
+ /token must be non-empty/,
134
+ );
135
+ });
136
+
137
+ test("validateGitHubConfig rejects missing or empty userLogin", () => {
138
+ assert.throws(
139
+ () => validateGitHubConfig({ token: SYNTHETIC_TOKEN }),
140
+ /userLogin must be a string/,
141
+ );
142
+ assert.throws(
143
+ () => validateGitHubConfig({ token: SYNTHETIC_TOKEN, userLogin: "" }),
144
+ /userLogin must be non-empty/,
145
+ );
146
+ });
147
+
148
+ test("validateGitHubConfig rejects malformed pollIntervalMs", () => {
149
+ assert.throws(
150
+ () =>
151
+ validateGitHubConfig({ token: SYNTHETIC_TOKEN, userLogin: SYNTHETIC_LOGIN, pollIntervalMs: "300000" }),
152
+ /pollIntervalMs/,
153
+ );
154
+ assert.throws(
155
+ () =>
156
+ validateGitHubConfig({ token: SYNTHETIC_TOKEN, userLogin: SYNTHETIC_LOGIN, pollIntervalMs: 50 }),
157
+ /≥1000/,
158
+ );
159
+ assert.throws(
160
+ () =>
161
+ validateGitHubConfig({
162
+ token: SYNTHETIC_TOKEN,
163
+ userLogin: SYNTHETIC_LOGIN,
164
+ pollIntervalMs: 25 * 60 * 60 * 1000,
165
+ }),
166
+ /≤/,
167
+ );
168
+ assert.throws(
169
+ () =>
170
+ validateGitHubConfig({
171
+ token: SYNTHETIC_TOKEN,
172
+ userLogin: SYNTHETIC_LOGIN,
173
+ pollIntervalMs: 3000.5,
174
+ }),
175
+ /integer/,
176
+ );
177
+ });
178
+
179
+ test("validateGitHubConfig accepts valid repos in owner/repo format", () => {
180
+ const cfg = validateGitHubConfig({
181
+ token: SYNTHETIC_TOKEN,
182
+ userLogin: SYNTHETIC_LOGIN,
183
+ repos: [REPO_A, REPO_B],
184
+ });
185
+ assert.deepEqual([...cfg.repos], [REPO_A, REPO_B]);
186
+ });
187
+
188
+ test("validateGitHubConfig rejects malformed repo slugs", () => {
189
+ assert.throws(
190
+ () =>
191
+ validateGitHubConfig({
192
+ token: SYNTHETIC_TOKEN,
193
+ userLogin: SYNTHETIC_LOGIN,
194
+ repos: ["no-slash"],
195
+ }),
196
+ /owner\/repo/,
197
+ );
198
+ assert.throws(
199
+ () =>
200
+ validateGitHubConfig({
201
+ token: SYNTHETIC_TOKEN,
202
+ userLogin: SYNTHETIC_LOGIN,
203
+ repos: ["../../../etc/passwd"],
204
+ }),
205
+ /owner\/repo/,
206
+ );
207
+ assert.throws(
208
+ () =>
209
+ validateGitHubConfig({
210
+ token: SYNTHETIC_TOKEN,
211
+ userLogin: SYNTHETIC_LOGIN,
212
+ repos: [42 as unknown as string],
213
+ }),
214
+ /repos entries must be strings/,
215
+ );
216
+ });
217
+
218
+ test("validateGitHubConfig deduplicates repos", () => {
219
+ const cfg = validateGitHubConfig({
220
+ token: SYNTHETIC_TOKEN,
221
+ userLogin: SYNTHETIC_LOGIN,
222
+ repos: [REPO_A, REPO_A, REPO_B],
223
+ });
224
+ assert.deepEqual([...cfg.repos], [REPO_A, REPO_B]);
225
+ });
226
+
227
+ test("validateGitHubConfig rejects non-boolean includeDiscussions", () => {
228
+ assert.throws(
229
+ () =>
230
+ validateGitHubConfig({
231
+ token: SYNTHETIC_TOKEN,
232
+ userLogin: SYNTHETIC_LOGIN,
233
+ includeDiscussions: "yes" as unknown as boolean,
234
+ }),
235
+ /includeDiscussions must be a boolean/,
236
+ );
237
+ });
238
+
239
+ test("validateGitHubConfig accepts includeDiscussions: true", () => {
240
+ const cfg = validateGitHubConfig({
241
+ token: SYNTHETIC_TOKEN,
242
+ userLogin: SYNTHETIC_LOGIN,
243
+ includeDiscussions: true,
244
+ });
245
+ assert.equal(cfg.includeDiscussions, true);
246
+ });
247
+
248
+ // ---------------------------------------------------------------------------
249
+ // Connector identity
250
+ // ---------------------------------------------------------------------------
251
+
252
+ test("createGitHubConnector exposes the documented id and display name", () => {
253
+ const connector = createGitHubConnector({ fetchFn: emptyFetch() });
254
+ assert.equal(connector.id, GITHUB_CONNECTOR_ID);
255
+ assert.equal(connector.id, "github");
256
+ assert.equal(connector.displayName, "GitHub");
257
+ });
258
+
259
+ // ---------------------------------------------------------------------------
260
+ // No-op when repos is empty
261
+ // ---------------------------------------------------------------------------
262
+
263
+ test("syncIncremental is a no-op when repos is empty", async () => {
264
+ let fetchCalled = false;
265
+ const fetchFn: GitHubFetchFn = async () => {
266
+ fetchCalled = true;
267
+ throw new Error("should not be called");
268
+ };
269
+ const connector = createGitHubConnector({ fetchFn });
270
+ const config = connector.validateConfig({ token: SYNTHETIC_TOKEN, userLogin: SYNTHETIC_LOGIN });
271
+
272
+ const r1 = (await connector.syncIncremental({ cursor: null, config })) as GitHubSyncResult;
273
+ assert.deepEqual(r1.newDocs, []);
274
+ assert.equal(r1.nextCursor.kind, GITHUB_CURSOR_KIND);
275
+ assert.equal(fetchCalled, false);
276
+
277
+ const r2 = (await connector.syncIncremental({
278
+ cursor: r1.nextCursor,
279
+ config,
280
+ })) as GitHubSyncResult;
281
+ assert.deepEqual(r2.newDocs, []);
282
+ assert.equal(fetchCalled, false);
283
+ });
284
+
285
+ // ---------------------------------------------------------------------------
286
+ // First-sync bootstrap
287
+ // ---------------------------------------------------------------------------
288
+
289
+ test("first sync (cursor=null) seeds watermark and returns no docs", async () => {
290
+ const comment = makeComment(1, SYNTHETIC_LOGIN, "Hello", "2026-04-25T10:00:00.000Z");
291
+
292
+ const fetchFn = makeFetch([
293
+ {
294
+ // issue comments seed
295
+ match: (url) => url.includes("/issues/comments"),
296
+ respond: () => ({ status: 200, data: [comment] }),
297
+ },
298
+ {
299
+ // PR review comments seed
300
+ match: (url) => url.includes("/pulls/comments"),
301
+ respond: () => ({ status: 200, data: [] }),
302
+ },
303
+ ]);
304
+
305
+ const connector = createGitHubConnector({ fetchFn });
306
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
307
+
308
+ const result = (await connector.syncIncremental({ cursor: null, config })) as GitHubSyncResult;
309
+ assert.deepEqual(result.newDocs, []);
310
+ assert.equal(result.nextCursor.kind, GITHUB_CURSOR_KIND);
311
+
312
+ // The cursor must record the watermark from the seeded comment.
313
+ const payload = JSON.parse(result.nextCursor.value) as { watermarks: Record<string, string> };
314
+ assert.equal(
315
+ payload.watermarks[`${REPO_A}/issue-comment`],
316
+ "2026-04-25T10:00:00.000Z",
317
+ );
318
+ });
319
+
320
+ test("first sync with empty API responses seeds empty cursor", async () => {
321
+ const connector = createGitHubConnector({ fetchFn: emptyFetch() });
322
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
323
+
324
+ const result = await connector.syncIncremental({ cursor: null, config });
325
+ assert.deepEqual(result.newDocs, []);
326
+ assert.equal(result.nextCursor.kind, GITHUB_CURSOR_KIND);
327
+ });
328
+
329
+ // ---------------------------------------------------------------------------
330
+ // Incremental sync: basic happy path
331
+ // ---------------------------------------------------------------------------
332
+
333
+ test("incremental sync emits ConnectorDocument for matching issue comments", async () => {
334
+ const comment = makeComment(
335
+ 42,
336
+ SYNTHETIC_LOGIN,
337
+ "This is my note",
338
+ "2026-04-26T09:00:00.000Z",
339
+ `https://github.com/${REPO_A}/issues/10#issuecomment-42`,
340
+ );
341
+
342
+ const fetchFn = makeFetch([
343
+ {
344
+ match: (url) => url.includes("/issues/comments"),
345
+ respond: () => ({ status: 200, data: [comment] }),
346
+ },
347
+ {
348
+ match: (url) => url.includes("/pulls/comments"),
349
+ respond: () => ({ status: 200, data: [] }),
350
+ },
351
+ ]);
352
+
353
+ const connector = createGitHubConnector({ fetchFn });
354
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
355
+ const cursor = makeGitHubCursor({
356
+ [`${REPO_A}/issue-comment`]: "2026-04-25T00:00:00.000Z",
357
+ });
358
+
359
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
360
+
361
+ assert.equal(result.newDocs.length, 1);
362
+ const doc = result.newDocs[0];
363
+ assert.equal(doc.source.connector, GITHUB_CONNECTOR_ID);
364
+ assert.equal(doc.source.externalId, `${REPO_A}/issue-comment/42`);
365
+ assert.equal(doc.source.externalRevision, "2026-04-26T09:00:00.000Z");
366
+ assert.equal(doc.source.externalUrl, `https://github.com/${REPO_A}/issues/10#issuecomment-42`);
367
+ assert.equal(doc.content, "This is my note");
368
+ assert.ok(doc.title?.includes("Issue comment"));
369
+ assert.ok(doc.title?.includes(REPO_A));
370
+ });
371
+
372
+ test("incremental sync emits ConnectorDocument for matching PR review comments", async () => {
373
+ const comment = makeComment(99, SYNTHETIC_LOGIN, "PR note here", "2026-04-26T10:00:00.000Z");
374
+
375
+ const fetchFn = makeFetch([
376
+ {
377
+ match: (url) => url.includes("/issues/comments"),
378
+ respond: () => ({ status: 200, data: [] }),
379
+ },
380
+ {
381
+ match: (url) => url.includes("/pulls/comments"),
382
+ respond: () => ({ status: 200, data: [comment] }),
383
+ },
384
+ ]);
385
+
386
+ const connector = createGitHubConnector({ fetchFn });
387
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
388
+ const cursor = makeGitHubCursor({});
389
+
390
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
391
+
392
+ assert.equal(result.newDocs.length, 1);
393
+ const doc = result.newDocs[0];
394
+ assert.equal(doc.source.externalId, `${REPO_A}/pr-review-comment/99`);
395
+ assert.ok(doc.title?.includes("PR review comment"));
396
+ });
397
+
398
+ // ---------------------------------------------------------------------------
399
+ // Author filtering
400
+ // ---------------------------------------------------------------------------
401
+
402
+ test("incremental sync skips comments authored by a different user", async () => {
403
+ const myComment = makeComment(1, SYNTHETIC_LOGIN, "Mine", "2026-04-26T09:00:00.000Z");
404
+ const otherComment = makeComment(2, "other-user", "Not mine", "2026-04-26T09:01:00.000Z");
405
+
406
+ const fetchFn = makeFetch([
407
+ {
408
+ match: (url) => url.includes("/issues/comments"),
409
+ respond: () => ({ status: 200, data: [myComment, otherComment] }),
410
+ },
411
+ {
412
+ match: (url) => url.includes("/pulls/comments"),
413
+ respond: () => ({ status: 200, data: [] }),
414
+ },
415
+ ]);
416
+
417
+ const connector = createGitHubConnector({ fetchFn });
418
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
419
+ const cursor = makeGitHubCursor({});
420
+
421
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
422
+
423
+ assert.equal(result.newDocs.length, 1);
424
+ assert.equal(result.newDocs[0].source.externalId, `${REPO_A}/issue-comment/1`);
425
+ assert.equal(result.skippedOtherAuthor, 1);
426
+ });
427
+
428
+ // ---------------------------------------------------------------------------
429
+ // Empty / too-large bodies
430
+ // ---------------------------------------------------------------------------
431
+
432
+ test("incremental sync skips comments with empty body", async () => {
433
+ const emptyComment = makeComment(5, SYNTHETIC_LOGIN, "", "2026-04-26T09:00:00.000Z");
434
+ const whitespaceComment = makeComment(6, SYNTHETIC_LOGIN, " \n\t ", "2026-04-26T09:01:00.000Z");
435
+
436
+ const fetchFn = makeFetch([
437
+ {
438
+ match: (url) => url.includes("/issues/comments"),
439
+ respond: () => ({ status: 200, data: [emptyComment, whitespaceComment] }),
440
+ },
441
+ {
442
+ match: (url) => url.includes("/pulls/comments"),
443
+ respond: () => ({ status: 200, data: [] }),
444
+ },
445
+ ]);
446
+
447
+ const connector = createGitHubConnector({ fetchFn });
448
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
449
+ const cursor = makeGitHubCursor({});
450
+
451
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
452
+ assert.deepEqual(result.newDocs, []);
453
+ assert.equal(result.skippedEmpty, 2);
454
+ });
455
+
456
+ // ---------------------------------------------------------------------------
457
+ // Watermark advancement
458
+ // ---------------------------------------------------------------------------
459
+
460
+ test("incremental sync advances watermark after importing comments", async () => {
461
+ const c1 = makeComment(10, SYNTHETIC_LOGIN, "first", "2026-04-26T09:00:00.000Z");
462
+ const c2 = makeComment(11, SYNTHETIC_LOGIN, "second", "2026-04-26T10:00:00.000Z");
463
+
464
+ const fetchFn = makeFetch([
465
+ {
466
+ match: (url) => url.includes("/issues/comments"),
467
+ respond: () => ({ status: 200, data: [c1, c2] }),
468
+ },
469
+ {
470
+ match: (url) => url.includes("/pulls/comments"),
471
+ respond: () => ({ status: 200, data: [] }),
472
+ },
473
+ ]);
474
+
475
+ const connector = createGitHubConnector({ fetchFn });
476
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
477
+ const cursor = makeGitHubCursor({
478
+ [`${REPO_A}/issue-comment`]: "2026-04-25T00:00:00.000Z",
479
+ });
480
+
481
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
482
+ assert.equal(result.newDocs.length, 2);
483
+
484
+ const payload = JSON.parse(result.nextCursor.value) as { watermarks: Record<string, string> };
485
+ // Watermark must advance to the latest comment's updated_at.
486
+ assert.equal(payload.watermarks[`${REPO_A}/issue-comment`], "2026-04-26T10:00:00.000Z");
487
+ });
488
+
489
+ test("incremental sync skips items strictly before the watermark", async () => {
490
+ // Only comments whose updated_at is STRICTLY before the watermark are
491
+ // dropped by the filter. A comment AT the watermark second passes through
492
+ // to the seenIds check (and, if not in seenIds, is ingested). A comment
493
+ // one second after the watermark is always ingested.
494
+ //
495
+ // "beforeComment" has a timestamp 1 second before the watermark → skipped.
496
+ // "atComment" is AT the watermark second and NOT in seenIds → ingested.
497
+ // "afterComment" is after the watermark → ingested.
498
+ const watermark = "2026-04-25T00:00:01.000Z";
499
+ const beforeComment = makeComment(1, SYNTHETIC_LOGIN, "before", "2026-04-25T00:00:00.000Z");
500
+ const atComment = makeComment(2, SYNTHETIC_LOGIN, "at watermark", watermark);
501
+ const afterComment = makeComment(3, SYNTHETIC_LOGIN, "after", "2026-04-25T00:00:02.000Z");
502
+
503
+ const fetchFn = makeFetch([
504
+ {
505
+ match: (url) => url.includes("/issues/comments"),
506
+ respond: () => ({ status: 200, data: [beforeComment, atComment, afterComment] }),
507
+ },
508
+ {
509
+ match: (url) => url.includes("/pulls/comments"),
510
+ respond: () => ({ status: 200, data: [] }),
511
+ },
512
+ ]);
513
+
514
+ const connector = createGitHubConnector({ fetchFn });
515
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
516
+ // Cursor watermark at exactly the "at" second; seenIds is empty.
517
+ const cursor: import("./framework.js").ConnectorCursor = {
518
+ kind: GITHUB_CURSOR_KIND,
519
+ value: JSON.stringify({
520
+ watermarks: { [`${REPO_A}/issue-comment`]: watermark },
521
+ seenIds: {},
522
+ }),
523
+ updatedAt: watermark,
524
+ };
525
+
526
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
527
+ // beforeComment is strictly before the watermark → skipped.
528
+ // atComment is AT the watermark and not in seenIds → ingested.
529
+ // afterComment is after the watermark → ingested.
530
+ assert.equal(result.newDocs.length, 2);
531
+ const ids = result.newDocs.map((d) => d.source.externalId);
532
+ assert.ok(ids.includes(`${REPO_A}/issue-comment/2`), "atComment must be ingested");
533
+ assert.ok(ids.includes(`${REPO_A}/issue-comment/3`), "afterComment must be ingested");
534
+ });
535
+
536
+ // ---------------------------------------------------------------------------
537
+ // Multiple repos
538
+ // ---------------------------------------------------------------------------
539
+
540
+ test("incremental sync handles multiple repos independently", async () => {
541
+ const commentA = makeComment(1, SYNTHETIC_LOGIN, "In A", "2026-04-26T09:00:00.000Z");
542
+ const commentB = makeComment(2, SYNTHETIC_LOGIN, "In B", "2026-04-26T09:00:00.000Z");
543
+
544
+ const fetchFn = makeFetch([
545
+ {
546
+ match: (url) => url.includes(`${REPO_A}/issues/comments`),
547
+ respond: () => ({ status: 200, data: [commentA] }),
548
+ },
549
+ {
550
+ match: (url) => url.includes(`${REPO_B}/issues/comments`),
551
+ respond: () => ({ status: 200, data: [commentB] }),
552
+ },
553
+ {
554
+ match: (url) => url.includes("/pulls/comments"),
555
+ respond: () => ({ status: 200, data: [] }),
556
+ },
557
+ ]);
558
+
559
+ const connector = createGitHubConnector({ fetchFn });
560
+ const config = connector.validateConfig({
561
+ token: SYNTHETIC_TOKEN,
562
+ userLogin: SYNTHETIC_LOGIN,
563
+ repos: [REPO_A, REPO_B],
564
+ });
565
+ const cursor = makeGitHubCursor({});
566
+
567
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
568
+ assert.equal(result.newDocs.length, 2);
569
+ const ids = result.newDocs.map((d) => d.source.externalId).sort();
570
+ assert.deepEqual(ids, [
571
+ `${REPO_A}/issue-comment/1`,
572
+ `${REPO_B}/issue-comment/2`,
573
+ ].sort());
574
+ });
575
+
576
+ // ---------------------------------------------------------------------------
577
+ // Discussion comments (opt-in)
578
+ // ---------------------------------------------------------------------------
579
+
580
+ test("discussion comments are not fetched unless includeDiscussions is true", async () => {
581
+ let discussionFetched = false;
582
+ const fetchFn = makeFetch([
583
+ {
584
+ match: (url) => url.includes("/discussions"),
585
+ respond: () => {
586
+ discussionFetched = true;
587
+ return { status: 200, data: [] };
588
+ },
589
+ },
590
+ {
591
+ match: () => true,
592
+ respond: () => ({ status: 200, data: [] }),
593
+ },
594
+ ]);
595
+
596
+ const connector = createGitHubConnector({ fetchFn });
597
+ const config = connector.validateConfig({
598
+ ...SYNTHETIC_CONFIG,
599
+ includeDiscussions: false,
600
+ });
601
+ const cursor = makeGitHubCursor({});
602
+
603
+ await connector.syncIncremental({ cursor, config });
604
+ assert.equal(discussionFetched, false);
605
+ });
606
+
607
+ test("discussion comments are fetched when includeDiscussions is true", async () => {
608
+ let discussionFetched = false;
609
+ const fetchFn = makeFetch([
610
+ {
611
+ match: (url) => url.includes("/discussions"),
612
+ respond: () => {
613
+ discussionFetched = true;
614
+ return { status: 200, data: [] };
615
+ },
616
+ },
617
+ {
618
+ match: () => true,
619
+ respond: () => ({ status: 200, data: [] }),
620
+ },
621
+ ]);
622
+
623
+ const connector = createGitHubConnector({ fetchFn });
624
+ const config = connector.validateConfig({
625
+ ...SYNTHETIC_CONFIG,
626
+ includeDiscussions: true,
627
+ });
628
+ const cursor = makeGitHubCursor({});
629
+
630
+ await connector.syncIncremental({ cursor, config });
631
+ assert.equal(discussionFetched, true);
632
+ });
633
+
634
+ // ---------------------------------------------------------------------------
635
+ // Error classification
636
+ // ---------------------------------------------------------------------------
637
+
638
+ test("isTransientGitHubError classifies common error shapes", () => {
639
+ // Terminal — skip-and-continue.
640
+ assert.equal(isTransientGitHubError({ githubStatus: 404 }), false);
641
+ assert.equal(isTransientGitHubError({ githubStatus: 403 }), false);
642
+ assert.equal(isTransientGitHubError({ githubStatus: 400 }), false);
643
+ assert.equal(isTransientGitHubError({ status: 410 }), false);
644
+ // Transient — re-throw.
645
+ assert.equal(isTransientGitHubError({ githubStatus: 429 }), true);
646
+ assert.equal(isTransientGitHubError({ githubStatus: 500 }), true);
647
+ assert.equal(isTransientGitHubError({ githubStatus: 503 }), true);
648
+ assert.equal(isTransientGitHubError({ status: 504 }), true);
649
+ // Network errors.
650
+ assert.equal(isTransientGitHubError({ code: "ECONNRESET" }), true);
651
+ assert.equal(isTransientGitHubError({ code: "ETIMEDOUT" }), true);
652
+ assert.equal(isTransientGitHubError({ code: "ENOTFOUND" }), true);
653
+ assert.equal(isTransientGitHubError({ code: "EAI_AGAIN" }), true);
654
+ // AbortError.
655
+ assert.equal(isTransientGitHubError({ name: "AbortError" }), true);
656
+ // Bare Error with no metadata — conservatively transient.
657
+ assert.equal(isTransientGitHubError(new Error("unknown")), true);
658
+ // Non-objects.
659
+ assert.equal(isTransientGitHubError(null), false);
660
+ assert.equal(isTransientGitHubError(undefined), false);
661
+ assert.equal(isTransientGitHubError("oops"), false);
662
+ });
663
+
664
+ // ---------------------------------------------------------------------------
665
+ // HTTP error handling
666
+ // ---------------------------------------------------------------------------
667
+
668
+ test("a 429 on issue comments re-throws (transient) and cursor does NOT advance", async () => {
669
+ const fetchFn = makeFetch([
670
+ {
671
+ match: (url) => url.includes("/issues/comments"),
672
+ respond: () => ({
673
+ status: 429,
674
+ data: { message: "API rate limit exceeded" },
675
+ }),
676
+ },
677
+ ]);
678
+
679
+ const connector = createGitHubConnector({ fetchFn });
680
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
681
+ const cursor = makeGitHubCursor({
682
+ [`${REPO_A}/issue-comment`]: "2026-04-25T00:00:00.000Z",
683
+ });
684
+
685
+ await assert.rejects(
686
+ connector.syncIncremental({ cursor, config }),
687
+ /rate limit/i,
688
+ );
689
+ });
690
+
691
+ test("a 503 on issue comments re-throws (transient)", async () => {
692
+ const fetchFn = makeFetch([
693
+ {
694
+ match: (url) => url.includes("/issues/comments"),
695
+ respond: () => ({
696
+ status: 503,
697
+ data: { message: "Service Unavailable" },
698
+ }),
699
+ },
700
+ ]);
701
+
702
+ const connector = createGitHubConnector({ fetchFn });
703
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
704
+ const cursor = makeGitHubCursor({});
705
+
706
+ await assert.rejects(
707
+ connector.syncIncremental({ cursor, config }),
708
+ /503/,
709
+ );
710
+ });
711
+
712
+ test("a 404 on issue comments is terminal (skip repo resource, continue)", async () => {
713
+ // Issue comments returns 404 → skipped.
714
+ // PR review comments returns a valid comment → should still be imported.
715
+ const prComment = makeComment(77, SYNTHETIC_LOGIN, "PR note", "2026-04-26T09:00:00.000Z");
716
+
717
+ const fetchFn = makeFetch([
718
+ {
719
+ match: (url) => url.includes("/issues/comments"),
720
+ respond: () => ({
721
+ status: 404,
722
+ data: { message: "Not Found" },
723
+ }),
724
+ },
725
+ {
726
+ match: (url) => url.includes("/pulls/comments"),
727
+ respond: () => ({ status: 200, data: [prComment] }),
728
+ },
729
+ ]);
730
+
731
+ const connector = createGitHubConnector({ fetchFn });
732
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
733
+ const cursor = makeGitHubCursor({});
734
+
735
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
736
+ // The 404 should be swallowed (terminal), and the PR comment should be imported.
737
+ assert.equal(result.newDocs.length, 1);
738
+ assert.equal(result.newDocs[0].source.externalId, `${REPO_A}/pr-review-comment/77`);
739
+ });
740
+
741
+ test("a 403 on issue comments is terminal (skip, continue to PR comments)", async () => {
742
+ const prComment = makeComment(88, SYNTHETIC_LOGIN, "Another PR note", "2026-04-26T09:00:00.000Z");
743
+
744
+ const fetchFn = makeFetch([
745
+ {
746
+ match: (url) => url.includes("/issues/comments"),
747
+ respond: () => ({
748
+ status: 403,
749
+ data: { message: "Forbidden" },
750
+ }),
751
+ },
752
+ {
753
+ match: (url) => url.includes("/pulls/comments"),
754
+ respond: () => ({ status: 200, data: [prComment] }),
755
+ },
756
+ ]);
757
+
758
+ const connector = createGitHubConnector({ fetchFn });
759
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
760
+ const cursor = makeGitHubCursor({});
761
+
762
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
763
+ assert.equal(result.newDocs.length, 1);
764
+ });
765
+
766
+ // ---------------------------------------------------------------------------
767
+ // AbortSignal
768
+ // ---------------------------------------------------------------------------
769
+
770
+ test("syncIncremental honors abortSignal", async () => {
771
+ const controller = new AbortController();
772
+ let callCount = 0;
773
+
774
+ const fetchFn: GitHubFetchFn = async () => {
775
+ callCount++;
776
+ if (callCount === 1) controller.abort();
777
+ return {
778
+ ok: true,
779
+ status: 200,
780
+ headers: { get: () => null },
781
+ json: async () => [],
782
+ };
783
+ };
784
+
785
+ const connector = createGitHubConnector({ fetchFn });
786
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
787
+ const cursor = makeGitHubCursor({});
788
+
789
+ await assert.rejects(
790
+ connector.syncIncremental({ cursor, config, abortSignal: controller.signal }),
791
+ /aborted/,
792
+ );
793
+ });
794
+
795
+ // ---------------------------------------------------------------------------
796
+ // Cursor validation
797
+ // ---------------------------------------------------------------------------
798
+
799
+ test("syncIncremental rejects a cursor of an unexpected kind", async () => {
800
+ const connector = createGitHubConnector({ fetchFn: emptyFetch() });
801
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
802
+ const badCursor: ConnectorCursor = {
803
+ kind: "wrong-kind",
804
+ value: "{}",
805
+ updatedAt: "2026-04-25T00:00:00.000Z",
806
+ };
807
+
808
+ await assert.rejects(
809
+ connector.syncIncremental({ cursor: badCursor, config }),
810
+ /unexpected cursor kind/,
811
+ );
812
+ });
813
+
814
+ test("syncIncremental rejects a cursor with invalid JSON", async () => {
815
+ const connector = createGitHubConnector({ fetchFn: emptyFetch() });
816
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
817
+ const badCursor: ConnectorCursor = {
818
+ kind: GITHUB_CURSOR_KIND,
819
+ value: "{ not valid json",
820
+ updatedAt: "2026-04-25T00:00:00.000Z",
821
+ };
822
+
823
+ await assert.rejects(
824
+ connector.syncIncremental({ cursor: badCursor, config }),
825
+ /not valid JSON/,
826
+ );
827
+ });
828
+
829
+ test("validateConfig is enforced again on every sync pass", async () => {
830
+ const connector = createGitHubConnector({ fetchFn: emptyFetch() });
831
+ const badConfig = { token: SYNTHETIC_TOKEN } as unknown as import("./framework.js").ConnectorConfig;
832
+ const cursor = makeGitHubCursor({});
833
+
834
+ await assert.rejects(
835
+ connector.syncIncremental({ cursor, config: badConfig }),
836
+ /userLogin/,
837
+ );
838
+ });
839
+
840
+ // ---------------------------------------------------------------------------
841
+ // Network-layer transient error
842
+ // ---------------------------------------------------------------------------
843
+
844
+ test("a network ECONNRESET on issue comments re-throws as transient", async () => {
845
+ const fetchFn: GitHubFetchFn = async () => {
846
+ throw Object.assign(new Error("socket hang up"), { code: "ECONNRESET" });
847
+ };
848
+
849
+ const connector = createGitHubConnector({ fetchFn });
850
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
851
+ const cursor = makeGitHubCursor({});
852
+
853
+ await assert.rejects(
854
+ connector.syncIncremental({ cursor, config }),
855
+ /socket hang up/,
856
+ );
857
+ });
858
+
859
+ // ---------------------------------------------------------------------------
860
+ // Non-matching author watermark advancement (CLAUDE.md gotcha #44 regression)
861
+ // ---------------------------------------------------------------------------
862
+
863
+ test("watermark advances for non-matching-author and empty comments so they aren't re-fetched", async () => {
864
+ // A comment from a different user. The watermark must still advance so we
865
+ // don't fetch the same item on every subsequent poll.
866
+ const otherComment = makeComment(200, "other-user", "Not mine", "2026-04-26T09:00:00.000Z");
867
+
868
+ const fetchFn = makeFetch([
869
+ {
870
+ match: (url) => url.includes("/issues/comments"),
871
+ respond: () => ({ status: 200, data: [otherComment] }),
872
+ },
873
+ {
874
+ match: (url) => url.includes("/pulls/comments"),
875
+ respond: () => ({ status: 200, data: [] }),
876
+ },
877
+ ]);
878
+
879
+ const connector = createGitHubConnector({ fetchFn });
880
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
881
+ const cursor = makeGitHubCursor({});
882
+
883
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
884
+ assert.deepEqual(result.newDocs, []);
885
+ assert.equal(result.skippedOtherAuthor, 1);
886
+
887
+ // The watermark must have advanced past the other-author comment so the
888
+ // next incremental pass skips it via the `since` filter.
889
+ const payload = JSON.parse(result.nextCursor.value) as { watermarks: Record<string, string> };
890
+ assert.equal(payload.watermarks[`${REPO_A}/issue-comment`], "2026-04-26T09:00:00.000Z");
891
+ });
892
+
893
+ // ---------------------------------------------------------------------------
894
+ // P1 fix: Same-timestamp dedup via seenIds (PRRT_kwDORJXyws59sfBq)
895
+ // ---------------------------------------------------------------------------
896
+
897
+ test("seenIds are stored in cursor for ingested comments at the watermark second", async () => {
898
+ // Two comments with the same second-level timestamp. Both are new (above watermark).
899
+ const c1 = makeComment(10, SYNTHETIC_LOGIN, "first comment", "2026-04-26T10:00:00.000Z");
900
+ const c2 = makeComment(11, SYNTHETIC_LOGIN, "second comment", "2026-04-26T10:00:00.500Z");
901
+
902
+ const fetchFn = makeFetch([
903
+ {
904
+ match: (url) => url.includes("/issues/comments"),
905
+ respond: () => ({ status: 200, data: [c1, c2] }),
906
+ },
907
+ {
908
+ match: (url) => url.includes("/pulls/comments"),
909
+ respond: () => ({ status: 200, data: [] }),
910
+ },
911
+ ]);
912
+
913
+ const connector = createGitHubConnector({ fetchFn });
914
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
915
+ const cursor = makeGitHubCursor({
916
+ [`${REPO_A}/issue-comment`]: "2026-04-26T09:00:00.000Z",
917
+ });
918
+
919
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
920
+ assert.equal(result.newDocs.length, 2);
921
+
922
+ const payload = JSON.parse(result.nextCursor.value) as {
923
+ watermarks: Record<string, string>;
924
+ seenIds: Record<string, string>;
925
+ };
926
+ // seenIds must contain both ingested comment ids.
927
+ assert.ok(
928
+ `${REPO_A}/issue-comment/10` in payload.seenIds,
929
+ "seenIds must include comment 10",
930
+ );
931
+ assert.ok(
932
+ `${REPO_A}/issue-comment/11` in payload.seenIds,
933
+ "seenIds must include comment 11",
934
+ );
935
+ });
936
+
937
+ test("seenIds prevent re-importing same-second comments on the next poll", async () => {
938
+ // Scenario: c1 was ingested on the previous pass and is recorded in seenIds.
939
+ // On this poll GitHub re-returns it (inclusive `since=` at the watermark
940
+ // second). It must be skipped without emitting a new document.
941
+ const ts = "2026-04-26T10:00:00.000Z";
942
+ const c1 = makeComment(10, SYNTHETIC_LOGIN, "already imported", ts);
943
+ const c2 = makeComment(12, SYNTHETIC_LOGIN, "new this poll", "2026-04-26T10:00:01.000Z");
944
+
945
+ const fetchFn = makeFetch([
946
+ {
947
+ match: (url) => url.includes("/issues/comments"),
948
+ respond: () => ({ status: 200, data: [c1, c2] }),
949
+ },
950
+ {
951
+ match: (url) => url.includes("/pulls/comments"),
952
+ respond: () => ({ status: 200, data: [] }),
953
+ },
954
+ ]);
955
+
956
+ const connector = createGitHubConnector({ fetchFn });
957
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
958
+ // Cursor encodes the watermark at c1's timestamp AND c1 already in seenIds.
959
+ const cursor: import("./framework.js").ConnectorCursor = {
960
+ kind: GITHUB_CURSOR_KIND,
961
+ value: JSON.stringify({
962
+ watermarks: { [`${REPO_A}/issue-comment`]: ts },
963
+ seenIds: { [`${REPO_A}/issue-comment/10`]: ts },
964
+ }),
965
+ updatedAt: "2026-04-26T10:00:00.000Z",
966
+ };
967
+
968
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
969
+ // c1 must be skipped (in seenIds); only c2 should be imported.
970
+ assert.equal(result.newDocs.length, 1);
971
+ assert.equal(result.newDocs[0].source.externalId, `${REPO_A}/issue-comment/12`);
972
+ });
973
+
974
+ test("seenIds are cleared when the watermark advances past a second boundary", async () => {
975
+ // Previous cursor has seenIds entries at the old second.
976
+ // After ingesting c2 which is in a new second, seenIds must be cleared.
977
+ const oldTs = "2026-04-26T10:00:00.000Z";
978
+ const newTs = "2026-04-26T10:00:01.000Z";
979
+ const c1Old = makeComment(10, SYNTHETIC_LOGIN, "old second item", oldTs);
980
+ const c2New = makeComment(20, SYNTHETIC_LOGIN, "new second item", newTs);
981
+
982
+ const fetchFn = makeFetch([
983
+ {
984
+ match: (url) => url.includes("/issues/comments"),
985
+ respond: () => ({ status: 200, data: [c1Old, c2New] }),
986
+ },
987
+ {
988
+ match: (url) => url.includes("/pulls/comments"),
989
+ respond: () => ({ status: 200, data: [] }),
990
+ },
991
+ ]);
992
+
993
+ const connector = createGitHubConnector({ fetchFn });
994
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
995
+ // Cursor: watermark is at oldTs, seenIds contains c1Old's id.
996
+ const cursor: import("./framework.js").ConnectorCursor = {
997
+ kind: GITHUB_CURSOR_KIND,
998
+ value: JSON.stringify({
999
+ watermarks: { [`${REPO_A}/issue-comment`]: oldTs },
1000
+ seenIds: { [`${REPO_A}/issue-comment/10`]: oldTs },
1001
+ }),
1002
+ updatedAt: oldTs,
1003
+ };
1004
+
1005
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
1006
+ // c1Old is in seenIds → skipped. c2New (above watermark) → imported.
1007
+ assert.equal(result.newDocs.length, 1);
1008
+ assert.equal(result.newDocs[0].source.externalId, `${REPO_A}/issue-comment/20`);
1009
+
1010
+ const payload = JSON.parse(result.nextCursor.value) as {
1011
+ watermarks: Record<string, string>;
1012
+ seenIds: Record<string, string>;
1013
+ };
1014
+ // Watermark must have advanced to the new second.
1015
+ assert.equal(payload.watermarks[`${REPO_A}/issue-comment`], newTs);
1016
+ // seenIds for c1Old must be cleared (watermark crossed the second boundary).
1017
+ assert.ok(
1018
+ !(`${REPO_A}/issue-comment/10` in payload.seenIds),
1019
+ "stale seenId from old second must be cleared",
1020
+ );
1021
+ // c2New must be in the fresh seenIds.
1022
+ assert.ok(
1023
+ `${REPO_A}/issue-comment/20` in payload.seenIds,
1024
+ "new-second comment must be in seenIds",
1025
+ );
1026
+ });
1027
+
1028
+ // ---------------------------------------------------------------------------
1029
+ // P1 fix: Skip-aware budget — skipped records don't consume the cap
1030
+ // (PRRT_kwDORJXyws59sfBs)
1031
+ // ---------------------------------------------------------------------------
1032
+
1033
+ test("skipped (wrong-author) records do not consume the per-pass budget", async () => {
1034
+ // Build MAX_ITEMS_PER_PASS wrong-author comments followed by one valid one.
1035
+ // The budget should NOT be exhausted by the skipped ones, so the valid
1036
+ // comment at the end must still be ingested.
1037
+ const MAX = 200; // matches MAX_ITEMS_PER_PASS constant
1038
+ const skippedComments = Array.from({ length: MAX }, (_, i) =>
1039
+ makeComment(1000 + i, "other-user", `not mine ${i}`, `2026-04-26T09:00:${String(i).padStart(2, "0")}.000Z`),
1040
+ );
1041
+ const validComment = makeComment(9999, SYNTHETIC_LOGIN, "mine", "2026-04-26T09:05:00.000Z");
1042
+
1043
+ // All comments returned on first page (we return MAX+1 items so pagination
1044
+ // doesn't trigger — but since GITHUB_PAGE_SIZE=100 we need to simulate
1045
+ // multiple pages). Simpler: just return one page with all items (>100),
1046
+ // but since the page-size check caps at 100 we'll use a single page of
1047
+ // exactly the right set. Instead use a simpler approach: return the skipped
1048
+ // comments as 2 pages of 100, then the valid comment on a "short" 3rd page.
1049
+ let callCount = 0;
1050
+ const issuePages: (typeof skippedComments)[] = [
1051
+ skippedComments.slice(0, 100),
1052
+ skippedComments.slice(100, 200),
1053
+ [validComment],
1054
+ ];
1055
+
1056
+ const fetchFn = makeFetch([
1057
+ {
1058
+ match: (url) => url.includes("/issues/comments"),
1059
+ respond: () => {
1060
+ const page = issuePages[callCount] ?? [];
1061
+ callCount++;
1062
+ return { status: 200, data: page };
1063
+ },
1064
+ },
1065
+ {
1066
+ match: (url) => url.includes("/pulls/comments"),
1067
+ respond: () => ({ status: 200, data: [] }),
1068
+ },
1069
+ ]);
1070
+
1071
+ const connector = createGitHubConnector({ fetchFn });
1072
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
1073
+ const cursor = makeGitHubCursor({});
1074
+
1075
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
1076
+
1077
+ // The valid comment must be imported despite all the skipped ones.
1078
+ assert.equal(
1079
+ result.newDocs.length,
1080
+ 1,
1081
+ "the valid comment must not be starved by budget-consuming skipped items",
1082
+ );
1083
+ assert.equal(result.newDocs[0].source.externalId, `${REPO_A}/issue-comment/9999`);
1084
+ assert.equal(result.skippedOtherAuthor, MAX);
1085
+ });
1086
+
1087
+ test("skipped (empty-body) records do not consume the per-pass budget", async () => {
1088
+ // 5 empty-body comments followed by 3 valid ones within a budget of 3.
1089
+ const emptyComments = Array.from({ length: 5 }, (_, i) =>
1090
+ makeComment(200 + i, SYNTHETIC_LOGIN, "", `2026-04-26T09:00:0${i}.000Z`),
1091
+ );
1092
+ const validComments = Array.from({ length: 3 }, (_, i) =>
1093
+ makeComment(300 + i, SYNTHETIC_LOGIN, `valid ${i}`, `2026-04-26T09:01:0${i}.000Z`),
1094
+ );
1095
+
1096
+ const fetchFn = makeFetch([
1097
+ {
1098
+ match: (url) => url.includes("/issues/comments"),
1099
+ respond: () => ({ status: 200, data: [...emptyComments, ...validComments] }),
1100
+ },
1101
+ {
1102
+ match: (url) => url.includes("/pulls/comments"),
1103
+ respond: () => ({ status: 200, data: [] }),
1104
+ },
1105
+ ]);
1106
+
1107
+ const connector = createGitHubConnector({ fetchFn });
1108
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
1109
+ const cursor = makeGitHubCursor({});
1110
+
1111
+ // Use a budget of 3. With the old (buggy) code, the 5 empty comments would
1112
+ // exhaust the budget before reaching the valid ones.
1113
+ // We can't set MAX_ITEMS_PER_PASS directly; instead verify that with the
1114
+ // default budget all 3 valid comments are imported.
1115
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
1116
+
1117
+ assert.equal(result.newDocs.length, 3, "all 3 valid comments must be imported");
1118
+ assert.equal(result.skippedEmpty, 5);
1119
+ });
1120
+
1121
+ // ---------------------------------------------------------------------------
1122
+ // Regression: strict watermark filter (<, not <=) + timestamp-gated seenIds
1123
+ // Fixes: Cursor High finding (watermark boundary), Codex P1 finding (seenIds).
1124
+ // ---------------------------------------------------------------------------
1125
+
1126
+ test("watermark uses strict < so boundary-second comments pass through to seenIds", async () => {
1127
+ // Scenario: The cursor watermark is set to T. On the next poll GitHub's
1128
+ // `since=T` filter re-returns any comment whose updated_at equals T
1129
+ // (GitHub's `since` parameter is inclusive). With the old `<=` filter these
1130
+ // were silently dropped before seenIds could distinguish them. This test
1131
+ // verifies the `<` fix: a comment AT exactly the watermark second that is
1132
+ // NOT in seenIds must be ingested.
1133
+ const ts = "2026-04-26T12:00:00.000Z";
1134
+ // commentAtTs is at the exact watermark second but was NOT ingested before.
1135
+ const commentAtTs = makeComment(42, SYNTHETIC_LOGIN, "exactly at watermark", ts);
1136
+
1137
+ const fetchFn = makeFetch([
1138
+ {
1139
+ match: (url) => url.includes("/issues/comments"),
1140
+ respond: () => ({ status: 200, data: [commentAtTs] }),
1141
+ },
1142
+ {
1143
+ match: (url) => url.includes("/pulls/comments"),
1144
+ respond: () => ({ status: 200, data: [] }),
1145
+ },
1146
+ ]);
1147
+
1148
+ const connector = createGitHubConnector({ fetchFn });
1149
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
1150
+ // Cursor watermark is AT ts; seenIds is empty (comment was NOT previously seen).
1151
+ const cursor: import("./framework.js").ConnectorCursor = {
1152
+ kind: GITHUB_CURSOR_KIND,
1153
+ value: JSON.stringify({
1154
+ watermarks: { [`${REPO_A}/issue-comment`]: ts },
1155
+ seenIds: {},
1156
+ }),
1157
+ updatedAt: ts,
1158
+ };
1159
+
1160
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
1161
+ // With `<` fix: commentAtTs is NOT before the watermark, NOT in seenIds →
1162
+ // must be ingested. With old `<=` it would have been silently dropped.
1163
+ assert.equal(
1164
+ result.newDocs.length,
1165
+ 1,
1166
+ "comment exactly at watermark second must be ingested when not in seenIds",
1167
+ );
1168
+ assert.equal(result.newDocs[0].source.externalId, `${REPO_A}/issue-comment/42`);
1169
+ });
1170
+
1171
+ test("seenIds check gates on (id + timestamp), not id alone", async () => {
1172
+ // Scenario: A comment was previously imported at ts1. It is then edited and
1173
+ // re-fetched at ts2 (same id, newer updated_at). With the old `!== undefined`
1174
+ // check the edited version would be silently dropped. With the new
1175
+ // `=== comment.updated_at` check only the exact (id, ts) pair is suppressed.
1176
+ const ts1 = "2026-04-26T13:00:00.000Z";
1177
+ const ts2 = "2026-04-26T13:00:01.000Z";
1178
+ // Same id as the previously-ingested comment, but updated_at has advanced.
1179
+ const editedComment = makeComment(77, SYNTHETIC_LOGIN, "edited body", ts2);
1180
+
1181
+ const fetchFn = makeFetch([
1182
+ {
1183
+ match: (url) => url.includes("/issues/comments"),
1184
+ respond: () => ({ status: 200, data: [editedComment] }),
1185
+ },
1186
+ {
1187
+ match: (url) => url.includes("/pulls/comments"),
1188
+ respond: () => ({ status: 200, data: [] }),
1189
+ },
1190
+ ]);
1191
+
1192
+ const connector = createGitHubConnector({ fetchFn });
1193
+ const config = connector.validateConfig({ ...SYNTHETIC_CONFIG });
1194
+ // Cursor records id 77 with ts1 in seenIds (the old ingested version).
1195
+ // Watermark is at ts1 so the edited comment (ts2 > ts1) is above it.
1196
+ const cursor: import("./framework.js").ConnectorCursor = {
1197
+ kind: GITHUB_CURSOR_KIND,
1198
+ value: JSON.stringify({
1199
+ watermarks: { [`${REPO_A}/issue-comment`]: ts1 },
1200
+ seenIds: { [`${REPO_A}/issue-comment/77`]: ts1 },
1201
+ }),
1202
+ updatedAt: ts1,
1203
+ };
1204
+
1205
+ const result = (await connector.syncIncremental({ cursor, config })) as GitHubSyncResult;
1206
+ // The edited comment (same id, newer ts) must be ingested — seenIds only
1207
+ // suppresses the (id, ts1) pair, not (id, ts2).
1208
+ assert.equal(
1209
+ result.newDocs.length,
1210
+ 1,
1211
+ "edited comment with newer updated_at must not be suppressed by seenIds",
1212
+ );
1213
+ assert.equal(result.newDocs[0].source.externalId, `${REPO_A}/issue-comment/77`);
1214
+ assert.ok(
1215
+ result.newDocs[0].content.includes("edited body"),
1216
+ "imported document must contain the new body",
1217
+ );
1218
+ });