@ncukondo/search-hub 0.12.0 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. package/dist/_virtual/_commonjsHelpers.js +30 -0
  2. package/dist/_virtual/_commonjsHelpers.js.map +1 -0
  3. package/dist/_virtual/aliases.js +5 -0
  4. package/dist/_virtual/aliases.js.map +1 -0
  5. package/dist/_virtual/attributes.js +5 -0
  6. package/dist/_virtual/attributes.js.map +1 -0
  7. package/dist/_virtual/back.js +5 -0
  8. package/dist/_virtual/back.js.map +1 -0
  9. package/dist/_virtual/comment.js +5 -0
  10. package/dist/_virtual/comment.js.map +1 -0
  11. package/dist/_virtual/compile.js +5 -0
  12. package/dist/_virtual/compile.js.map +1 -0
  13. package/dist/_virtual/compile2.js +5 -0
  14. package/dist/_virtual/compile2.js.map +1 -0
  15. package/dist/_virtual/decode-data-html.js +5 -0
  16. package/dist/_virtual/decode-data-html.js.map +1 -0
  17. package/dist/_virtual/decode-data-xml.js +5 -0
  18. package/dist/_virtual/decode-data-xml.js.map +1 -0
  19. package/dist/_virtual/decode.js +5 -0
  20. package/dist/_virtual/decode.js.map +1 -0
  21. package/dist/_virtual/decode_codepoint.js +5 -0
  22. package/dist/_virtual/decode_codepoint.js.map +1 -0
  23. package/dist/_virtual/encode-html.js +5 -0
  24. package/dist/_virtual/encode-html.js.map +1 -0
  25. package/dist/_virtual/encode.js +5 -0
  26. package/dist/_virtual/encode.js.map +1 -0
  27. package/dist/_virtual/escape.js +5 -0
  28. package/dist/_virtual/escape.js.map +1 -0
  29. package/dist/_virtual/feeds.js +5 -0
  30. package/dist/_virtual/feeds.js.map +1 -0
  31. package/dist/_virtual/filters.js +5 -0
  32. package/dist/_virtual/filters.js.map +1 -0
  33. package/dist/_virtual/foreignNames.js +5 -0
  34. package/dist/_virtual/foreignNames.js.map +1 -0
  35. package/dist/_virtual/general.js +5 -0
  36. package/dist/_virtual/general.js.map +1 -0
  37. package/dist/_virtual/he.js +5 -0
  38. package/dist/_virtual/he.js.map +1 -0
  39. package/dist/_virtual/helpers.js +5 -0
  40. package/dist/_virtual/helpers.js.map +1 -0
  41. package/dist/_virtual/html.js +5 -0
  42. package/dist/_virtual/html.js.map +1 -0
  43. package/dist/_virtual/index.js +6 -0
  44. package/dist/_virtual/index.js.map +1 -0
  45. package/dist/_virtual/index10.js +5 -0
  46. package/dist/_virtual/index10.js.map +1 -0
  47. package/dist/_virtual/index11.js +5 -0
  48. package/dist/_virtual/index11.js.map +1 -0
  49. package/dist/_virtual/index2.js +5 -0
  50. package/dist/_virtual/index2.js.map +1 -0
  51. package/dist/_virtual/index3.js +5 -0
  52. package/dist/_virtual/index3.js.map +1 -0
  53. package/dist/_virtual/index4.js +5 -0
  54. package/dist/_virtual/index4.js.map +1 -0
  55. package/dist/_virtual/index5.js +7 -0
  56. package/dist/_virtual/index5.js.map +1 -0
  57. package/dist/_virtual/index6.js +5 -0
  58. package/dist/_virtual/index6.js.map +1 -0
  59. package/dist/_virtual/index7.js +5 -0
  60. package/dist/_virtual/index7.js.map +1 -0
  61. package/dist/_virtual/index8.js +5 -0
  62. package/dist/_virtual/index8.js.map +1 -0
  63. package/dist/_virtual/index9.js +5 -0
  64. package/dist/_virtual/index9.js.map +1 -0
  65. package/dist/_virtual/legacy.js +5 -0
  66. package/dist/_virtual/legacy.js.map +1 -0
  67. package/dist/_virtual/manipulation.js +5 -0
  68. package/dist/_virtual/manipulation.js.map +1 -0
  69. package/dist/_virtual/matcher.js +5 -0
  70. package/dist/_virtual/matcher.js.map +1 -0
  71. package/dist/_virtual/node.js +5 -0
  72. package/dist/_virtual/node.js.map +1 -0
  73. package/dist/_virtual/node2.js +5 -0
  74. package/dist/_virtual/node2.js.map +1 -0
  75. package/dist/_virtual/parse.js +5 -0
  76. package/dist/_virtual/parse.js.map +1 -0
  77. package/dist/_virtual/parse2.js +5 -0
  78. package/dist/_virtual/parse2.js.map +1 -0
  79. package/dist/_virtual/pseudos.js +5 -0
  80. package/dist/_virtual/pseudos.js.map +1 -0
  81. package/dist/_virtual/querying.js +5 -0
  82. package/dist/_virtual/querying.js.map +1 -0
  83. package/dist/_virtual/sort.js +5 -0
  84. package/dist/_virtual/sort.js.map +1 -0
  85. package/dist/_virtual/stringify.js +5 -0
  86. package/dist/_virtual/stringify.js.map +1 -0
  87. package/dist/_virtual/subselects.js +5 -0
  88. package/dist/_virtual/subselects.js.map +1 -0
  89. package/dist/_virtual/text.js +5 -0
  90. package/dist/_virtual/text.js.map +1 -0
  91. package/dist/_virtual/traversal.js +5 -0
  92. package/dist/_virtual/traversal.js.map +1 -0
  93. package/dist/_virtual/type.js +5 -0
  94. package/dist/_virtual/type.js.map +1 -0
  95. package/dist/_virtual/valid.js +5 -0
  96. package/dist/_virtual/valid.js.map +1 -0
  97. package/dist/_virtual/void-tag.js +5 -0
  98. package/dist/_virtual/void-tag.js.map +1 -0
  99. package/dist/cli/commands/fulltext/attach.js +1 -1
  100. package/dist/cli/commands/fulltext/attach.js.map +1 -1
  101. package/dist/cli/commands/fulltext/check.d.ts +1 -2
  102. package/dist/cli/commands/fulltext/check.d.ts.map +1 -1
  103. package/dist/cli/commands/fulltext/check.js +4 -2
  104. package/dist/cli/commands/fulltext/check.js.map +1 -1
  105. package/dist/cli/commands/fulltext/convert.d.ts.map +1 -1
  106. package/dist/cli/commands/fulltext/convert.js +8 -8
  107. package/dist/cli/commands/fulltext/convert.js.map +1 -1
  108. package/dist/cli/commands/fulltext/fetch.d.ts.map +1 -1
  109. package/dist/cli/commands/fulltext/fetch.js +10 -6
  110. package/dist/cli/commands/fulltext/fetch.js.map +1 -1
  111. package/dist/cli/commands/fulltext/index.d.ts.map +1 -1
  112. package/dist/cli/commands/fulltext/index.js +2 -0
  113. package/dist/cli/commands/fulltext/index.js.map +1 -1
  114. package/dist/cli/commands/fulltext/init.d.ts.map +1 -1
  115. package/dist/cli/commands/fulltext/init.js +6 -5
  116. package/dist/cli/commands/fulltext/init.js.map +1 -1
  117. package/dist/cli/commands/fulltext/pending.d.ts +1 -1
  118. package/dist/cli/commands/fulltext/pending.d.ts.map +1 -1
  119. package/dist/cli/commands/fulltext/pending.js +4 -2
  120. package/dist/cli/commands/fulltext/pending.js.map +1 -1
  121. package/dist/cli/commands/fulltext/status.d.ts.map +1 -1
  122. package/dist/cli/commands/fulltext/status.js +4 -2
  123. package/dist/cli/commands/fulltext/status.js.map +1 -1
  124. package/dist/cli/commands/fulltext/sync.d.ts.map +1 -1
  125. package/dist/cli/commands/fulltext/sync.js +6 -2
  126. package/dist/cli/commands/fulltext/sync.js.map +1 -1
  127. package/dist/cli/commands/review/types.d.ts +1 -1
  128. package/dist/cli/commands/review/types.d.ts.map +1 -1
  129. package/dist/cli/commands/review/types.js.map +1 -1
  130. package/dist/cli/index.d.ts.map +1 -1
  131. package/dist/cli/index.js +7 -0
  132. package/dist/cli/index.js.map +1 -1
  133. package/dist/config/schema.d.ts +2 -0
  134. package/dist/config/schema.d.ts.map +1 -1
  135. package/dist/config/schema.js +6 -0
  136. package/dist/config/schema.js.map +1 -1
  137. package/dist/{fulltext → integration}/attach-shared.d.ts +2 -2
  138. package/dist/integration/attach-shared.d.ts.map +1 -0
  139. package/dist/integration/attach-shared.js.map +1 -0
  140. package/dist/integration/fulltext-attach.js +1 -1
  141. package/dist/integration/fulltext-attach.js.map +1 -1
  142. package/dist/{fulltext → node_modules/@ncukondo/academic-fulltext/dist}/citation-key.js +1 -1
  143. package/dist/node_modules/@ncukondo/academic-fulltext/dist/citation-key.js.map +1 -0
  144. package/dist/node_modules/@ncukondo/academic-fulltext/dist/convert/arxiv-html-parser.js +434 -0
  145. package/dist/node_modules/@ncukondo/academic-fulltext/dist/convert/arxiv-html-parser.js.map +1 -0
  146. package/dist/node_modules/@ncukondo/academic-fulltext/dist/convert/index.js +93 -0
  147. package/dist/node_modules/@ncukondo/academic-fulltext/dist/convert/index.js.map +1 -0
  148. package/dist/node_modules/@ncukondo/academic-fulltext/dist/convert/jats-parser.js +1060 -0
  149. package/dist/node_modules/@ncukondo/academic-fulltext/dist/convert/jats-parser.js.map +1 -0
  150. package/dist/{fulltext → node_modules/@ncukondo/academic-fulltext/dist}/convert/markdown-writer.js +146 -117
  151. package/dist/node_modules/@ncukondo/academic-fulltext/dist/convert/markdown-writer.js.map +1 -0
  152. package/dist/{fulltext → node_modules/@ncukondo/academic-fulltext/dist}/discovery/arxiv.js +8 -1
  153. package/dist/node_modules/@ncukondo/academic-fulltext/dist/discovery/arxiv.js.map +1 -0
  154. package/dist/{fulltext → node_modules/@ncukondo/academic-fulltext/dist}/discovery/core.js +6 -3
  155. package/dist/node_modules/@ncukondo/academic-fulltext/dist/discovery/core.js.map +1 -0
  156. package/dist/node_modules/@ncukondo/academic-fulltext/dist/discovery/index.js +139 -0
  157. package/dist/node_modules/@ncukondo/academic-fulltext/dist/discovery/index.js.map +1 -0
  158. package/dist/node_modules/@ncukondo/academic-fulltext/dist/discovery/ncbi-id-converter.js +46 -0
  159. package/dist/node_modules/@ncukondo/academic-fulltext/dist/discovery/ncbi-id-converter.js.map +1 -0
  160. package/dist/{fulltext → node_modules/@ncukondo/academic-fulltext/dist}/discovery/pmc.js +8 -4
  161. package/dist/node_modules/@ncukondo/academic-fulltext/dist/discovery/pmc.js.map +1 -0
  162. package/dist/{fulltext → node_modules/@ncukondo/academic-fulltext/dist}/discovery/unpaywall.js +43 -9
  163. package/dist/node_modules/@ncukondo/academic-fulltext/dist/discovery/unpaywall.js.map +1 -0
  164. package/dist/node_modules/@ncukondo/academic-fulltext/dist/download/arxiv-html.js +48 -0
  165. package/dist/node_modules/@ncukondo/academic-fulltext/dist/download/arxiv-html.js.map +1 -0
  166. package/dist/node_modules/@ncukondo/academic-fulltext/dist/download/downloader.js +64 -0
  167. package/dist/node_modules/@ncukondo/academic-fulltext/dist/download/downloader.js.map +1 -0
  168. package/dist/node_modules/@ncukondo/academic-fulltext/dist/download/orchestrator.js +236 -0
  169. package/dist/node_modules/@ncukondo/academic-fulltext/dist/download/orchestrator.js.map +1 -0
  170. package/dist/{fulltext → node_modules/@ncukondo/academic-fulltext/dist}/download/pmc-xml.js +2 -1
  171. package/dist/node_modules/@ncukondo/academic-fulltext/dist/download/pmc-xml.js.map +1 -0
  172. package/dist/{fulltext → node_modules/@ncukondo/academic-fulltext/dist}/meta.js +15 -10
  173. package/dist/node_modules/@ncukondo/academic-fulltext/dist/meta.js.map +1 -0
  174. package/dist/node_modules/@ncukondo/academic-fulltext/dist/paths.js.map +1 -0
  175. package/dist/{fulltext → node_modules/@ncukondo/academic-fulltext/dist}/readme.js +8 -4
  176. package/dist/node_modules/@ncukondo/academic-fulltext/dist/readme.js.map +1 -0
  177. package/dist/node_modules/boolbase/index.js +19 -0
  178. package/dist/node_modules/boolbase/index.js.map +1 -0
  179. package/dist/node_modules/css-select/lib/attributes.js +203 -0
  180. package/dist/node_modules/css-select/lib/attributes.js.map +1 -0
  181. package/dist/node_modules/css-select/lib/compile.js +141 -0
  182. package/dist/node_modules/css-select/lib/compile.js.map +1 -0
  183. package/dist/node_modules/css-select/lib/general.js +154 -0
  184. package/dist/node_modules/css-select/lib/general.js.map +1 -0
  185. package/dist/node_modules/css-select/lib/index.js +128 -0
  186. package/dist/node_modules/css-select/lib/index.js.map +1 -0
  187. package/dist/node_modules/css-select/lib/pseudo-selectors/aliases.js +40 -0
  188. package/dist/node_modules/css-select/lib/pseudo-selectors/aliases.js.map +1 -0
  189. package/dist/node_modules/css-select/lib/pseudo-selectors/filters.js +163 -0
  190. package/dist/node_modules/css-select/lib/pseudo-selectors/filters.js.map +1 -0
  191. package/dist/node_modules/css-select/lib/pseudo-selectors/index.js +71 -0
  192. package/dist/node_modules/css-select/lib/pseudo-selectors/index.js.map +1 -0
  193. package/dist/node_modules/css-select/lib/pseudo-selectors/pseudos.js +93 -0
  194. package/dist/node_modules/css-select/lib/pseudo-selectors/pseudos.js.map +1 -0
  195. package/dist/node_modules/css-select/lib/pseudo-selectors/subselects.js +111 -0
  196. package/dist/node_modules/css-select/lib/pseudo-selectors/subselects.js.map +1 -0
  197. package/dist/node_modules/css-select/lib/sort.js +78 -0
  198. package/dist/node_modules/css-select/lib/sort.js.map +1 -0
  199. package/dist/node_modules/css-what/lib/es/index.js +12 -0
  200. package/dist/node_modules/css-what/lib/es/index.js.map +1 -0
  201. package/dist/node_modules/css-what/lib/es/parse.js +349 -0
  202. package/dist/node_modules/css-what/lib/es/parse.js.map +1 -0
  203. package/dist/node_modules/css-what/lib/es/stringify.js +102 -0
  204. package/dist/node_modules/css-what/lib/es/stringify.js.map +1 -0
  205. package/dist/node_modules/css-what/lib/es/types.js +37 -0
  206. package/dist/node_modules/css-what/lib/es/types.js.map +1 -0
  207. package/dist/node_modules/dom-serializer/lib/foreignNames.js +117 -0
  208. package/dist/node_modules/dom-serializer/lib/foreignNames.js.map +1 -0
  209. package/dist/node_modules/dom-serializer/lib/index.js +207 -0
  210. package/dist/node_modules/dom-serializer/lib/index.js.map +1 -0
  211. package/dist/node_modules/dom-serializer/node_modules/entities/lib/decode.js +368 -0
  212. package/dist/node_modules/dom-serializer/node_modules/entities/lib/decode.js.map +1 -0
  213. package/dist/node_modules/dom-serializer/node_modules/entities/lib/decode_codepoint.js +70 -0
  214. package/dist/node_modules/dom-serializer/node_modules/entities/lib/decode_codepoint.js.map +1 -0
  215. package/dist/node_modules/dom-serializer/node_modules/entities/lib/encode.js +61 -0
  216. package/dist/node_modules/dom-serializer/node_modules/entities/lib/encode.js.map +1 -0
  217. package/dist/node_modules/dom-serializer/node_modules/entities/lib/escape.js +79 -0
  218. package/dist/node_modules/dom-serializer/node_modules/entities/lib/escape.js.map +1 -0
  219. package/dist/node_modules/dom-serializer/node_modules/entities/lib/generated/decode-data-html.js +18 -0
  220. package/dist/node_modules/dom-serializer/node_modules/entities/lib/generated/decode-data-html.js.map +1 -0
  221. package/dist/node_modules/dom-serializer/node_modules/entities/lib/generated/decode-data-xml.js +18 -0
  222. package/dist/node_modules/dom-serializer/node_modules/entities/lib/generated/decode-data-xml.js.map +1 -0
  223. package/dist/node_modules/dom-serializer/node_modules/entities/lib/generated/encode-html.js +19 -0
  224. package/dist/node_modules/dom-serializer/node_modules/entities/lib/generated/encode-html.js.map +1 -0
  225. package/dist/node_modules/dom-serializer/node_modules/entities/lib/index.js +139 -0
  226. package/dist/node_modules/dom-serializer/node_modules/entities/lib/index.js.map +1 -0
  227. package/dist/node_modules/domelementtype/lib/index.js +40 -0
  228. package/dist/node_modules/domelementtype/lib/index.js.map +1 -0
  229. package/dist/node_modules/domhandler/lib/index.js +167 -0
  230. package/dist/node_modules/domhandler/lib/index.js.map +1 -0
  231. package/dist/node_modules/domhandler/lib/node.js +439 -0
  232. package/dist/node_modules/domhandler/lib/node.js.map +1 -0
  233. package/dist/node_modules/domutils/lib/feeds.js +146 -0
  234. package/dist/node_modules/domutils/lib/feeds.js.map +1 -0
  235. package/dist/node_modules/domutils/lib/helpers.js +97 -0
  236. package/dist/node_modules/domutils/lib/helpers.js.map +1 -0
  237. package/dist/node_modules/domutils/lib/index.js +65 -0
  238. package/dist/node_modules/domutils/lib/index.js.map +1 -0
  239. package/dist/node_modules/domutils/lib/legacy.js +124 -0
  240. package/dist/node_modules/domutils/lib/legacy.js.map +1 -0
  241. package/dist/node_modules/domutils/lib/manipulation.js +107 -0
  242. package/dist/node_modules/domutils/lib/manipulation.js.map +1 -0
  243. package/dist/node_modules/domutils/lib/querying.js +102 -0
  244. package/dist/node_modules/domutils/lib/querying.js.map +1 -0
  245. package/dist/node_modules/domutils/lib/stringify.js +65 -0
  246. package/dist/node_modules/domutils/lib/stringify.js.map +1 -0
  247. package/dist/node_modules/domutils/lib/traversal.js +69 -0
  248. package/dist/node_modules/domutils/lib/traversal.js.map +1 -0
  249. package/dist/node_modules/he/he.js +256 -0
  250. package/dist/node_modules/he/he.js.map +1 -0
  251. package/dist/node_modules/node-html-parser/dist/back.js +16 -0
  252. package/dist/node_modules/node-html-parser/dist/back.js.map +1 -0
  253. package/dist/node_modules/node-html-parser/dist/index.js +48 -0
  254. package/dist/node_modules/node-html-parser/dist/index.js.map +1 -0
  255. package/dist/node_modules/node-html-parser/dist/matcher.js +112 -0
  256. package/dist/node_modules/node-html-parser/dist/matcher.js.map +1 -0
  257. package/dist/node_modules/node-html-parser/dist/nodes/comment.js +41 -0
  258. package/dist/node_modules/node-html-parser/dist/nodes/comment.js.map +1 -0
  259. package/dist/node_modules/node-html-parser/dist/nodes/html.js +1048 -0
  260. package/dist/node_modules/node-html-parser/dist/nodes/html.js.map +1 -0
  261. package/dist/node_modules/node-html-parser/dist/nodes/node.js +49 -0
  262. package/dist/node_modules/node-html-parser/dist/nodes/node.js.map +1 -0
  263. package/dist/node_modules/node-html-parser/dist/nodes/text.js +106 -0
  264. package/dist/node_modules/node-html-parser/dist/nodes/text.js.map +1 -0
  265. package/dist/node_modules/node-html-parser/dist/nodes/type.js +19 -0
  266. package/dist/node_modules/node-html-parser/dist/nodes/type.js.map +1 -0
  267. package/dist/node_modules/node-html-parser/dist/parse.js +20 -0
  268. package/dist/node_modules/node-html-parser/dist/parse.js.map +1 -0
  269. package/dist/node_modules/node-html-parser/dist/valid.js +19 -0
  270. package/dist/node_modules/node-html-parser/dist/valid.js.map +1 -0
  271. package/dist/node_modules/node-html-parser/dist/void-tag.js +36 -0
  272. package/dist/node_modules/node-html-parser/dist/void-tag.js.map +1 -0
  273. package/dist/node_modules/nth-check/lib/compile.js +76 -0
  274. package/dist/node_modules/nth-check/lib/compile.js.map +1 -0
  275. package/dist/node_modules/nth-check/lib/index.js +36 -0
  276. package/dist/node_modules/nth-check/lib/index.js.map +1 -0
  277. package/dist/node_modules/nth-check/lib/parse.js +69 -0
  278. package/dist/node_modules/nth-check/lib/parse.js.map +1 -0
  279. package/package.json +2 -2
  280. package/dist/fulltext/attach-shared.d.ts.map +0 -1
  281. package/dist/fulltext/attach-shared.js.map +0 -1
  282. package/dist/fulltext/citation-key.d.ts +0 -15
  283. package/dist/fulltext/citation-key.d.ts.map +0 -1
  284. package/dist/fulltext/citation-key.js.map +0 -1
  285. package/dist/fulltext/convert/index.d.ts +0 -20
  286. package/dist/fulltext/convert/index.d.ts.map +0 -1
  287. package/dist/fulltext/convert/index.js +0 -50
  288. package/dist/fulltext/convert/index.js.map +0 -1
  289. package/dist/fulltext/convert/jats-parser.d.ts +0 -36
  290. package/dist/fulltext/convert/jats-parser.d.ts.map +0 -1
  291. package/dist/fulltext/convert/jats-parser.js +0 -887
  292. package/dist/fulltext/convert/jats-parser.js.map +0 -1
  293. package/dist/fulltext/convert/markdown-writer.d.ts +0 -6
  294. package/dist/fulltext/convert/markdown-writer.d.ts.map +0 -1
  295. package/dist/fulltext/convert/markdown-writer.js.map +0 -1
  296. package/dist/fulltext/convert/types.d.ts +0 -141
  297. package/dist/fulltext/convert/types.d.ts.map +0 -1
  298. package/dist/fulltext/discovery/arxiv.d.ts +0 -11
  299. package/dist/fulltext/discovery/arxiv.d.ts.map +0 -1
  300. package/dist/fulltext/discovery/arxiv.js.map +0 -1
  301. package/dist/fulltext/discovery/core.d.ts +0 -11
  302. package/dist/fulltext/discovery/core.d.ts.map +0 -1
  303. package/dist/fulltext/discovery/core.js.map +0 -1
  304. package/dist/fulltext/discovery/index.d.ts +0 -28
  305. package/dist/fulltext/discovery/index.d.ts.map +0 -1
  306. package/dist/fulltext/discovery/index.js +0 -75
  307. package/dist/fulltext/discovery/index.js.map +0 -1
  308. package/dist/fulltext/discovery/pmc.d.ts +0 -19
  309. package/dist/fulltext/discovery/pmc.d.ts.map +0 -1
  310. package/dist/fulltext/discovery/pmc.js.map +0 -1
  311. package/dist/fulltext/discovery/unpaywall.d.ts +0 -11
  312. package/dist/fulltext/discovery/unpaywall.d.ts.map +0 -1
  313. package/dist/fulltext/discovery/unpaywall.js.map +0 -1
  314. package/dist/fulltext/download/downloader.d.ts +0 -21
  315. package/dist/fulltext/download/downloader.d.ts.map +0 -1
  316. package/dist/fulltext/download/downloader.js +0 -59
  317. package/dist/fulltext/download/downloader.js.map +0 -1
  318. package/dist/fulltext/download/orchestrator.d.ts +0 -33
  319. package/dist/fulltext/download/orchestrator.d.ts.map +0 -1
  320. package/dist/fulltext/download/orchestrator.js +0 -125
  321. package/dist/fulltext/download/orchestrator.js.map +0 -1
  322. package/dist/fulltext/download/pmc-xml.d.ts +0 -13
  323. package/dist/fulltext/download/pmc-xml.d.ts.map +0 -1
  324. package/dist/fulltext/download/pmc-xml.js.map +0 -1
  325. package/dist/fulltext/meta.d.ts +0 -25
  326. package/dist/fulltext/meta.d.ts.map +0 -1
  327. package/dist/fulltext/meta.js.map +0 -1
  328. package/dist/fulltext/paths.d.ts +0 -12
  329. package/dist/fulltext/paths.d.ts.map +0 -1
  330. package/dist/fulltext/paths.js.map +0 -1
  331. package/dist/fulltext/readme.d.ts +0 -4
  332. package/dist/fulltext/readme.d.ts.map +0 -1
  333. package/dist/fulltext/readme.js.map +0 -1
  334. package/dist/fulltext/types.d.ts +0 -90
  335. package/dist/fulltext/types.d.ts.map +0 -1
  336. /package/dist/{fulltext → integration}/attach-shared.js +0 -0
  337. /package/dist/{fulltext → node_modules/@ncukondo/academic-fulltext/dist}/paths.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sources":["../../../../src/cli/commands/fulltext/sync.ts"],"sourcesContent":["/**\n * fulltext sync command - Detect and register manually added files.\n */\n\nimport { join } from 'node:path';\nimport { readFile, writeFile, readdir, stat } from 'node:fs/promises';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport type { ReviewFile } from '../review/types.js';\nimport type { FulltextMeta, FileInfo } from '../../../fulltext/types.js';\nimport { loadMeta, saveMeta, updateMetaFiles } from '../../../fulltext/meta.js';\nimport { getFulltextDir } from '../../../fulltext/paths.js';\n\n/** Known fulltext filenames and their type keys. */\nconst FULLTEXT_FILES: Record<string, 'pdf' | 'xml' | 'markdown'> = {\n 'fulltext.pdf': 'pdf',\n 'fulltext.xml': 'xml',\n 'fulltext.md': 'markdown',\n};\n\nexport interface FulltextSyncOptions {\n sessionId: string;\n sessionsDir: string;\n dryRun?: boolean;\n}\n\nexport interface FulltextSyncEntry {\n dirName: string;\n files: string[];\n sizes: number[];\n}\n\nexport interface FulltextSyncResult {\n /** Total number of new files synced */\n synced: number;\n /** Number of articles updated */\n articlesUpdated: number;\n entries: FulltextSyncEntry[];\n dryRun?: boolean;\n}\n\nexport async function executeFulltextSync(\n options: FulltextSyncOptions,\n): Promise<FulltextSyncResult> {\n const { sessionId, sessionsDir, dryRun } = options;\n const sessionDir = join(sessionsDir, sessionId);\n const fulltextDir = getFulltextDir(sessionDir);\n\n // Scan all directories in fulltext/\n let dirEntries: string[];\n try {\n const entries = await readdir(fulltextDir, { withFileTypes: true });\n dirEntries = entries.filter(e => e.isDirectory()).map(e => e.name);\n } catch {\n return { synced: 0, articlesUpdated: 0, entries: [] };\n }\n\n const syncEntries: FulltextSyncEntry[] = [];\n let totalSynced = 0;\n const articlesWithChanges = new Set<string>();\n\n // Track updates for meta and reviews\n const hasFilesUpdates = new Map<string, { pdf: boolean; xml: boolean; markdown: boolean }>();\n const metaUpdates = new Map<string, { meta: FulltextMeta; path: string }>();\n\n for (const dirName of dirEntries) {\n const articleDir = join(fulltextDir, dirName);\n const metaPath = join(articleDir, 'meta.json');\n\n // Load meta.json\n let meta: FulltextMeta;\n try {\n meta = await loadMeta(metaPath);\n } catch {\n // Skip directories without meta.json\n continue;\n }\n\n const newFiles: string[] = [];\n const newSizes: number[] = [];\n const fileInfoUpdates: { pdf?: FileInfo; xml?: FileInfo; markdown?: FileInfo } = {};\n\n for (const [filename, typeKey] of Object.entries(FULLTEXT_FILES)) {\n // Skip if already tracked in meta\n if (meta.files[typeKey]) {\n continue;\n }\n\n // Check if file exists\n const filePath = join(articleDir, filename);\n let fileStat;\n try {\n fileStat = await stat(filePath);\n } catch {\n continue; // File doesn't exist\n }\n\n if (!fileStat.isFile()) continue;\n\n // New file found\n const fileInfo: FileInfo = {\n filename,\n source: 'manual',\n retrievedAt: new Date().toISOString(),\n size: fileStat.size,\n };\n\n fileInfoUpdates[typeKey] = fileInfo;\n newFiles.push(filename);\n newSizes.push(fileStat.size);\n }\n\n if (newFiles.length > 0) {\n totalSynced += newFiles.length;\n articlesWithChanges.add(dirName);\n\n syncEntries.push({\n dirName,\n files: newFiles,\n sizes: newSizes,\n });\n\n if (!dryRun) {\n // Update meta.json\n const updatedMeta = updateMetaFiles(meta, fileInfoUpdates);\n metaUpdates.set(dirName, { meta: updatedMeta, path: metaPath });\n\n // Compute updated hasFiles for reviews\n const hasFiles = {\n pdf: !!(updatedMeta.files.pdf),\n xml: !!(updatedMeta.files.xml),\n markdown: !!(updatedMeta.files.markdown),\n };\n hasFilesUpdates.set(dirName, hasFiles);\n }\n }\n }\n\n if (!dryRun && metaUpdates.size > 0) {\n // Save all meta.json updates\n for (const [, { meta, path }] of metaUpdates) {\n await saveMeta(path, meta);\n }\n\n // Update reviews.yaml if it exists\n const reviewsPath = join(sessionDir, '.internal', 'reviews.yaml');\n try {\n const reviewContent = await readFile(reviewsPath, 'utf-8');\n const reviewFile = parseYaml(reviewContent) as ReviewFile;\n let reviewsChanged = false;\n\n for (const article of reviewFile.articles) {\n if (article.fulltext?.dirName && hasFilesUpdates.has(article.fulltext.dirName)) {\n const hasFiles = hasFilesUpdates.get(article.fulltext.dirName);\n if (hasFiles) {\n article.fulltext.hasFiles = hasFiles;\n reviewsChanged = true;\n }\n }\n }\n\n if (reviewsChanged) {\n await writeFile(reviewsPath, stringifyYaml(reviewFile), 'utf-8');\n }\n } catch {\n // No reviews.yaml - that's fine\n }\n }\n\n return {\n synced: totalSynced,\n articlesUpdated: articlesWithChanges.size,\n entries: syncEntries,\n ...(dryRun && { dryRun: true }),\n };\n}\n"],"names":["parseYaml","stringifyYaml"],"mappings":"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"}
1
+ {"version":3,"file":"sync.js","sources":["../../../../src/cli/commands/fulltext/sync.ts"],"sourcesContent":["/**\n * fulltext sync command - Detect and register manually added files.\n */\n\nimport { join } from 'node:path';\nimport { readFile, writeFile, readdir, stat } from 'node:fs/promises';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport type { ReviewFile } from '../review/types.js';\nimport { loadMeta, saveMeta, updateMetaFiles, getFulltextDir, type FulltextMeta, type FileInfo } from '@ncukondo/academic-fulltext';\n\n/** Known fulltext filenames and their type keys. */\nconst FULLTEXT_FILES: Record<string, 'pdf' | 'xml' | 'html' | 'markdown'> = {\n 'fulltext.pdf': 'pdf',\n 'fulltext.xml': 'xml',\n 'fulltext.html': 'html',\n 'fulltext.md': 'markdown',\n};\n\nexport interface FulltextSyncOptions {\n sessionId: string;\n sessionsDir: string;\n dryRun?: boolean;\n}\n\nexport interface FulltextSyncEntry {\n dirName: string;\n files: string[];\n sizes: number[];\n}\n\nexport interface FulltextSyncResult {\n /** Total number of new files synced */\n synced: number;\n /** Number of articles updated */\n articlesUpdated: number;\n entries: FulltextSyncEntry[];\n dryRun?: boolean;\n}\n\nexport async function executeFulltextSync(\n options: FulltextSyncOptions,\n): Promise<FulltextSyncResult> {\n const { sessionId, sessionsDir, dryRun } = options;\n const sessionDir = join(sessionsDir, sessionId);\n const fulltextDir = getFulltextDir(sessionDir);\n\n // Scan all directories in fulltext/\n let dirEntries: string[];\n try {\n const entries = await readdir(fulltextDir, { withFileTypes: true });\n dirEntries = entries.filter(e => e.isDirectory()).map(e => e.name);\n } catch {\n return { synced: 0, articlesUpdated: 0, entries: [] };\n }\n\n const syncEntries: FulltextSyncEntry[] = [];\n let totalSynced = 0;\n const articlesWithChanges = new Set<string>();\n\n // Track updates for meta and reviews\n const hasFilesUpdates = new Map<string, { pdf: boolean; xml: boolean; html: boolean; markdown: boolean }>();\n const metaUpdates = new Map<string, { meta: FulltextMeta; path: string }>();\n\n for (const dirName of dirEntries) {\n const articleDir = join(fulltextDir, dirName);\n const metaPath = join(articleDir, 'meta.json');\n\n // Load meta.json\n let meta: FulltextMeta;\n try {\n meta = await loadMeta(metaPath);\n } catch {\n // Skip directories without meta.json\n continue;\n }\n\n const newFiles: string[] = [];\n const newSizes: number[] = [];\n const fileInfoUpdates: { pdf?: FileInfo; xml?: FileInfo; html?: FileInfo; markdown?: FileInfo } = {};\n\n for (const [filename, typeKey] of Object.entries(FULLTEXT_FILES)) {\n // Skip if already tracked in meta\n if (meta.files[typeKey]) {\n continue;\n }\n\n // Check if file exists\n const filePath = join(articleDir, filename);\n let fileStat;\n try {\n fileStat = await stat(filePath);\n } catch {\n continue; // File doesn't exist\n }\n\n if (!fileStat.isFile()) continue;\n\n // New file found\n const fileInfo: FileInfo = {\n filename,\n source: 'manual',\n retrievedAt: new Date().toISOString(),\n size: fileStat.size,\n };\n\n fileInfoUpdates[typeKey] = fileInfo;\n newFiles.push(filename);\n newSizes.push(fileStat.size);\n }\n\n if (newFiles.length > 0) {\n totalSynced += newFiles.length;\n articlesWithChanges.add(dirName);\n\n syncEntries.push({\n dirName,\n files: newFiles,\n sizes: newSizes,\n });\n\n if (!dryRun) {\n // Update meta.json\n const updatedMeta = updateMetaFiles(meta, fileInfoUpdates);\n metaUpdates.set(dirName, { meta: updatedMeta, path: metaPath });\n\n // Compute updated hasFiles for reviews\n const hasFiles = {\n pdf: !!(updatedMeta.files.pdf),\n xml: !!(updatedMeta.files.xml),\n html: !!(updatedMeta.files.html),\n markdown: !!(updatedMeta.files.markdown),\n };\n hasFilesUpdates.set(dirName, hasFiles);\n }\n }\n }\n\n if (!dryRun && metaUpdates.size > 0) {\n // Save all meta.json updates\n for (const [, { meta, path }] of metaUpdates) {\n await saveMeta(path, meta);\n }\n\n // Update reviews.yaml if it exists\n const reviewsPath = join(sessionDir, '.internal', 'reviews.yaml');\n try {\n const reviewContent = await readFile(reviewsPath, 'utf-8');\n const reviewFile = parseYaml(reviewContent) as ReviewFile;\n let reviewsChanged = false;\n\n for (const article of reviewFile.articles) {\n if (article.fulltext?.dirName && hasFilesUpdates.has(article.fulltext.dirName)) {\n const hasFiles = hasFilesUpdates.get(article.fulltext.dirName);\n if (hasFiles) {\n article.fulltext.hasFiles = hasFiles;\n reviewsChanged = true;\n }\n }\n }\n\n if (reviewsChanged) {\n await writeFile(reviewsPath, stringifyYaml(reviewFile), 'utf-8');\n }\n } catch {\n // No reviews.yaml - that's fine\n }\n }\n\n return {\n synced: totalSynced,\n articlesUpdated: articlesWithChanges.size,\n entries: syncEntries,\n ...(dryRun && { dryRun: true }),\n };\n}\n"],"names":["parseYaml","stringifyYaml"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { ArticleFulltextRef } from '../../../fulltext/types.js';
1
+ import { ArticleFulltextRef } from '@ncukondo/academic-fulltext';
2
2
  export type ReviewDecision = 'include' | 'exclude' | 'uncertain';
3
3
  /**
4
4
  * Basis of the review decision (what information was used)
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/review/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAErE,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,wDAAwD;IACxD,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAE3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAGhB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;IAG5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;IAG7C,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,iEAAiE;IACjE,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,iGAAiG;AACjG,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,mGAAmG;AACnG,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAWD,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,CAGhE;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,YAAY,GACZ,WAAW,GACX,gBAAgB,GAChB,gBAAgB,GAChB,aAAa,GACb,WAAW,CAAC;AAEhB;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,YAAY,EACnB,mBAAmB,CAAC,EAAE,cAAc,EAAE,GACrC,YAAY,CAsHd"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/review/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sources":["../../../../src/cli/commands/review/types.ts"],"sourcesContent":["/**\n * Review workflow types for article assessment tracking\n */\n\nimport type { ArticleFulltextRef } from '../../../fulltext/types.js';\n\nexport type ReviewDecision = 'include' | 'exclude' | 'uncertain';\n\n/**\n * Basis of the review decision (what information was used)\n */\nexport type ReviewBasis = 'title' | 'abstract' | 'fulltext';\n\n/**\n * Individual assessment of an article by a reviewer\n */\nexport interface Review {\n /** Reviewer identifier: \"human:name\" or \"ai:name\" */\n reviewer: string;\n /** Assessment decision */\n decision?: ReviewDecision;\n /** Basis of the decision (what information was used) */\n basis?: ReviewBasis;\n /** Optional comment or reason */\n comment?: string;\n /** ISO 8601 timestamp (optional - auto-assigned on merge if not provided) */\n timestamp?: string;\n}\n\n/**\n * Source information for merged duplicates\n */\nexport interface MergedSource {\n source: string;\n pmid?: string;\n doi?: string;\n scopusId?: string;\n arxivId?: string;\n ericId?: string;\n}\n\n/**\n * Article entry with identifiers, bibliographic info, and reviews\n */\nexport interface ArticleEntry {\n // Identifiers (at least one required for matching)\n doi?: string;\n pmid?: string;\n scopusId?: string;\n arxivId?: string;\n ericId?: string;\n\n // Bibliographic info (for reviewer reference)\n title: string;\n authors?: string;\n year?: string;\n abstract?: string;\n\n // Deduplication tracking\n mergedFrom?: MergedSource[];\n\n // Review data\n reviews: Review[];\n /** Historical reviews (only in extracted ReviewFiles, never in master file) */\n reviewHistory?: Review[];\n finalDecision?: 'include' | 'exclude' | null;\n\n // Fulltext reference (set by fulltext init/sync)\n fulltext?: ArticleFulltextRef;\n}\n\n/**\n * Top-level structure of the reviews.yaml file\n */\nexport interface ReviewerRecord {\n name: string;\n basis: ReviewBasis;\n}\n\nexport interface ReviewFile {\n sessionId: string;\n /** Path to inclusion criteria file */\n criteria?: string;\n /** Reviewer identifier (only in extracted ReviewFiles) */\n reviewer?: string;\n /** Basis level for screening (only in extracted ReviewFiles) */\n basis?: ReviewBasis;\n articles: ArticleEntry[];\n /** Registry of reviewers who participated at each basis level */\n reviewers?: ReviewerRecord[];\n}\n\n/**\n * Work file article entry for AI agent workflow\n */\n/** @deprecated Use ReviewFile format with reviews[] instead. Kept for backward compatibility. */\nexport interface WorkFileArticle {\n id: string;\n title: string;\n abstract?: string;\n /** Fulltext directory name (only for fulltext basis) */\n fulltext?: string;\n decision: ReviewDecision | null;\n comment: string;\n}\n\n/**\n * Work file structure for AI agent workflow\n */\n/** @deprecated Use ReviewFile format with basis field instead. Kept for backward compatibility. */\nexport interface WorkFile {\n sessionId: string;\n basis: ReviewBasis;\n reviewer: string;\n articles: WorkFileArticle[];\n}\n\n/**\n * Basis priority rank: fulltext > abstract > title > undefined\n */\nconst BASIS_RANK: Record<string, number> = {\n title: 1,\n abstract: 2,\n fulltext: 3,\n};\n\nexport function basisRank(basis: ReviewBasis | undefined): number {\n if (basis === undefined) return 0;\n return BASIS_RANK[basis] ?? 0;\n}\n\n/**\n * Review status classification (7-state model)\n */\nexport type ReviewStatus =\n | 'pending'\n | 'incomplete'\n | 'uncertain'\n | 'agreed-include'\n | 'agreed-exclude'\n | 'conflicting'\n | 'finalized';\n\n/**\n * Classify the review status of an article entry\n *\n * Classification logic (in order):\n * 1. finalDecision set? → finalized\n * 2. No reviews? → pending\n * 3. Registered reviewer missing? → incomplete\n * 4. include AND exclude present? → conflicting\n * 5. Any uncertain? → uncertain\n * 6. All include? → agreed-include\n * 7. All exclude? → agreed-exclude\n */\nexport function classifyStatus(\n entry: ArticleEntry,\n registeredReviewers?: ReviewerRecord[]\n): ReviewStatus {\n // 1. Finalized takes precedence\n if (entry.finalDecision !== undefined && entry.finalDecision !== null) {\n return 'finalized';\n }\n\n // No reviews = pending (reviews can be null from YAML parsing with only comments)\n const reviews = entry.reviews ?? [];\n if (reviews.length === 0) {\n return 'pending';\n }\n\n // 3. Check for incomplete (registered reviewer missing)\n // Only check reviewers whose registered basis ≤ article's highest reviewed basis\n if (registeredReviewers && registeredReviewers.length > 0) {\n const reviewerNames = new Set(reviews.map((r) => r.reviewer));\n let highestReviewedRank = 0;\n for (const r of reviews) {\n highestReviewedRank = Math.max(highestReviewedRank, basisRank(r.basis));\n }\n // When reviews have no basis (legacy), check all registered reviewers\n const applicableReviewers = highestReviewedRank === 0\n ? registeredReviewers\n : registeredReviewers.filter(\n (reg) => basisRank(reg.basis) <= highestReviewedRank\n );\n const hasAllReviewers = applicableReviewers.every((reg) =>\n reviewerNames.has(reg.name)\n );\n if (applicableReviewers.length > 0 && !hasAllReviewers) {\n return 'incomplete';\n }\n }\n\n // Get reviews that have decisions\n const reviewsWithDecisions = reviews.filter((r) => r.decision !== undefined);\n\n if (reviewsWithDecisions.length === 0) {\n // All reviews lack a decision — treat as pending\n return 'pending';\n }\n\n // Basis-priority resolution:\n // \"uncertain\" at a lower basis means \"need more info\" (escalate).\n // A definitive decision at a higher basis resolves that uncertainty.\n //\n // Algorithm:\n // 1. Find the highest basis rank among all definitive (include/exclude) reviews\n // 2. For each reviewer, compute their effective decision:\n // - Take their highest-basis definitive decision if they have one\n // - Otherwise, keep uncertain only if their uncertain rank >= highest definitive rank\n // (i.e., no higher-basis definitive exists globally to resolve it)\n // 3. Reviewers whose only reviews are uncertain at a lower basis than the\n // highest global definitive are excluded from consensus (their uncertainty was resolved)\n\n // Find highest definitive basis rank across ALL reviews\n let highestDefinitiveRank = 0;\n for (const r of reviewsWithDecisions) {\n if (r.decision !== 'uncertain') {\n highestDefinitiveRank = Math.max(highestDefinitiveRank, basisRank(r.basis));\n }\n }\n\n // For each reviewer, compute effective decision\n const reviewerMap = new Map<string, { decision: ReviewDecision; rank: number }>();\n for (const r of reviewsWithDecisions) {\n const rank = basisRank(r.basis);\n const existing = reviewerMap.get(r.reviewer);\n if (!existing) {\n reviewerMap.set(r.reviewer, { decision: r.decision!, rank });\n } else {\n // Prefer definitive over uncertain\n if (r.decision !== 'uncertain' && existing.decision === 'uncertain') {\n reviewerMap.set(r.reviewer, { decision: r.decision!, rank });\n } else if (r.decision !== 'uncertain' && existing.decision !== 'uncertain' && rank > existing.rank) {\n // Higher-basis definitive overrides lower-basis definitive\n reviewerMap.set(r.reviewer, { decision: r.decision!, rank });\n } else if (r.decision === 'uncertain' && existing.decision === 'uncertain' && rank > existing.rank) {\n reviewerMap.set(r.reviewer, { decision: r.decision!, rank });\n }\n }\n }\n\n // Collect effective decisions, excluding reviewers whose effective decision\n // is at a lower basis than the highest global definitive\n const effectiveDecisions: ReviewDecision[] = [];\n for (const { decision, rank } of reviewerMap.values()) {\n if (rank < highestDefinitiveRank) {\n // This reviewer's decision is at a lower basis than the highest definitive — skip\n continue;\n }\n effectiveDecisions.push(decision);\n }\n\n if (effectiveDecisions.length === 0) {\n return 'pending';\n }\n\n // 4. Check for conflicts: both include and exclude present among effective decisions\n const hasInclude = effectiveDecisions.includes('include');\n const hasExclude = effectiveDecisions.includes('exclude');\n if (hasInclude && hasExclude) {\n return 'conflicting';\n }\n\n // 5. Any effective uncertain?\n const hasUncertain = effectiveDecisions.includes('uncertain');\n if (hasUncertain) {\n return 'uncertain';\n }\n\n // 6. All include?\n if (effectiveDecisions.every((d) => d === 'include')) {\n return 'agreed-include';\n }\n\n // 7. All exclude (only remaining possibility after ruling out conflicts and uncertain)\n return 'agreed-exclude';\n}\n"],"names":[],"mappings":"AAwHA,MAAM,aAAqC;AAAA,EACzC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,UAAU;AACZ;AAEO,SAAS,UAAU,OAAwC;AAChE,MAAI,UAAU,OAAW,QAAO;AAChC,SAAO,WAAW,KAAK,KAAK;AAC9B;AA0BO,SAAS,eACd,OACA,qBACc;AAEd,MAAI,MAAM,kBAAkB,UAAa,MAAM,kBAAkB,MAAM;AACrE,WAAO;AAAA,EACT;AAGA,QAAM,UAAU,MAAM,WAAW,CAAA;AACjC,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,EACT;AAIA,MAAI,uBAAuB,oBAAoB,SAAS,GAAG;AACzD,UAAM,gBAAgB,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;AAC5D,QAAI,sBAAsB;AAC1B,eAAW,KAAK,SAAS;AACvB,4BAAsB,KAAK,IAAI,qBAAqB,UAAU,EAAE,KAAK,CAAC;AAAA,IACxE;AAEA,UAAM,sBAAsB,wBAAwB,IAChD,sBACA,oBAAoB;AAAA,MAClB,CAAC,QAAQ,UAAU,IAAI,KAAK,KAAK;AAAA,IAAA;AAEvC,UAAM,kBAAkB,oBAAoB;AAAA,MAAM,CAAC,QACjD,cAAc,IAAI,IAAI,IAAI;AAAA,IAAA;AAE5B,QAAI,oBAAoB,SAAS,KAAK,CAAC,iBAAiB;AACtD,aAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,uBAAuB,QAAQ,OAAO,CAAC,MAAM,EAAE,aAAa,MAAS;AAE3E,MAAI,qBAAqB,WAAW,GAAG;AAErC,WAAO;AAAA,EACT;AAgBA,MAAI,wBAAwB;AAC5B,aAAW,KAAK,sBAAsB;AACpC,QAAI,EAAE,aAAa,aAAa;AAC9B,8BAAwB,KAAK,IAAI,uBAAuB,UAAU,EAAE,KAAK,CAAC;AAAA,IAC5E;AAAA,EACF;AAGA,QAAM,kCAAkB,IAAA;AACxB,aAAW,KAAK,sBAAsB;AACpC,UAAM,OAAO,UAAU,EAAE,KAAK;AAC9B,UAAM,WAAW,YAAY,IAAI,EAAE,QAAQ;AAC3C,QAAI,CAAC,UAAU;AACb,kBAAY,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAW,MAAM;AAAA,IAC7D,OAAO;AAEL,UAAI,EAAE,aAAa,eAAe,SAAS,aAAa,aAAa;AACnE,oBAAY,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAW,MAAM;AAAA,MAC7D,WAAW,EAAE,aAAa,eAAe,SAAS,aAAa,eAAe,OAAO,SAAS,MAAM;AAElG,oBAAY,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAW,MAAM;AAAA,MAC7D,WAAW,EAAE,aAAa,eAAe,SAAS,aAAa,eAAe,OAAO,SAAS,MAAM;AAClG,oBAAY,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAW,MAAM;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAIA,QAAM,qBAAuC,CAAA;AAC7C,aAAW,EAAE,UAAU,KAAA,KAAU,YAAY,UAAU;AACrD,QAAI,OAAO,uBAAuB;AAEhC;AAAA,IACF;AACA,uBAAmB,KAAK,QAAQ;AAAA,EAClC;AAEA,MAAI,mBAAmB,WAAW,GAAG;AACnC,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,mBAAmB,SAAS,SAAS;AACxD,QAAM,aAAa,mBAAmB,SAAS,SAAS;AACxD,MAAI,cAAc,YAAY;AAC5B,WAAO;AAAA,EACT;AAGA,QAAM,eAAe,mBAAmB,SAAS,WAAW;AAC5D,MAAI,cAAc;AAChB,WAAO;AAAA,EACT;AAGA,MAAI,mBAAmB,MAAM,CAAC,MAAM,MAAM,SAAS,GAAG;AACpD,WAAO;AAAA,EACT;AAGA,SAAO;AACT;"}
1
+ {"version":3,"file":"types.js","sources":["../../../../src/cli/commands/review/types.ts"],"sourcesContent":["/**\n * Review workflow types for article assessment tracking\n */\n\nimport type { ArticleFulltextRef } from '@ncukondo/academic-fulltext';\n\nexport type ReviewDecision = 'include' | 'exclude' | 'uncertain';\n\n/**\n * Basis of the review decision (what information was used)\n */\nexport type ReviewBasis = 'title' | 'abstract' | 'fulltext';\n\n/**\n * Individual assessment of an article by a reviewer\n */\nexport interface Review {\n /** Reviewer identifier: \"human:name\" or \"ai:name\" */\n reviewer: string;\n /** Assessment decision */\n decision?: ReviewDecision;\n /** Basis of the decision (what information was used) */\n basis?: ReviewBasis;\n /** Optional comment or reason */\n comment?: string;\n /** ISO 8601 timestamp (optional - auto-assigned on merge if not provided) */\n timestamp?: string;\n}\n\n/**\n * Source information for merged duplicates\n */\nexport interface MergedSource {\n source: string;\n pmid?: string;\n doi?: string;\n scopusId?: string;\n arxivId?: string;\n ericId?: string;\n}\n\n/**\n * Article entry with identifiers, bibliographic info, and reviews\n */\nexport interface ArticleEntry {\n // Identifiers (at least one required for matching)\n doi?: string;\n pmid?: string;\n scopusId?: string;\n arxivId?: string;\n ericId?: string;\n\n // Bibliographic info (for reviewer reference)\n title: string;\n authors?: string;\n year?: string;\n abstract?: string;\n\n // Deduplication tracking\n mergedFrom?: MergedSource[];\n\n // Review data\n reviews: Review[];\n /** Historical reviews (only in extracted ReviewFiles, never in master file) */\n reviewHistory?: Review[];\n finalDecision?: 'include' | 'exclude' | null;\n\n // Fulltext reference (set by fulltext init/sync)\n fulltext?: ArticleFulltextRef;\n}\n\n/**\n * Top-level structure of the reviews.yaml file\n */\nexport interface ReviewerRecord {\n name: string;\n basis: ReviewBasis;\n}\n\nexport interface ReviewFile {\n sessionId: string;\n /** Path to inclusion criteria file */\n criteria?: string;\n /** Reviewer identifier (only in extracted ReviewFiles) */\n reviewer?: string;\n /** Basis level for screening (only in extracted ReviewFiles) */\n basis?: ReviewBasis;\n articles: ArticleEntry[];\n /** Registry of reviewers who participated at each basis level */\n reviewers?: ReviewerRecord[];\n}\n\n/**\n * Work file article entry for AI agent workflow\n */\n/** @deprecated Use ReviewFile format with reviews[] instead. Kept for backward compatibility. */\nexport interface WorkFileArticle {\n id: string;\n title: string;\n abstract?: string;\n /** Fulltext directory name (only for fulltext basis) */\n fulltext?: string;\n decision: ReviewDecision | null;\n comment: string;\n}\n\n/**\n * Work file structure for AI agent workflow\n */\n/** @deprecated Use ReviewFile format with basis field instead. Kept for backward compatibility. */\nexport interface WorkFile {\n sessionId: string;\n basis: ReviewBasis;\n reviewer: string;\n articles: WorkFileArticle[];\n}\n\n/**\n * Basis priority rank: fulltext > abstract > title > undefined\n */\nconst BASIS_RANK: Record<string, number> = {\n title: 1,\n abstract: 2,\n fulltext: 3,\n};\n\nexport function basisRank(basis: ReviewBasis | undefined): number {\n if (basis === undefined) return 0;\n return BASIS_RANK[basis] ?? 0;\n}\n\n/**\n * Review status classification (7-state model)\n */\nexport type ReviewStatus =\n | 'pending'\n | 'incomplete'\n | 'uncertain'\n | 'agreed-include'\n | 'agreed-exclude'\n | 'conflicting'\n | 'finalized';\n\n/**\n * Classify the review status of an article entry\n *\n * Classification logic (in order):\n * 1. finalDecision set? → finalized\n * 2. No reviews? → pending\n * 3. Registered reviewer missing? → incomplete\n * 4. include AND exclude present? → conflicting\n * 5. Any uncertain? → uncertain\n * 6. All include? → agreed-include\n * 7. All exclude? → agreed-exclude\n */\nexport function classifyStatus(\n entry: ArticleEntry,\n registeredReviewers?: ReviewerRecord[]\n): ReviewStatus {\n // 1. Finalized takes precedence\n if (entry.finalDecision !== undefined && entry.finalDecision !== null) {\n return 'finalized';\n }\n\n // No reviews = pending (reviews can be null from YAML parsing with only comments)\n const reviews = entry.reviews ?? [];\n if (reviews.length === 0) {\n return 'pending';\n }\n\n // 3. Check for incomplete (registered reviewer missing)\n // Only check reviewers whose registered basis ≤ article's highest reviewed basis\n if (registeredReviewers && registeredReviewers.length > 0) {\n const reviewerNames = new Set(reviews.map((r) => r.reviewer));\n let highestReviewedRank = 0;\n for (const r of reviews) {\n highestReviewedRank = Math.max(highestReviewedRank, basisRank(r.basis));\n }\n // When reviews have no basis (legacy), check all registered reviewers\n const applicableReviewers = highestReviewedRank === 0\n ? registeredReviewers\n : registeredReviewers.filter(\n (reg) => basisRank(reg.basis) <= highestReviewedRank\n );\n const hasAllReviewers = applicableReviewers.every((reg) =>\n reviewerNames.has(reg.name)\n );\n if (applicableReviewers.length > 0 && !hasAllReviewers) {\n return 'incomplete';\n }\n }\n\n // Get reviews that have decisions\n const reviewsWithDecisions = reviews.filter((r) => r.decision !== undefined);\n\n if (reviewsWithDecisions.length === 0) {\n // All reviews lack a decision — treat as pending\n return 'pending';\n }\n\n // Basis-priority resolution:\n // \"uncertain\" at a lower basis means \"need more info\" (escalate).\n // A definitive decision at a higher basis resolves that uncertainty.\n //\n // Algorithm:\n // 1. Find the highest basis rank among all definitive (include/exclude) reviews\n // 2. For each reviewer, compute their effective decision:\n // - Take their highest-basis definitive decision if they have one\n // - Otherwise, keep uncertain only if their uncertain rank >= highest definitive rank\n // (i.e., no higher-basis definitive exists globally to resolve it)\n // 3. Reviewers whose only reviews are uncertain at a lower basis than the\n // highest global definitive are excluded from consensus (their uncertainty was resolved)\n\n // Find highest definitive basis rank across ALL reviews\n let highestDefinitiveRank = 0;\n for (const r of reviewsWithDecisions) {\n if (r.decision !== 'uncertain') {\n highestDefinitiveRank = Math.max(highestDefinitiveRank, basisRank(r.basis));\n }\n }\n\n // For each reviewer, compute effective decision\n const reviewerMap = new Map<string, { decision: ReviewDecision; rank: number }>();\n for (const r of reviewsWithDecisions) {\n const rank = basisRank(r.basis);\n const existing = reviewerMap.get(r.reviewer);\n if (!existing) {\n reviewerMap.set(r.reviewer, { decision: r.decision!, rank });\n } else {\n // Prefer definitive over uncertain\n if (r.decision !== 'uncertain' && existing.decision === 'uncertain') {\n reviewerMap.set(r.reviewer, { decision: r.decision!, rank });\n } else if (r.decision !== 'uncertain' && existing.decision !== 'uncertain' && rank > existing.rank) {\n // Higher-basis definitive overrides lower-basis definitive\n reviewerMap.set(r.reviewer, { decision: r.decision!, rank });\n } else if (r.decision === 'uncertain' && existing.decision === 'uncertain' && rank > existing.rank) {\n reviewerMap.set(r.reviewer, { decision: r.decision!, rank });\n }\n }\n }\n\n // Collect effective decisions, excluding reviewers whose effective decision\n // is at a lower basis than the highest global definitive\n const effectiveDecisions: ReviewDecision[] = [];\n for (const { decision, rank } of reviewerMap.values()) {\n if (rank < highestDefinitiveRank) {\n // This reviewer's decision is at a lower basis than the highest definitive — skip\n continue;\n }\n effectiveDecisions.push(decision);\n }\n\n if (effectiveDecisions.length === 0) {\n return 'pending';\n }\n\n // 4. Check for conflicts: both include and exclude present among effective decisions\n const hasInclude = effectiveDecisions.includes('include');\n const hasExclude = effectiveDecisions.includes('exclude');\n if (hasInclude && hasExclude) {\n return 'conflicting';\n }\n\n // 5. Any effective uncertain?\n const hasUncertain = effectiveDecisions.includes('uncertain');\n if (hasUncertain) {\n return 'uncertain';\n }\n\n // 6. All include?\n if (effectiveDecisions.every((d) => d === 'include')) {\n return 'agreed-include';\n }\n\n // 7. All exclude (only remaining possibility after ruling out conflicts and uncertain)\n return 'agreed-exclude';\n}\n"],"names":[],"mappings":"AAwHA,MAAM,aAAqC;AAAA,EACzC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,UAAU;AACZ;AAEO,SAAS,UAAU,OAAwC;AAChE,MAAI,UAAU,OAAW,QAAO;AAChC,SAAO,WAAW,KAAK,KAAK;AAC9B;AA0BO,SAAS,eACd,OACA,qBACc;AAEd,MAAI,MAAM,kBAAkB,UAAa,MAAM,kBAAkB,MAAM;AACrE,WAAO;AAAA,EACT;AAGA,QAAM,UAAU,MAAM,WAAW,CAAA;AACjC,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,EACT;AAIA,MAAI,uBAAuB,oBAAoB,SAAS,GAAG;AACzD,UAAM,gBAAgB,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;AAC5D,QAAI,sBAAsB;AAC1B,eAAW,KAAK,SAAS;AACvB,4BAAsB,KAAK,IAAI,qBAAqB,UAAU,EAAE,KAAK,CAAC;AAAA,IACxE;AAEA,UAAM,sBAAsB,wBAAwB,IAChD,sBACA,oBAAoB;AAAA,MAClB,CAAC,QAAQ,UAAU,IAAI,KAAK,KAAK;AAAA,IAAA;AAEvC,UAAM,kBAAkB,oBAAoB;AAAA,MAAM,CAAC,QACjD,cAAc,IAAI,IAAI,IAAI;AAAA,IAAA;AAE5B,QAAI,oBAAoB,SAAS,KAAK,CAAC,iBAAiB;AACtD,aAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,uBAAuB,QAAQ,OAAO,CAAC,MAAM,EAAE,aAAa,MAAS;AAE3E,MAAI,qBAAqB,WAAW,GAAG;AAErC,WAAO;AAAA,EACT;AAgBA,MAAI,wBAAwB;AAC5B,aAAW,KAAK,sBAAsB;AACpC,QAAI,EAAE,aAAa,aAAa;AAC9B,8BAAwB,KAAK,IAAI,uBAAuB,UAAU,EAAE,KAAK,CAAC;AAAA,IAC5E;AAAA,EACF;AAGA,QAAM,kCAAkB,IAAA;AACxB,aAAW,KAAK,sBAAsB;AACpC,UAAM,OAAO,UAAU,EAAE,KAAK;AAC9B,UAAM,WAAW,YAAY,IAAI,EAAE,QAAQ;AAC3C,QAAI,CAAC,UAAU;AACb,kBAAY,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAW,MAAM;AAAA,IAC7D,OAAO;AAEL,UAAI,EAAE,aAAa,eAAe,SAAS,aAAa,aAAa;AACnE,oBAAY,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAW,MAAM;AAAA,MAC7D,WAAW,EAAE,aAAa,eAAe,SAAS,aAAa,eAAe,OAAO,SAAS,MAAM;AAElG,oBAAY,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAW,MAAM;AAAA,MAC7D,WAAW,EAAE,aAAa,eAAe,SAAS,aAAa,eAAe,OAAO,SAAS,MAAM;AAClG,oBAAY,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAW,MAAM;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAIA,QAAM,qBAAuC,CAAA;AAC7C,aAAW,EAAE,UAAU,KAAA,KAAU,YAAY,UAAU;AACrD,QAAI,OAAO,uBAAuB;AAEhC;AAAA,IACF;AACA,uBAAmB,KAAK,QAAQ;AAAA,EAClC;AAEA,MAAI,mBAAmB,WAAW,GAAG;AACnC,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,mBAAmB,SAAS,SAAS;AACxD,QAAM,aAAa,mBAAmB,SAAS,SAAS;AACxD,MAAI,cAAc,YAAY;AAC5B,WAAO;AAAA,EACT;AAGA,QAAM,eAAe,mBAAmB,SAAS,WAAW;AAC5D,MAAI,cAAc;AAChB,WAAO;AAAA,EACT;AAGA,MAAI,mBAAmB,MAAM,CAAC,MAAM,MAAM,SAAS,GAAG;AACpD,WAAO;AAAA,EACT;AAGA,SAAO;AACT;"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAQA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqKpC;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAC;IACf,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAktEvC;AAED;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAG1C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAQA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqKpC;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAC;IACf,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CA0tEvC;AAED;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAG1C"}
package/dist/cli/index.js CHANGED
@@ -1647,6 +1647,13 @@ Examples:
1647
1647
  process.exitCode = EXIT_CODES.SESSION_ERROR;
1648
1648
  return;
1649
1649
  }
1650
+ if (!await sessionExists(sessionId, sessionsDir)) {
1651
+ if (!globalOpts.quiet) {
1652
+ console.error(`Error: session '${sessionId}' not found`);
1653
+ }
1654
+ process.exitCode = EXIT_CODES.SESSION_ERROR;
1655
+ return;
1656
+ }
1650
1657
  const sessionDir = join(sessionsDir, sessionId);
1651
1658
  const notes = await loadNotes(sessionDir);
1652
1659
  if (!globalOpts.quiet) {