scoutline 0.22.0 → 0.24.0

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 (325) hide show
  1. package/README.md +108 -26
  2. package/dist/capabilities/investigation.d.ts +134 -0
  3. package/dist/capabilities/investigation.d.ts.map +1 -0
  4. package/dist/capabilities/investigation.js +278 -0
  5. package/dist/capabilities/investigation.js.map +1 -0
  6. package/dist/capabilities/search.d.ts +18 -4
  7. package/dist/capabilities/search.d.ts.map +1 -1
  8. package/dist/commands/config.d.ts.map +1 -1
  9. package/dist/commands/config.js +14 -5
  10. package/dist/commands/config.js.map +1 -1
  11. package/dist/commands/crawl.d.ts.map +1 -1
  12. package/dist/commands/crawl.js +2 -1
  13. package/dist/commands/crawl.js.map +1 -1
  14. package/dist/commands/doctor.d.ts.map +1 -1
  15. package/dist/commands/doctor.js +2 -1
  16. package/dist/commands/doctor.js.map +1 -1
  17. package/dist/commands/init.d.ts +42 -1
  18. package/dist/commands/init.d.ts.map +1 -1
  19. package/dist/commands/init.js +42 -5
  20. package/dist/commands/init.js.map +1 -1
  21. package/dist/commands/investigate.d.ts +232 -0
  22. package/dist/commands/investigate.d.ts.map +1 -0
  23. package/dist/commands/investigate.js +838 -0
  24. package/dist/commands/investigate.js.map +1 -0
  25. package/dist/commands/map.d.ts.map +1 -1
  26. package/dist/commands/map.js +2 -1
  27. package/dist/commands/map.js.map +1 -1
  28. package/dist/commands/quota.d.ts.map +1 -1
  29. package/dist/commands/quota.js +2 -2
  30. package/dist/commands/quota.js.map +1 -1
  31. package/dist/commands/read.d.ts.map +1 -1
  32. package/dist/commands/read.js +2 -1
  33. package/dist/commands/read.js.map +1 -1
  34. package/dist/commands/repo.js +1 -1
  35. package/dist/commands/research.d.ts.map +1 -1
  36. package/dist/commands/research.js +2 -1
  37. package/dist/commands/research.js.map +1 -1
  38. package/dist/commands/search.d.ts +54 -6
  39. package/dist/commands/search.d.ts.map +1 -1
  40. package/dist/commands/search.js +273 -25
  41. package/dist/commands/search.js.map +1 -1
  42. package/dist/commands/vision.d.ts.map +1 -1
  43. package/dist/commands/vision.js +15 -2
  44. package/dist/commands/vision.js.map +1 -1
  45. package/dist/index.d.ts +93 -1
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +737 -14
  48. package/dist/index.js.map +1 -1
  49. package/dist/lib/code-mode.d.ts +12 -0
  50. package/dist/lib/code-mode.d.ts.map +1 -1
  51. package/dist/lib/code-mode.js +18 -10
  52. package/dist/lib/code-mode.js.map +1 -1
  53. package/dist/lib/config-store.d.ts +45 -1
  54. package/dist/lib/config-store.d.ts.map +1 -1
  55. package/dist/lib/config-store.js +70 -1
  56. package/dist/lib/config-store.js.map +1 -1
  57. package/dist/lib/config.d.ts.map +1 -1
  58. package/dist/lib/config.js +5 -1
  59. package/dist/lib/config.js.map +1 -1
  60. package/dist/lib/errors.d.ts +7 -1
  61. package/dist/lib/errors.d.ts.map +1 -1
  62. package/dist/lib/errors.js +8 -2
  63. package/dist/lib/errors.js.map +1 -1
  64. package/dist/lib/execution.d.ts +14 -5
  65. package/dist/lib/execution.d.ts.map +1 -1
  66. package/dist/lib/execution.js +25 -6
  67. package/dist/lib/execution.js.map +1 -1
  68. package/dist/lib/investigate-claims.d.ts +90 -0
  69. package/dist/lib/investigate-claims.d.ts.map +1 -0
  70. package/dist/lib/investigate-claims.js +188 -0
  71. package/dist/lib/investigate-claims.js.map +1 -0
  72. package/dist/lib/investigate-extract.d.ts +35 -0
  73. package/dist/lib/investigate-extract.d.ts.map +1 -0
  74. package/dist/lib/investigate-extract.js +101 -0
  75. package/dist/lib/investigate-extract.js.map +1 -0
  76. package/dist/lib/investigate-planner.d.ts +58 -0
  77. package/dist/lib/investigate-planner.d.ts.map +1 -0
  78. package/dist/lib/investigate-planner.js +141 -0
  79. package/dist/lib/investigate-planner.js.map +1 -0
  80. package/dist/lib/mcp-client.d.ts +7 -0
  81. package/dist/lib/mcp-client.d.ts.map +1 -1
  82. package/dist/lib/mcp-client.js +11 -1
  83. package/dist/lib/mcp-client.js.map +1 -1
  84. package/dist/lib/parse-zoned-instant.d.ts +13 -0
  85. package/dist/lib/parse-zoned-instant.d.ts.map +1 -0
  86. package/dist/lib/parse-zoned-instant.js +17 -0
  87. package/dist/lib/parse-zoned-instant.js.map +1 -0
  88. package/dist/lib/quota-mapping.d.ts +4 -2
  89. package/dist/lib/quota-mapping.d.ts.map +1 -1
  90. package/dist/lib/quota-mapping.js +25 -2
  91. package/dist/lib/quota-mapping.js.map +1 -1
  92. package/dist/lib/redact.d.ts +3 -2
  93. package/dist/lib/redact.d.ts.map +1 -1
  94. package/dist/lib/redact.js +90 -24
  95. package/dist/lib/redact.js.map +1 -1
  96. package/dist/lib/timeout.d.ts +28 -0
  97. package/dist/lib/timeout.d.ts.map +1 -0
  98. package/dist/lib/timeout.js +30 -0
  99. package/dist/lib/timeout.js.map +1 -0
  100. package/dist/lib/url.d.ts +10 -4
  101. package/dist/lib/url.d.ts.map +1 -1
  102. package/dist/lib/url.js +21 -6
  103. package/dist/lib/url.js.map +1 -1
  104. package/dist/providers/arxiv/client.d.ts +4 -1
  105. package/dist/providers/arxiv/client.d.ts.map +1 -1
  106. package/dist/providers/arxiv/client.js +11 -3
  107. package/dist/providers/arxiv/client.js.map +1 -1
  108. package/dist/providers/bocha/adapter.d.ts +43 -0
  109. package/dist/providers/bocha/adapter.d.ts.map +1 -0
  110. package/dist/providers/bocha/adapter.js +197 -0
  111. package/dist/providers/bocha/adapter.js.map +1 -0
  112. package/dist/providers/bocha/client.d.ts +51 -0
  113. package/dist/providers/bocha/client.d.ts.map +1 -0
  114. package/dist/providers/bocha/client.js +104 -0
  115. package/dist/providers/bocha/client.js.map +1 -0
  116. package/dist/providers/bocha/credentials.d.ts +12 -0
  117. package/dist/providers/bocha/credentials.d.ts.map +1 -0
  118. package/dist/providers/bocha/credentials.js +29 -0
  119. package/dist/providers/bocha/credentials.js.map +1 -0
  120. package/dist/providers/bocha/diagnostics.d.ts +17 -0
  121. package/dist/providers/bocha/diagnostics.d.ts.map +1 -0
  122. package/dist/providers/bocha/diagnostics.js +33 -0
  123. package/dist/providers/bocha/diagnostics.js.map +1 -0
  124. package/dist/providers/brave/adapter.d.ts.map +1 -1
  125. package/dist/providers/brave/adapter.js +4 -3
  126. package/dist/providers/brave/adapter.js.map +1 -1
  127. package/dist/providers/brave/client.d.ts +1 -0
  128. package/dist/providers/brave/client.d.ts.map +1 -1
  129. package/dist/providers/brave/client.js +4 -6
  130. package/dist/providers/brave/client.js.map +1 -1
  131. package/dist/providers/brave/credentials.d.ts +2 -0
  132. package/dist/providers/brave/credentials.d.ts.map +1 -1
  133. package/dist/providers/brave/credentials.js +2 -0
  134. package/dist/providers/brave/credentials.js.map +1 -1
  135. package/dist/providers/catalog.d.ts +34 -0
  136. package/dist/providers/catalog.d.ts.map +1 -0
  137. package/dist/providers/catalog.js +57 -0
  138. package/dist/providers/catalog.js.map +1 -0
  139. package/dist/providers/crossref/adapter.js +2 -2
  140. package/dist/providers/crossref/adapter.js.map +1 -1
  141. package/dist/providers/crossref/client.d.ts +4 -1
  142. package/dist/providers/crossref/client.d.ts.map +1 -1
  143. package/dist/providers/crossref/client.js +11 -3
  144. package/dist/providers/crossref/client.js.map +1 -1
  145. package/dist/providers/crossref/diagnostics.d.ts +1 -1
  146. package/dist/providers/crossref/diagnostics.js +1 -1
  147. package/dist/providers/crossref/diagnostics.js.map +1 -1
  148. package/dist/providers/europepmc/adapter.js +2 -2
  149. package/dist/providers/europepmc/adapter.js.map +1 -1
  150. package/dist/providers/europepmc/client.d.ts +4 -1
  151. package/dist/providers/europepmc/client.d.ts.map +1 -1
  152. package/dist/providers/europepmc/client.js +11 -3
  153. package/dist/providers/europepmc/client.js.map +1 -1
  154. package/dist/providers/exa/client.d.ts +1 -0
  155. package/dist/providers/exa/client.d.ts.map +1 -1
  156. package/dist/providers/exa/client.js +3 -2
  157. package/dist/providers/exa/client.js.map +1 -1
  158. package/dist/providers/exa/credentials.d.ts +2 -0
  159. package/dist/providers/exa/credentials.d.ts.map +1 -1
  160. package/dist/providers/exa/credentials.js +2 -0
  161. package/dist/providers/exa/credentials.js.map +1 -1
  162. package/dist/providers/firecrawl/adapter.d.ts.map +1 -1
  163. package/dist/providers/firecrawl/adapter.js +2 -1
  164. package/dist/providers/firecrawl/adapter.js.map +1 -1
  165. package/dist/providers/firecrawl/client.d.ts +1 -0
  166. package/dist/providers/firecrawl/client.d.ts.map +1 -1
  167. package/dist/providers/firecrawl/client.js +3 -2
  168. package/dist/providers/firecrawl/client.js.map +1 -1
  169. package/dist/providers/firecrawl/credentials.d.ts +2 -0
  170. package/dist/providers/firecrawl/credentials.d.ts.map +1 -1
  171. package/dist/providers/firecrawl/credentials.js +2 -0
  172. package/dist/providers/firecrawl/credentials.js.map +1 -1
  173. package/dist/providers/firecrawl/quota.d.ts.map +1 -1
  174. package/dist/providers/firecrawl/quota.js +5 -2
  175. package/dist/providers/firecrawl/quota.js.map +1 -1
  176. package/dist/providers/jina/adapter.d.ts.map +1 -1
  177. package/dist/providers/jina/adapter.js +6 -4
  178. package/dist/providers/jina/adapter.js.map +1 -1
  179. package/dist/providers/jina/client.d.ts +2 -0
  180. package/dist/providers/jina/client.d.ts.map +1 -1
  181. package/dist/providers/jina/client.js +6 -5
  182. package/dist/providers/jina/client.js.map +1 -1
  183. package/dist/providers/jina/credentials.d.ts +2 -0
  184. package/dist/providers/jina/credentials.d.ts.map +1 -1
  185. package/dist/providers/jina/credentials.js +2 -0
  186. package/dist/providers/jina/credentials.js.map +1 -1
  187. package/dist/providers/kagi/adapter.d.ts +44 -0
  188. package/dist/providers/kagi/adapter.d.ts.map +1 -0
  189. package/dist/providers/kagi/adapter.js +188 -0
  190. package/dist/providers/kagi/adapter.js.map +1 -0
  191. package/dist/providers/kagi/client.d.ts +41 -0
  192. package/dist/providers/kagi/client.d.ts.map +1 -0
  193. package/dist/providers/kagi/client.js +100 -0
  194. package/dist/providers/kagi/client.js.map +1 -0
  195. package/dist/providers/kagi/credentials.d.ts +15 -0
  196. package/dist/providers/kagi/credentials.d.ts.map +1 -0
  197. package/dist/providers/kagi/credentials.js +35 -0
  198. package/dist/providers/kagi/credentials.js.map +1 -0
  199. package/dist/providers/kagi/diagnostics.d.ts +17 -0
  200. package/dist/providers/kagi/diagnostics.d.ts.map +1 -0
  201. package/dist/providers/kagi/diagnostics.js +33 -0
  202. package/dist/providers/kagi/diagnostics.js.map +1 -0
  203. package/dist/providers/linkup/client.d.ts +1 -0
  204. package/dist/providers/linkup/client.d.ts.map +1 -1
  205. package/dist/providers/linkup/client.js +3 -2
  206. package/dist/providers/linkup/client.js.map +1 -1
  207. package/dist/providers/linkup/credentials.d.ts +2 -0
  208. package/dist/providers/linkup/credentials.d.ts.map +1 -1
  209. package/dist/providers/linkup/credentials.js +2 -0
  210. package/dist/providers/linkup/credentials.js.map +1 -1
  211. package/dist/providers/minimax/adapter.d.ts.map +1 -1
  212. package/dist/providers/minimax/adapter.js +2 -2
  213. package/dist/providers/minimax/adapter.js.map +1 -1
  214. package/dist/providers/minimax/coding-plan-client.d.ts +1 -0
  215. package/dist/providers/minimax/coding-plan-client.d.ts.map +1 -1
  216. package/dist/providers/minimax/coding-plan-client.js +3 -2
  217. package/dist/providers/minimax/coding-plan-client.js.map +1 -1
  218. package/dist/providers/minimax/quota-client.d.ts +1 -0
  219. package/dist/providers/minimax/quota-client.d.ts.map +1 -1
  220. package/dist/providers/minimax/quota-client.js +3 -2
  221. package/dist/providers/minimax/quota-client.js.map +1 -1
  222. package/dist/providers/openalex/client.d.ts +2 -0
  223. package/dist/providers/openalex/client.d.ts.map +1 -1
  224. package/dist/providers/openalex/client.js +10 -3
  225. package/dist/providers/openalex/client.js.map +1 -1
  226. package/dist/providers/openalex/diagnostics.d.ts +1 -1
  227. package/dist/providers/openalex/diagnostics.js +1 -1
  228. package/dist/providers/openalex/diagnostics.js.map +1 -1
  229. package/dist/providers/parallel/client.d.ts +1 -0
  230. package/dist/providers/parallel/client.d.ts.map +1 -1
  231. package/dist/providers/parallel/client.js +3 -2
  232. package/dist/providers/parallel/client.js.map +1 -1
  233. package/dist/providers/parallel/credentials.d.ts +2 -0
  234. package/dist/providers/parallel/credentials.d.ts.map +1 -1
  235. package/dist/providers/parallel/credentials.js +2 -0
  236. package/dist/providers/parallel/credentials.js.map +1 -1
  237. package/dist/providers/perplexity/client.d.ts +2 -0
  238. package/dist/providers/perplexity/client.d.ts.map +1 -1
  239. package/dist/providers/perplexity/client.js +5 -4
  240. package/dist/providers/perplexity/client.js.map +1 -1
  241. package/dist/providers/perplexity/credentials.d.ts +2 -0
  242. package/dist/providers/perplexity/credentials.d.ts.map +1 -1
  243. package/dist/providers/perplexity/credentials.js +2 -0
  244. package/dist/providers/perplexity/credentials.js.map +1 -1
  245. package/dist/providers/pubmed/client.d.ts +2 -0
  246. package/dist/providers/pubmed/client.d.ts.map +1 -1
  247. package/dist/providers/pubmed/client.js +10 -3
  248. package/dist/providers/pubmed/client.js.map +1 -1
  249. package/dist/providers/registry.d.ts.map +1 -1
  250. package/dist/providers/registry.js +10 -1
  251. package/dist/providers/registry.js.map +1 -1
  252. package/dist/providers/searchapi/adapter.d.ts +54 -0
  253. package/dist/providers/searchapi/adapter.d.ts.map +1 -0
  254. package/dist/providers/searchapi/adapter.js +310 -0
  255. package/dist/providers/searchapi/adapter.js.map +1 -0
  256. package/dist/providers/searchapi/client.d.ts +73 -0
  257. package/dist/providers/searchapi/client.d.ts.map +1 -0
  258. package/dist/providers/searchapi/client.js +196 -0
  259. package/dist/providers/searchapi/client.js.map +1 -0
  260. package/dist/providers/searchapi/credentials.d.ts +46 -0
  261. package/dist/providers/searchapi/credentials.d.ts.map +1 -0
  262. package/dist/providers/searchapi/credentials.js +71 -0
  263. package/dist/providers/searchapi/credentials.js.map +1 -0
  264. package/dist/providers/searchapi/diagnostics.d.ts +48 -0
  265. package/dist/providers/searchapi/diagnostics.d.ts.map +1 -0
  266. package/dist/providers/searchapi/diagnostics.js +70 -0
  267. package/dist/providers/searchapi/diagnostics.js.map +1 -0
  268. package/dist/providers/searchapi/quota.d.ts +60 -0
  269. package/dist/providers/searchapi/quota.d.ts.map +1 -0
  270. package/dist/providers/searchapi/quota.js +125 -0
  271. package/dist/providers/searchapi/quota.js.map +1 -0
  272. package/dist/providers/spider/client.d.ts +2 -0
  273. package/dist/providers/spider/client.d.ts.map +1 -1
  274. package/dist/providers/spider/client.js +16 -6
  275. package/dist/providers/spider/client.js.map +1 -1
  276. package/dist/providers/spider/credentials.d.ts +2 -0
  277. package/dist/providers/spider/credentials.d.ts.map +1 -1
  278. package/dist/providers/spider/credentials.js +2 -0
  279. package/dist/providers/spider/credentials.js.map +1 -1
  280. package/dist/providers/tavily/client.d.ts +1 -0
  281. package/dist/providers/tavily/client.d.ts.map +1 -1
  282. package/dist/providers/tavily/client.js +3 -2
  283. package/dist/providers/tavily/client.js.map +1 -1
  284. package/dist/providers/tavily/credentials.d.ts +2 -0
  285. package/dist/providers/tavily/credentials.d.ts.map +1 -1
  286. package/dist/providers/tavily/credentials.js +2 -0
  287. package/dist/providers/tavily/credentials.js.map +1 -1
  288. package/dist/providers/types.d.ts +31 -2
  289. package/dist/providers/types.d.ts.map +1 -1
  290. package/dist/providers/types.js +3 -0
  291. package/dist/providers/types.js.map +1 -1
  292. package/dist/providers/you/client.d.ts +4 -0
  293. package/dist/providers/you/client.d.ts.map +1 -1
  294. package/dist/providers/you/client.js +4 -5
  295. package/dist/providers/you/client.js.map +1 -1
  296. package/dist/providers/you/credentials.d.ts +2 -0
  297. package/dist/providers/you/credentials.d.ts.map +1 -1
  298. package/dist/providers/you/credentials.js +3 -3
  299. package/dist/providers/you/credentials.js.map +1 -1
  300. package/dist/providers/zai/adapter.d.ts.map +1 -1
  301. package/dist/providers/zai/adapter.js +219 -4
  302. package/dist/providers/zai/adapter.js.map +1 -1
  303. package/dist/providers/zai/credentials.d.ts +2 -0
  304. package/dist/providers/zai/credentials.d.ts.map +1 -1
  305. package/dist/providers/zai/credentials.js +2 -0
  306. package/dist/providers/zai/credentials.js.map +1 -1
  307. package/dist/providers/zai/layout-parsing.d.ts +76 -0
  308. package/dist/providers/zai/layout-parsing.d.ts.map +1 -0
  309. package/dist/providers/zai/layout-parsing.js +151 -0
  310. package/dist/providers/zai/layout-parsing.js.map +1 -0
  311. package/dist/providers/zai/media.d.ts +19 -0
  312. package/dist/providers/zai/media.d.ts.map +1 -1
  313. package/dist/providers/zai/media.js +61 -0
  314. package/dist/providers/zai/media.js.map +1 -1
  315. package/dist/providers/zai/monitor-client.d.ts +1 -0
  316. package/dist/providers/zai/monitor-client.d.ts.map +1 -1
  317. package/dist/providers/zai/monitor-client.js +3 -2
  318. package/dist/providers/zai/monitor-client.js.map +1 -1
  319. package/dist/providers/zai/quota.d.ts +4 -0
  320. package/dist/providers/zai/quota.d.ts.map +1 -1
  321. package/dist/providers/zai/quota.js +16 -1
  322. package/dist/providers/zai/quota.js.map +1 -1
  323. package/package.json +1 -1
  324. package/skills/scoutline/SKILL.md +163 -45
  325. package/skills/scoutline/references/advanced.md +12 -10
package/README.md CHANGED
@@ -21,7 +21,7 @@
21
21
  - **Repo** - Search and read GitHub repository code via ZRead
22
22
  - **Tools** - MCP tool discovery, schemas, and raw calls
23
23
  - **Code Mode** - TypeScript tool chaining for agent automation
24
- - **Provider selection** - Run shared capabilities through Z.AI, MiniMax, Tavily, Exa, Brave, Firecrawl, Parallel AI, Perplexity, Jina AI, You.com, Linkup, or Spider.cloud
24
+ - **Provider selection** - Run shared capabilities through Z.AI, MiniMax, Tavily, Exa, Brave, Firecrawl, Parallel AI, Perplexity, Jina AI, You.com, Linkup, Spider.cloud, Bocha AI, SearchApi.io, or Kagi
25
25
  - **Usage ledger** - Local 90-day call-usage history per provider and capability (`scoutline usage`), counters only
26
26
  - **Saved artifacts** - Durable clean reports from any provider-backed run (`--save`), content + request id only, plus a credential-free `scoutline history` inventory (list/show/stats/recall/export/note/clear)
27
27
  - **Research journal** - Always-on local memory of every `search`/`read`/`research` call: thin skeletons (query, provider, url+title identity, content hash) recorded under `~/.scoutline/artifacts/` and re-found offline via `history recall`; opt out per call (`--no-journal`) or globally (`journal: false`)
@@ -53,6 +53,30 @@ npx scoutline --provider brave search "AI policy news" --topic news
53
53
  npx scoutline --provider brave search "rust async" --type video
54
54
  ```
55
55
 
56
+ To use Bocha AI (Search and Diagnostics):
57
+
58
+ ```bash
59
+ export BOCHA_API_KEY="your-bocha-key"
60
+ npx scoutline --provider bocha search "AI policy news"
61
+ ```
62
+
63
+ Get your Bocha AI API key at: https://open.bochaai.com/
64
+
65
+ To use Kagi (Search and Diagnostics):
66
+
67
+ ```bash
68
+ export KAGI_API_KEY="your-kagi-key"
69
+ npx scoutline --provider kagi search "AI policy news"
70
+ npx scoutline --provider kagi search "AI policy" --topic news
71
+ npx scoutline doctor --provider kagi
72
+ ```
73
+
74
+ Kagi reads the key from `KAGI_API_KEY` (legacy alias `KAGI_TOKEN`).
75
+ Search rides `GET /api/v1/search` (`Authorization: Bot <key>`);
76
+ `--topic news` routes to `GET /api/v0/enrich/news`.
77
+
78
+ Get your Kagi API key at: https://kagi.com/settings/api
79
+
56
80
  ### Interactive Onboarding (`scoutline init`)
57
81
 
58
82
  Instead of exporting environment variables, run the interactive wizard to
@@ -63,7 +87,8 @@ scoutline init
63
87
  ```
64
88
 
65
89
  The wizard walks you through a registry-derived provider checklist
66
- (all 12 built-in Providers, rendered in registry order — equal
90
+ (all 20 built-in registry entries — 15 Providers plus the five science
91
+ suppliers — rendered in registry order — equal
67
92
  weight, none pre-checked), takes each key via
68
93
  hidden input, and performs a single inline validation probe against an
69
94
  ephemeral in-memory environment (the candidate key is never persisted or
@@ -142,9 +167,9 @@ npx scoutline --help
142
167
  ## Provider Selection
143
168
 
144
169
  Shared commands (`search`, `vision`, `quota`, `doctor`, `repo`) accept a global
145
- `--provider <zai|minimax|tavily|exa|brave|firecrawl|parallel|perplexity|jina|you|linkup|spider>` flag. Resolution precedence:
170
+ `--provider <zai|minimax|tavily|exa|brave|firecrawl|parallel|perplexity|jina|you|linkup|spider|bocha|searchapi|kagi>` flag. Resolution precedence:
146
171
 
147
- 1. Explicit `--provider <zai|minimax|tavily|exa|brave|firecrawl|parallel|perplexity|jina|you|linkup|spider>` on the command line
172
+ 1. Explicit `--provider <zai|minimax|tavily|exa|brave|firecrawl|parallel|perplexity|jina|you|linkup|spider|bocha|searchapi|kagi>` on the command line
148
173
  2. `SCOUTLINE_PROVIDER` environment variable
149
174
  3. Per-capability **routing table** (`config.json` `routing` key; the first
150
175
  configured, capable provider in the list wins — over quota ranking)
@@ -187,7 +212,7 @@ selected provider does not advertise the capability (for example,
187
212
  MiniMax does not advertise `repository-exploration` or `reader`) or
188
213
  fails at runtime, Scoutline emits a stderr notice and silently
189
214
  reroutes to the next eligible configured provider in registry order
190
- `[zai, minimax, tavily, exa, brave, firecrawl, parallel, perplexity, jina, you, linkup, spider, arxiv, openalex, crossref, pubmed, europepmc]`. Pass `--no-fallback`
215
+ `[zai, minimax, tavily, exa, brave, firecrawl, parallel, perplexity, jina, you, linkup, spider, bocha, searchapi, kagi, arxiv, openalex, crossref, pubmed, europepmc]`. Pass `--no-fallback`
191
216
  (or set `SCOUTLINE_NO_FALLBACK=1`) to restore the previous strict
192
217
  single-provider, fail-loud behavior for scripting or cost-sensitive
193
218
  workflows. See
@@ -238,6 +263,15 @@ every arm runs every sub-query and occurrences span the arms ×
238
263
  sub-queries grid. Disable the standing switch with
239
264
  `scoutline config set fanout false`.
240
265
 
266
+ **Ranking (fusion):** as of this release, merged lists — from fan-out
267
+ and from `--merge` — no longer rank by raw occurrence count but by
268
+ reciprocal rank fusion (Σ 1/(60 + rank) over every arm × sub-query
269
+ occurrence; each row carries a fixed 3-decimal `fusionScore`, and
270
+ near-duplicate cluster members travel on `clusterUrls`). If you need
271
+ the old order back, `scoutline config set fusion occurrence` restores
272
+ the pre-fusion ordering byte-for-byte (or set `SCOUTLINE_FUSION=occurrence`
273
+ per invocation; the config key is `fusion`, default `rrf`).
274
+
241
275
  ### Local Context (`--context` / `--context-stdin`)
242
276
 
243
277
  Steer `research` and `search` with a local notes file (markdown headings and
@@ -370,33 +404,34 @@ for the full contract.
370
404
  The matrix below is generated from the production provider registry
371
405
  (`packages/scoutline/src/providers/registry.ts`) and reflects the
372
406
  release-shipped capability advertisements; the registry order is
373
- `[zai, minimax, tavily, exa, brave, firecrawl, parallel, perplexity, jina, you, linkup, spider, arxiv, openalex, crossref, pubmed, europepmc]`.
407
+ `[zai, minimax, tavily, exa, brave, firecrawl, parallel, perplexity, jina, you, linkup, spider, bocha, searchapi, kagi, arxiv, openalex, crossref, pubmed, europepmc]`.
374
408
  The matrix columns cover the shared-capability providers — the five
375
409
  keyless science suppliers (arXiv, OpenAlex, Crossref, PubMed, Europe
376
410
  PMC) serve only `scoutline science ...` and `doctor` (see the Science
377
411
  section). The exact same `descriptor.capabilities()` set drives
378
412
  executor preflight, Provider selection, and `doctor`.
379
413
 
380
- | Capability | Z.AI | MiniMax | Tavily | Exa | Brave | Firecrawl | Parallel | Perplexity | Jina | You.com | Linkup | Spider.cloud | Notes |
381
- |---|---|---|---|---|---|---|---|---|---|---|---|---|---|
382
- | `search` | Yes | Yes | Yes | Yes | Yes (incl. `type: "video"`) | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Parallel (declarative semantic), Jina (neural web search) |
383
- | `vision.interpret-image` (analyze) | Yes | Yes | No | No | No | No | No | No | No | No | No | No | Provider-specific media limits; uncached |
384
- | `vision.ui-artifact` (ui-to-code) | Yes | Available | No | No | No | No | No | No | No | No | No | No | Live-attested; conformance-gated |
385
- | `vision.extract-text` | Yes | Pending | No | No | No | No | No | No | No | No | No | No | Implemented, pending live conformance |
386
- | `vision.diagnose-error` | Yes | Available | No | No | No | No | No | No | No | No | No | No | Live-attested; conformance-gated |
387
- | `vision.diagram` | Yes | Pending | No | No | No | No | No | No | No | No | No | No | Implemented, pending live conformance |
388
- | `vision.chart` | Yes | Pending | No | No | No | No | No | No | No | No | No | No | Implemented, pending live conformance |
389
- | `vision.diff` (image diff) | Yes | No | No | No | No | No | No | No | No | No | No | No | Z.AI-only (never MiniMax-claimable) |
390
- | `vision.video` | Yes | No | No | No | No | No | No | No | No | No | No | No | Z.AI-only (never MiniMax-claimable) |
391
- | `quota` | Yes | Yes | Yes | No | Yes | Yes (USD balance) | No | No | Yes (rate-limit telemetry, not spend) | No | Yes (credits) | Yes (credits) | Normalized `QuotaDashboard` (ADR-0001) |
392
- | `diagnostics` (`doctor`) | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Lists every Provider; probes configured |
393
- | `read` (Reader) | Yes | **No** | Yes | Yes | No | Yes | Yes | No | Yes | Yes | Yes | Yes | Parallel (Extract API), Jina, You.com, Linkup, and Spider.cloud add Reader support |
394
- | `crawl` | **No** | **No** | Yes | No | No | Yes (async) | No | No | No | No | No | Yes (sync) | Tavily sync; Firecrawl async (resumable after Ctrl-C) |
395
- | `map` | **No** | **No** | Yes | No | No | Yes | No | No | No | No | No | Yes | URL-set discovery; no per-page content |
396
- | `research` | **No** | **No** | Yes | Yes | **No** | **No** | Yes | Yes | Yes | Yes | Yes | No | Tavily, Exa, Parallel, Perplexity (Agent API `high` preset), Jina DeepSearch, You.com, and Linkup research report synthesis |
397
- | `repo search` / `repo read` / `repo tree` / `repo brief` | Yes | **No** | **No** | **No** | **No** | **No** | **No** | **No** | **No** | No | Participates in selection; only Z.AI supplies `repository-exploration` |
398
- | `tools`, `tool`, `call` (Raw tools) | Yes | No | No | No | No | No | No | No | No | No | Z.AI-only; accepts but ignores `--provider` |
399
- | `code` (Code Mode) | Yes | No | No | No | No | No | No | No | No | No | Z.AI-only; accepts but ignores `--provider` |
414
+ | Capability | Z.AI | MiniMax | Tavily | Exa | Brave | Firecrawl | Parallel | Perplexity | Jina AI | You.com | Linkup | Spider.cloud | Bocha AI | SearchApi | Kagi | Notes |
415
+ | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
416
+ | `search` | Yes | Yes | Yes | Yes | Yes (incl. `type: "video"`) | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Parallel (declarative semantic), Jina (neural web search) |
417
+ | `vision.interpret-image` (analyze) | Yes | Yes | No | No | No | No | No | No | No | No | No | No | No | No | No | Provider-specific media limits; uncached |
418
+ | `vision.ui-artifact` (ui-to-code) | Yes | Available | No | No | No | No | No | No | No | No | No | No | No | No | No | Live-attested; conformance-gated |
419
+ | `vision.extract-text` | Yes (GLM-OCR engine: PDF ≤50MB, images ≤10MB, content-hash cached; exhaustion falls back to the vision model) | Pending | No | No | No | No | No | No | No | No | No | No | No | No | No | Implemented, pending live conformance |
420
+ | `vision.diagnose-error` | Yes | Available | No | No | No | No | No | No | No | No | No | No | No | No | No | Live-attested; conformance-gated |
421
+ | `vision.diagram` | Yes | Pending | No | No | No | No | No | No | No | No | No | No | No | No | No | Implemented, pending live conformance |
422
+ | `vision.chart` | Yes | Pending | No | No | No | No | No | No | No | No | No | No | No | No | No | Implemented, pending live conformance |
423
+ | `vision.diff` (image diff) | Yes | No | No | No | No | No | No | No | No | No | No | No | No | No | No | Z.AI-only (never MiniMax-claimable) |
424
+ | `vision.video` | Yes | No | No | No | No | No | No | No | No | No | No | No | No | No | No | Z.AI-only (never MiniMax-claimable) |
425
+ | `quota` | Yes | Yes | Yes | No | Yes | Yes (USD balance) | No | No | Yes (rate-limit telemetry, not spend) | No | Yes (credits) | Yes (credits) | No | Yes (credits) | No | Normalized `QuotaDashboard` (ADR-0001) |
426
+ | `diagnostics` (`doctor`) | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Lists every Provider; probes configured |
427
+ | `read` (Reader) | Yes | **No** | Yes | Yes | No | Yes | Yes | No | Yes | Yes | Yes | Yes | No | **No** | No | Parallel (Extract API), Jina, You.com, Linkup, and Spider.cloud add Reader support |
428
+ | `crawl` | **No** | **No** | Yes | No | No | Yes (async) | No | No | No | No | No | Yes (sync) | No | **No** | No | Tavily sync; Firecrawl async (resumable after Ctrl-C) |
429
+ | `map` | **No** | **No** | Yes | No | No | Yes | No | No | No | No | No | Yes | No | **No** | No | URL-set discovery; no per-page content |
430
+ | `research` | **No** | **No** | Yes | Yes | **No** | **No** | Yes | Yes | Yes | Yes | Yes | No | No | **No** | No | Tavily, Exa, Parallel, Perplexity (Agent API `high` preset), Jina DeepSearch, You.com, and Linkup research report synthesis |
431
+ | `investigation` (EvidencePack) | Yes | **No** (no reader) | Yes | Yes | **No** (no reader) | Yes | Yes | **No** (no reader) | Yes | Yes | Yes | Yes | **No** (no reader) | **No** (no reader) | **No** (no reader) | Provider-composed — supplied by the search+reader supplier union (Z.AI, Tavily, Exa, Firecrawl, Parallel, Jina AI, You.com, Linkup, Spider.cloud); `--synthesize` is Z.AI-only |
432
+ | `repo search` / `repo read` / `repo tree` / `repo brief` | Yes | **No** | **No** | **No** | **No** | **No** | **No** | **No** | **No** | No | No | No | No | No | No | Participates in selection; only Z.AI supplies `repository-exploration` |
433
+ | `tools`, `tool`, `call` (Raw tools) | Yes | No | No | No | No | No | No | No | No | No | No | No | No | No | No | Z.AI-only; accepts but ignores `--provider` |
434
+ | `code` (Code Mode) | Yes | No | No | No | No | No | No | No | No | No | No | No | No | No | No | Z.AI-only; accepts but ignores `--provider` |
400
435
 
401
436
  Media limits for general single-image interpretation:
402
437
 
@@ -491,6 +526,53 @@ the supplier wire supports them (rejected with `UNSUPPORTED_OPTION`
491
526
  elsewhere — never silently dropped). `science get <identifier>` fetches
492
527
  one work by bare DOI, numeric PMID, or arXiv id.
493
528
 
529
+ ### Investigation (`investigate`)
530
+
531
+ `scoutline investigate <question>` runs a local, transparent,
532
+ cache-resumable pipeline ([ADR-0013](https://github.com/vikasagarwal101/scoutline/blob/main/docs/adr/0013-local-investigation-pipeline.md)):
533
+ plan sub-queries → fan-out search → Fusion merge → read the top
534
+ `--sources` (default 5) → deterministic passage extraction → an
535
+ EvidencePack (`schemaVersion` 1). No provider-side job runs — distinct
536
+ from Research, an opaque billed provider job. The pack is data, not
537
+ prose: agents consume it directly and text output modes fall back to
538
+ JSON (agent-synthesis is the default; you write the prose). Warm re-runs
539
+ replay the response cache (`coverage.cacheHits` reflects it).
540
+
541
+ ```bash
542
+ scoutline investigate "rust async runtime benchmarks"
543
+ scoutline investigate "rust async | rust tokio" # pipes split explicit sub-queries
544
+ scoutline investigate "topic" --provider tavily,exa --sources 8
545
+ scoutline investigate "topic" --max-chars 20000 --synthesize
546
+ ```
547
+
548
+ Sub-query planning precedence: explicit pipes (the `--merge` grammar) >
549
+ `--context <path>` (a local notes file — it never leaves the machine,
550
+ only the derived sub-query strings are searched) > deterministic
551
+ templates of the bare question (original, key terms,
552
+ overview/evidence/criticism; deduped, capped at 5). Provider selection
553
+ reuses search's fan-out activation tiers verbatim (comma-list/`all`
554
+ fan-out, single pin, `config set fanout true`). Cost is stated in one
555
+ stderr notice before any billable work: N sub-queries × M arms billable
556
+ searches + up to K reads.
557
+
558
+ Controls: `--sources <n>`, `--max-chars <n>` (passages trim first, late
559
+ sources drop; the full untrimmed pack is saved and recoverable via
560
+ `scoutline history show <ref>`), `--no-cache`, `--no-journal`, `--save`,
561
+ `--isolated`. Sources surfaced but unread land in `coverage.unread` with
562
+ a reason code — never silently dropped. `--synthesize` attaches an
563
+ additive `brief` via Z.AI chat (Z.AI-only; absent by default; a
564
+ synthesis failure is the run's terminal error, never a degraded pack).
565
+ `--depth`, `--arms`, and `--budget-tokens` are rejected with
566
+ `VALIDATION_ERROR` by design.
567
+
568
+ `--verify` turns the positional into a statement: sentence-claims
569
+ (≤ 8, fail-loud) are searched verbatim and matched to the extracted
570
+ passages; the pack gains an additive `verify` block — per claim, a
571
+ verdict (`corroborated` / `contradicted` / `unresolved`), evidence
572
+ pointers, and a negation-cue count. `contradicted` is a disclosed
573
+ negation-cue heuristic (hint-grade), not semantic judgment;
574
+ `--context` + `--verify` is a mode-conflict VALIDATION_ERROR.
575
+
494
576
  ## Usage
495
577
 
496
578
  The CLI is self-documenting. Use `--help` at any level:
@@ -0,0 +1,134 @@
1
+ /**
2
+ * EvidencePack schema + total decoder (T1, docs/plans/investigate-pipeline
3
+ * PRD AC-6; ADR-0013 §7).
4
+ *
5
+ * The EvidencePack is the self-contained deliverable of an Investigation
6
+ * (CONTEXT.md glossary): question, sub-queries, sources with per-source
7
+ * content hashes and extracted passages, and a coverage block. The pack is
8
+ * data, not prose — agent-synthesis is the contract; `--synthesize` (T7)
9
+ * attaches a `brief` additively and is not part of this schema.
10
+ *
11
+ * This module declares the pack type, its total decoder, and the
12
+ * contentSha256 shape predicate. It imports NOTHING from other src modules
13
+ * (self-contained by ticket contract; hashing itself lands in T5 — this
14
+ * module only validates hash *shape*).
15
+ *
16
+ * Decoder discipline mirrors capabilities/reader.ts exactly:
17
+ * - accepts `unknown`, returns the pack or `null`, never throws,
18
+ * never trusts a generic cast;
19
+ * - reject primitives and arrays at the top level;
20
+ * - `schemaVersion` MUST be the literal number 1 (rejects "1", 1.5,
21
+ * bigints, any future version);
22
+ * - `title: null` is a valid decoded value (reader parity);
23
+ * - optional fields preserved verbatim when present.
24
+ */
25
+ /** `[start, end)` character offsets into the source `content` string. */
26
+ export type CharRange = readonly [number, number];
27
+ /**
28
+ * One extracted passage. `quote` is pinned to the content by `charRange`:
29
+ * `content.slice(...charRange) === quote` for every passage (D4). The pin
30
+ * is enforced where content is available (assembly in T5, extraction in
31
+ * T3); the decoder enforces the shape so a decoded pack is at least
32
+ * structurally sound.
33
+ */
34
+ export interface EvidencePassage {
35
+ readonly quote: string;
36
+ readonly charRange: CharRange;
37
+ }
38
+ /** One read source: reader-envelope fields + passages. */
39
+ export interface EvidenceSource {
40
+ readonly url: string;
41
+ /** The URL the Reader actually fetched (provider rewrite possible). */
42
+ readonly finalUrl: string;
43
+ /** Page title if the provider returned one; `null` if absent (reader parity). */
44
+ readonly title: string | null;
45
+ /** ISO-8601 UTC Z timestamp captured when the read resolved (D5). */
46
+ readonly fetchedAt: string;
47
+ /** Provider id that surfaced the source (search-arm winner). */
48
+ readonly provider: string;
49
+ /** Mirrors the read `format`; `"markdown"` or `"text"`. */
50
+ readonly contentFormat: "markdown" | "text";
51
+ /** Lowercase hex SHA-256 of the UTF-8 normalized content string (D5). */
52
+ readonly contentSha256: string;
53
+ readonly passages: readonly EvidencePassage[];
54
+ }
55
+ /** Coverage block: how much of the planned grid actually produced evidence. */
56
+ export interface EvidenceCoverage {
57
+ /** Number of planned sub-queries. */
58
+ readonly subQueries: number;
59
+ /** Number of search arms actually used. */
60
+ readonly armsUsed: number;
61
+ /** Number of post-cluster candidate sources surfaced. */
62
+ readonly sourcesConsidered: number;
63
+ /** Number of sources whose read resolved successfully. */
64
+ readonly sourcesRead: number;
65
+ /** Count of search arms + reads served warm from cache (D5). */
66
+ readonly cacheHits: number;
67
+ /**
68
+ * Sources surfaced but not read, each with a reason code only —
69
+ * redacted, no error prose crossing the interface (house rule, D5).
70
+ */
71
+ readonly unread: readonly {
72
+ readonly url: string;
73
+ readonly reason: string;
74
+ }[];
75
+ }
76
+ /** The self-contained Investigation deliverable (PRD AC-6). */
77
+ export interface EvidencePack {
78
+ readonly schemaVersion: 1;
79
+ readonly question: string;
80
+ readonly subQueries: readonly string[];
81
+ readonly sources: readonly EvidenceSource[];
82
+ readonly coverage: EvidenceCoverage;
83
+ /**
84
+ * investigate-verify lane T2 (PRD AC-6): the additive claim-
85
+ * corroboration block. ABSENT on question-mode packs (byte-identity
86
+ * pin); present only when `investigate --verify` assembled the pack.
87
+ */
88
+ readonly verify?: VerifyBlock;
89
+ }
90
+ /** The deterministic verdict vocabulary (cue heuristic, PRD AC-5). */
91
+ export type ClaimVerdict = "corroborated" | "contradicted" | "unresolved";
92
+ /** One evidence pointer into the pack's own `sources` array. */
93
+ export interface ClaimEvidencePointer {
94
+ readonly sourceIndex: number;
95
+ readonly passageIndex: number;
96
+ }
97
+ /**
98
+ * One claim row: the claim text, its verdict, the count of cue-bearing
99
+ * matching passages (agent re-judgment input — the cue heuristic is
100
+ * DISCLOSED hint-grade), and first-encounter evidence pointers.
101
+ */
102
+ export interface ClaimRow {
103
+ readonly text: string;
104
+ readonly verdict: ClaimVerdict;
105
+ readonly negationCues: number;
106
+ readonly evidence: readonly ClaimEvidencePointer[];
107
+ }
108
+ /** The additive verify block: the statement plus one row per claim. */
109
+ export interface VerifyBlock {
110
+ readonly statement: string;
111
+ readonly claims: readonly ClaimRow[];
112
+ }
113
+ /**
114
+ * `contentSha256` validity: a 64-character lowercase hex string —
115
+ * the exact shape of `createHash("sha256")…digest("hex")` output.
116
+ * Ruling (ticket T1): hex-shape is enforced at decode, so an
117
+ * uppercased, truncated, or non-hex string fails closed. Full
118
+ * recompute-vs-content binding belongs to assembly (T5), which is the
119
+ * only place the paired content string exists.
120
+ */
121
+ export declare function isValidContentSha256(value: unknown): value is string;
122
+ /**
123
+ * Decode an `unknown` value into a canonical `EvidencePack`. Returns the
124
+ * typed pack on success, `null` for any malformed value. NEVER throws,
125
+ * NEVER trusts a generic cast.
126
+ *
127
+ * `title: null` is valid (reader parity). `sources` and `passages` may be
128
+ * empty arrays (a pack whose every read failed is still a valid, sad pack).
129
+ * `brief` (T7) is additive: unknown keys are NOT rejected — a decoded pack
130
+ * carries exactly the AC-6 keys, and an input carrying extra keys decodes
131
+ * to the canonical subset.
132
+ */
133
+ export declare function decodeInvestigationPack(value: unknown): EvidencePack | null;
134
+ //# sourceMappingURL=investigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"investigation.d.ts","sourceRoot":"","sources":["../../src/capabilities/investigation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,278 @@
1
+ /**
2
+ * EvidencePack schema + total decoder (T1, docs/plans/investigate-pipeline
3
+ * PRD AC-6; ADR-0013 §7).
4
+ *
5
+ * The EvidencePack is the self-contained deliverable of an Investigation
6
+ * (CONTEXT.md glossary): question, sub-queries, sources with per-source
7
+ * content hashes and extracted passages, and a coverage block. The pack is
8
+ * data, not prose — agent-synthesis is the contract; `--synthesize` (T7)
9
+ * attaches a `brief` additively and is not part of this schema.
10
+ *
11
+ * This module declares the pack type, its total decoder, and the
12
+ * contentSha256 shape predicate. It imports NOTHING from other src modules
13
+ * (self-contained by ticket contract; hashing itself lands in T5 — this
14
+ * module only validates hash *shape*).
15
+ *
16
+ * Decoder discipline mirrors capabilities/reader.ts exactly:
17
+ * - accepts `unknown`, returns the pack or `null`, never throws,
18
+ * never trusts a generic cast;
19
+ * - reject primitives and arrays at the top level;
20
+ * - `schemaVersion` MUST be the literal number 1 (rejects "1", 1.5,
21
+ * bigints, any future version);
22
+ * - `title: null` is a valid decoded value (reader parity);
23
+ * - optional fields preserved verbatim when present.
24
+ */
25
+ // ---------------------------------------------------------------------------
26
+ // Field predicates
27
+ // ---------------------------------------------------------------------------
28
+ function isPlainObject(value) {
29
+ return typeof value === "object" && value !== null && !Array.isArray(value);
30
+ }
31
+ function isNonEmptyString(value) {
32
+ return typeof value === "string" && value.length > 0;
33
+ }
34
+ function isFiniteNumber(value) {
35
+ return typeof value === "number" && Number.isFinite(value);
36
+ }
37
+ /**
38
+ * `contentSha256` validity: a 64-character lowercase hex string —
39
+ * the exact shape of `createHash("sha256")…digest("hex")` output.
40
+ * Ruling (ticket T1): hex-shape is enforced at decode, so an
41
+ * uppercased, truncated, or non-hex string fails closed. Full
42
+ * recompute-vs-content binding belongs to assembly (T5), which is the
43
+ * only place the paired content string exists.
44
+ */
45
+ export function isValidContentSha256(value) {
46
+ if (typeof value !== "string" || value.length !== 64)
47
+ return false;
48
+ for (const ch of value) {
49
+ const code = ch.charCodeAt(0);
50
+ const isDigit = code >= 48 && code <= 57;
51
+ const isLowerHex = (code >= 97 && code <= 102) || isDigit;
52
+ if (!isLowerHex)
53
+ return false;
54
+ }
55
+ return true;
56
+ }
57
+ // ---------------------------------------------------------------------------
58
+ // Total decoder
59
+ // ---------------------------------------------------------------------------
60
+ function decodeCharRange(value) {
61
+ // PR #264 F2: the documented `[start, end)` invariant, enforced at
62
+ // decode — safe integers, non-negative start, strictly increasing
63
+ // (an empty range cannot quote a non-empty passage).
64
+ return (Array.isArray(value) &&
65
+ value.length === 2 &&
66
+ Number.isSafeInteger(value[0]) &&
67
+ Number.isSafeInteger(value[1]) &&
68
+ value[0] >= 0 &&
69
+ value[1] > value[0]);
70
+ }
71
+ function decodePassage(value) {
72
+ if (!isPlainObject(value))
73
+ return null;
74
+ if (!isNonEmptyString(value.quote))
75
+ return null;
76
+ if (!decodeCharRange(value.charRange))
77
+ return null;
78
+ return { quote: value.quote, charRange: [value.charRange[0], value.charRange[1]] };
79
+ }
80
+ function decodeSource(value) {
81
+ if (!isPlainObject(value))
82
+ return null;
83
+ if (!isNonEmptyString(value.url))
84
+ return null;
85
+ if (!isNonEmptyString(value.finalUrl))
86
+ return null;
87
+ const title = value.title;
88
+ if (title !== null && typeof title !== "string")
89
+ return null;
90
+ if (!isNonEmptyString(value.fetchedAt))
91
+ return null;
92
+ if (!isNonEmptyString(value.provider))
93
+ return null;
94
+ if (value.contentFormat !== "markdown" && value.contentFormat !== "text")
95
+ return null;
96
+ if (!isValidContentSha256(value.contentSha256))
97
+ return null;
98
+ if (!Array.isArray(value.passages))
99
+ return null;
100
+ const passages = [];
101
+ for (const raw of value.passages) {
102
+ const passage = decodePassage(raw);
103
+ if (passage === null)
104
+ return null;
105
+ passages.push(passage);
106
+ }
107
+ return {
108
+ url: value.url,
109
+ finalUrl: value.finalUrl,
110
+ title: title,
111
+ fetchedAt: value.fetchedAt,
112
+ provider: value.provider,
113
+ contentFormat: value.contentFormat,
114
+ contentSha256: value.contentSha256,
115
+ passages,
116
+ };
117
+ }
118
+ function decodeCoverage(value) {
119
+ if (!isPlainObject(value))
120
+ return null;
121
+ if (!isFiniteNumber(value.subQueries))
122
+ return null;
123
+ if (!isFiniteNumber(value.armsUsed))
124
+ return null;
125
+ if (!isFiniteNumber(value.sourcesConsidered))
126
+ return null;
127
+ if (!isFiniteNumber(value.sourcesRead))
128
+ return null;
129
+ if (!isFiniteNumber(value.cacheHits))
130
+ return null;
131
+ if (!Array.isArray(value.unread))
132
+ return null;
133
+ const unread = [];
134
+ for (const raw of value.unread) {
135
+ if (!isPlainObject(raw))
136
+ return null;
137
+ if (!isNonEmptyString(raw.url))
138
+ return null;
139
+ if (!isNonEmptyString(raw.reason))
140
+ return null;
141
+ unread.push({ url: raw.url, reason: raw.reason });
142
+ }
143
+ return {
144
+ subQueries: value.subQueries,
145
+ armsUsed: value.armsUsed,
146
+ sourcesConsidered: value.sourcesConsidered,
147
+ sourcesRead: value.sourcesRead,
148
+ cacheHits: value.cacheHits,
149
+ unread,
150
+ };
151
+ }
152
+ /**
153
+ * Decode an `unknown` value into a canonical `EvidencePack`. Returns the
154
+ * typed pack on success, `null` for any malformed value. NEVER throws,
155
+ * NEVER trusts a generic cast.
156
+ *
157
+ * `title: null` is valid (reader parity). `sources` and `passages` may be
158
+ * empty arrays (a pack whose every read failed is still a valid, sad pack).
159
+ * `brief` (T7) is additive: unknown keys are NOT rejected — a decoded pack
160
+ * carries exactly the AC-6 keys, and an input carrying extra keys decodes
161
+ * to the canonical subset.
162
+ */
163
+ export function decodeInvestigationPack(value) {
164
+ // PR #264 F1: total containment for the never-throws contract — a
165
+ // throwing getter or Proxy trap on untrusted input must surface as
166
+ // a fail-closed null, never as an exception out of the decoder.
167
+ try {
168
+ return decodeInvestigationPackInner(value);
169
+ }
170
+ catch {
171
+ return null;
172
+ }
173
+ }
174
+ function decodeInvestigationPackInner(value) {
175
+ if (!isPlainObject(value))
176
+ return null;
177
+ if (value.schemaVersion !== 1)
178
+ return null;
179
+ if (!isNonEmptyString(value.question))
180
+ return null;
181
+ if (!Array.isArray(value.subQueries))
182
+ return null;
183
+ for (const q of value.subQueries) {
184
+ if (!isNonEmptyString(q))
185
+ return null;
186
+ }
187
+ if (!Array.isArray(value.sources))
188
+ return null;
189
+ const sources = [];
190
+ for (const raw of value.sources) {
191
+ const source = decodeSource(raw);
192
+ if (source === null)
193
+ return null;
194
+ sources.push(source);
195
+ }
196
+ const coverage = decodeCoverage(value.coverage);
197
+ if (coverage === null)
198
+ return null;
199
+ // investigate-verify lane T2 (D4): additive-optional `verify` — absent
200
+ // keeps the canonical subset (question-mode byte identity); present is
201
+ // validated row-by-row and fails closed on any malformed row.
202
+ const verify = decodeVerifyBlock(value.verify, sources.length, (sourceIndex) => sources[sourceIndex] === undefined ? 0 : sources[sourceIndex].passages.length);
203
+ if (verify === undefined)
204
+ return null;
205
+ return {
206
+ schemaVersion: 1,
207
+ question: value.question,
208
+ subQueries: [...value.subQueries],
209
+ sources,
210
+ coverage,
211
+ ...(verify !== null ? { verify } : {}),
212
+ };
213
+ }
214
+ const CLAIM_VERDICTS = ["corroborated", "contradicted", "unresolved"];
215
+ /**
216
+ * Decode the additive verify block. `undefined` = malformed (the caller
217
+ * fails closed); `null` = absent (the canonical subset stands); the
218
+ * decoded block = present + valid.
219
+ *
220
+ * PR #270 babysit: pointer RANGE is cross-checked against the decoded
221
+ * sources of the SAME pack (sourceIndex < sourceCount; passageIndex <
222
+ * that source's passage count) — a shape-safe but out-of-range pointer
223
+ * is malformed, INCLUDING any pointer into a zero-source pack (it can
224
+ * never dereference; assembly emits empty evidence there by
225
+ * construction, so only hand-built input reaches that arm).
226
+ */
227
+ function decodeVerifyBlock(value, sourceCount, passageCountAt) {
228
+ if (value === undefined)
229
+ return null;
230
+ if (!isPlainObject(value))
231
+ return undefined;
232
+ if (!isNonEmptyString(value.statement))
233
+ return undefined;
234
+ if (!Array.isArray(value.claims))
235
+ return undefined;
236
+ const claims = [];
237
+ for (const raw of value.claims) {
238
+ if (!isPlainObject(raw))
239
+ return undefined;
240
+ if (!isNonEmptyString(raw.text))
241
+ return undefined;
242
+ if (typeof raw.verdict !== "string" || !CLAIM_VERDICTS.includes(raw.verdict)) {
243
+ return undefined;
244
+ }
245
+ if (typeof raw.negationCues !== "number" ||
246
+ !Number.isSafeInteger(raw.negationCues) ||
247
+ raw.negationCues < 0) {
248
+ return undefined;
249
+ }
250
+ if (!Array.isArray(raw.evidence))
251
+ return undefined;
252
+ const evidence = [];
253
+ for (const pointer of raw.evidence) {
254
+ if (!isPlainObject(pointer))
255
+ return undefined;
256
+ if (!isSafeIndex(pointer.sourceIndex) || !isSafeIndex(pointer.passageIndex)) {
257
+ return undefined;
258
+ }
259
+ if (pointer.sourceIndex >= sourceCount ||
260
+ pointer.passageIndex >= passageCountAt(pointer.sourceIndex)) {
261
+ return undefined;
262
+ }
263
+ evidence.push({ sourceIndex: pointer.sourceIndex, passageIndex: pointer.passageIndex });
264
+ }
265
+ claims.push({
266
+ text: raw.text,
267
+ verdict: raw.verdict,
268
+ negationCues: raw.negationCues,
269
+ evidence,
270
+ });
271
+ }
272
+ return { statement: value.statement, claims };
273
+ }
274
+ /** Finite, safe, non-negative integer index (evidence pointer guard). */
275
+ function isSafeIndex(value) {
276
+ return (typeof value === "number" && Number.isSafeInteger(value) && value >= 0);
277
+ }
278
+ //# sourceMappingURL=investigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"investigation.js","sourceRoot":"","sources":["../../src/capabilities/investigation.ts"],"names":[],"mappings":"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"}