scoutline 0.19.7 → 0.21.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 (270) hide show
  1. package/README.md +131 -25
  2. package/bin/scoutline.js +0 -0
  3. package/dist/capabilities/map.d.ts +3 -3
  4. package/dist/capabilities/map.js +3 -3
  5. package/dist/capabilities/quota.d.ts +13 -6
  6. package/dist/capabilities/quota.d.ts.map +1 -1
  7. package/dist/capabilities/quota.js +15 -0
  8. package/dist/capabilities/quota.js.map +1 -1
  9. package/dist/capabilities/science.d.ts +193 -0
  10. package/dist/capabilities/science.d.ts.map +1 -0
  11. package/dist/capabilities/science.js +110 -0
  12. package/dist/capabilities/science.js.map +1 -0
  13. package/dist/command-invocation.d.ts +13 -1
  14. package/dist/command-invocation.d.ts.map +1 -1
  15. package/dist/command-invocation.js +44 -2
  16. package/dist/command-invocation.js.map +1 -1
  17. package/dist/commands/archive.d.ts +178 -0
  18. package/dist/commands/archive.d.ts.map +1 -0
  19. package/dist/commands/archive.js +871 -0
  20. package/dist/commands/archive.js.map +1 -0
  21. package/dist/commands/config.d.ts.map +1 -1
  22. package/dist/commands/config.js +12 -3
  23. package/dist/commands/config.js.map +1 -1
  24. package/dist/commands/crawl.d.ts +15 -2
  25. package/dist/commands/crawl.d.ts.map +1 -1
  26. package/dist/commands/crawl.js +93 -34
  27. package/dist/commands/crawl.js.map +1 -1
  28. package/dist/commands/doctor.d.ts +8 -0
  29. package/dist/commands/doctor.d.ts.map +1 -1
  30. package/dist/commands/doctor.js +40 -5
  31. package/dist/commands/doctor.js.map +1 -1
  32. package/dist/commands/fetch.d.ts +75 -0
  33. package/dist/commands/fetch.d.ts.map +1 -0
  34. package/dist/commands/fetch.js +596 -0
  35. package/dist/commands/fetch.js.map +1 -0
  36. package/dist/commands/history.d.ts +165 -8
  37. package/dist/commands/history.d.ts.map +1 -1
  38. package/dist/commands/history.js +591 -20
  39. package/dist/commands/history.js.map +1 -1
  40. package/dist/commands/init.d.ts +13 -0
  41. package/dist/commands/init.d.ts.map +1 -1
  42. package/dist/commands/init.js +411 -43
  43. package/dist/commands/init.js.map +1 -1
  44. package/dist/commands/map.d.ts.map +1 -1
  45. package/dist/commands/map.js +5 -0
  46. package/dist/commands/map.js.map +1 -1
  47. package/dist/commands/quota.d.ts.map +1 -1
  48. package/dist/commands/quota.js +2 -0
  49. package/dist/commands/quota.js.map +1 -1
  50. package/dist/commands/read.d.ts +28 -6
  51. package/dist/commands/read.d.ts.map +1 -1
  52. package/dist/commands/read.js +328 -31
  53. package/dist/commands/read.js.map +1 -1
  54. package/dist/commands/repo.d.ts +12 -10
  55. package/dist/commands/repo.d.ts.map +1 -1
  56. package/dist/commands/repo.js +189 -21
  57. package/dist/commands/repo.js.map +1 -1
  58. package/dist/commands/repository-explorer.d.ts +15 -7
  59. package/dist/commands/repository-explorer.d.ts.map +1 -1
  60. package/dist/commands/repository-explorer.js +117 -97
  61. package/dist/commands/repository-explorer.js.map +1 -1
  62. package/dist/commands/research.d.ts +21 -4
  63. package/dist/commands/research.d.ts.map +1 -1
  64. package/dist/commands/research.js +83 -12
  65. package/dist/commands/research.js.map +1 -1
  66. package/dist/commands/science.d.ts +54 -0
  67. package/dist/commands/science.d.ts.map +1 -0
  68. package/dist/commands/science.js +999 -0
  69. package/dist/commands/science.js.map +1 -0
  70. package/dist/commands/search.d.ts +13 -2
  71. package/dist/commands/search.d.ts.map +1 -1
  72. package/dist/commands/search.js +106 -7
  73. package/dist/commands/search.js.map +1 -1
  74. package/dist/commands/watch.d.ts +94 -0
  75. package/dist/commands/watch.d.ts.map +1 -0
  76. package/dist/commands/watch.js +900 -0
  77. package/dist/commands/watch.js.map +1 -0
  78. package/dist/index.d.ts +168 -4
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +1679 -232
  81. package/dist/index.js.map +1 -1
  82. package/dist/lib/agent-registration/deploy.d.ts +69 -0
  83. package/dist/lib/agent-registration/deploy.d.ts.map +1 -0
  84. package/dist/lib/agent-registration/deploy.js +279 -0
  85. package/dist/lib/agent-registration/deploy.js.map +1 -0
  86. package/dist/lib/agent-registration/engines.d.ts +77 -0
  87. package/dist/lib/agent-registration/engines.d.ts.map +1 -0
  88. package/dist/lib/agent-registration/engines.js +544 -0
  89. package/dist/lib/agent-registration/engines.js.map +1 -0
  90. package/dist/lib/agent-registration/registry.d.ts +32 -0
  91. package/dist/lib/agent-registration/registry.d.ts.map +1 -0
  92. package/dist/lib/agent-registration/registry.js +94 -0
  93. package/dist/lib/agent-registration/registry.js.map +1 -0
  94. package/dist/lib/api-client.d.ts +2 -3
  95. package/dist/lib/api-client.d.ts.map +1 -1
  96. package/dist/lib/api-client.js +18 -0
  97. package/dist/lib/api-client.js.map +1 -1
  98. package/dist/lib/artifacts.d.ts +83 -3
  99. package/dist/lib/artifacts.d.ts.map +1 -1
  100. package/dist/lib/artifacts.js +246 -13
  101. package/dist/lib/artifacts.js.map +1 -1
  102. package/dist/lib/async-file-lock.d.ts +19 -9
  103. package/dist/lib/async-file-lock.d.ts.map +1 -1
  104. package/dist/lib/async-file-lock.js +25 -11
  105. package/dist/lib/async-file-lock.js.map +1 -1
  106. package/dist/lib/batch-manifest.d.ts +1 -0
  107. package/dist/lib/batch-manifest.d.ts.map +1 -1
  108. package/dist/lib/batch-manifest.js +12 -5
  109. package/dist/lib/batch-manifest.js.map +1 -1
  110. package/dist/lib/batch-runner.d.ts.map +1 -1
  111. package/dist/lib/batch-runner.js +25 -0
  112. package/dist/lib/batch-runner.js.map +1 -1
  113. package/dist/lib/code-mode.d.ts +19 -0
  114. package/dist/lib/code-mode.d.ts.map +1 -1
  115. package/dist/lib/code-mode.js +170 -14
  116. package/dist/lib/code-mode.js.map +1 -1
  117. package/dist/lib/config-store.d.ts +48 -1
  118. package/dist/lib/config-store.d.ts.map +1 -1
  119. package/dist/lib/config-store.js +92 -5
  120. package/dist/lib/config-store.js.map +1 -1
  121. package/dist/lib/config.js +3 -3
  122. package/dist/lib/config.js.map +1 -1
  123. package/dist/lib/errors.d.ts +20 -0
  124. package/dist/lib/errors.d.ts.map +1 -1
  125. package/dist/lib/errors.js +26 -0
  126. package/dist/lib/errors.js.map +1 -1
  127. package/dist/lib/journal.d.ts +258 -0
  128. package/dist/lib/journal.d.ts.map +1 -0
  129. package/dist/lib/journal.js +582 -0
  130. package/dist/lib/journal.js.map +1 -0
  131. package/dist/lib/mcp-client.d.ts +18 -0
  132. package/dist/lib/mcp-client.d.ts.map +1 -1
  133. package/dist/lib/mcp-client.js +145 -17
  134. package/dist/lib/mcp-client.js.map +1 -1
  135. package/dist/lib/output-budget-persistence.d.ts +76 -0
  136. package/dist/lib/output-budget-persistence.d.ts.map +1 -0
  137. package/dist/lib/output-budget-persistence.js +76 -0
  138. package/dist/lib/output-budget-persistence.js.map +1 -0
  139. package/dist/lib/output-budget.d.ts +99 -0
  140. package/dist/lib/output-budget.d.ts.map +1 -0
  141. package/dist/lib/output-budget.js +175 -0
  142. package/dist/lib/output-budget.js.map +1 -0
  143. package/dist/lib/pdf.d.ts +22 -0
  144. package/dist/lib/pdf.d.ts.map +1 -0
  145. package/dist/lib/pdf.js +1213 -0
  146. package/dist/lib/pdf.js.map +1 -0
  147. package/dist/lib/provider-fallback.d.ts.map +1 -1
  148. package/dist/lib/provider-fallback.js +3 -0
  149. package/dist/lib/provider-fallback.js.map +1 -1
  150. package/dist/lib/quota-mapping.d.ts.map +1 -1
  151. package/dist/lib/quota-mapping.js +31 -0
  152. package/dist/lib/quota-mapping.js.map +1 -1
  153. package/dist/lib/quota-store.d.ts +11 -1
  154. package/dist/lib/quota-store.d.ts.map +1 -1
  155. package/dist/lib/quota-store.js +11 -2
  156. package/dist/lib/quota-store.js.map +1 -1
  157. package/dist/lib/redact.d.ts.map +1 -1
  158. package/dist/lib/redact.js +18 -8
  159. package/dist/lib/redact.js.map +1 -1
  160. package/dist/lib/save-artifacts.d.ts +38 -0
  161. package/dist/lib/save-artifacts.d.ts.map +1 -0
  162. package/dist/lib/save-artifacts.js +146 -0
  163. package/dist/lib/save-artifacts.js.map +1 -0
  164. package/dist/lib/section-diff.d.ts +90 -0
  165. package/dist/lib/section-diff.d.ts.map +1 -0
  166. package/dist/lib/section-diff.js +395 -0
  167. package/dist/lib/section-diff.js.map +1 -0
  168. package/dist/lib/skill-source.d.ts +11 -0
  169. package/dist/lib/skill-source.d.ts.map +1 -0
  170. package/dist/lib/skill-source.js +22 -0
  171. package/dist/lib/skill-source.js.map +1 -0
  172. package/dist/lib/tty.d.ts +1 -1
  173. package/dist/lib/tty.d.ts.map +1 -1
  174. package/dist/lib/tty.js +10 -1
  175. package/dist/lib/tty.js.map +1 -1
  176. package/dist/lib/watch-store.d.ts +203 -0
  177. package/dist/lib/watch-store.d.ts.map +1 -0
  178. package/dist/lib/watch-store.js +628 -0
  179. package/dist/lib/watch-store.js.map +1 -0
  180. package/dist/providers/arxiv/adapter.d.ts +88 -0
  181. package/dist/providers/arxiv/adapter.d.ts.map +1 -0
  182. package/dist/providers/arxiv/adapter.js +316 -0
  183. package/dist/providers/arxiv/adapter.js.map +1 -0
  184. package/dist/providers/arxiv/client.d.ts +33 -0
  185. package/dist/providers/arxiv/client.d.ts.map +1 -0
  186. package/dist/providers/arxiv/client.js +130 -0
  187. package/dist/providers/arxiv/client.js.map +1 -0
  188. package/dist/providers/arxiv/diagnostics.d.ts +28 -0
  189. package/dist/providers/arxiv/diagnostics.d.ts.map +1 -0
  190. package/dist/providers/arxiv/diagnostics.js +34 -0
  191. package/dist/providers/arxiv/diagnostics.js.map +1 -0
  192. package/dist/providers/crossref/adapter.d.ts +97 -0
  193. package/dist/providers/crossref/adapter.d.ts.map +1 -0
  194. package/dist/providers/crossref/adapter.js +249 -0
  195. package/dist/providers/crossref/adapter.js.map +1 -0
  196. package/dist/providers/crossref/client.d.ts +10 -0
  197. package/dist/providers/crossref/client.d.ts.map +1 -0
  198. package/dist/providers/crossref/client.js +143 -0
  199. package/dist/providers/crossref/client.js.map +1 -0
  200. package/dist/providers/crossref/diagnostics.d.ts +18 -0
  201. package/dist/providers/crossref/diagnostics.d.ts.map +1 -0
  202. package/dist/providers/crossref/diagnostics.js +23 -0
  203. package/dist/providers/crossref/diagnostics.js.map +1 -0
  204. package/dist/providers/europepmc/adapter.d.ts +94 -0
  205. package/dist/providers/europepmc/adapter.d.ts.map +1 -0
  206. package/dist/providers/europepmc/adapter.js +264 -0
  207. package/dist/providers/europepmc/adapter.js.map +1 -0
  208. package/dist/providers/europepmc/client.d.ts +18 -0
  209. package/dist/providers/europepmc/client.d.ts.map +1 -0
  210. package/dist/providers/europepmc/client.js +128 -0
  211. package/dist/providers/europepmc/client.js.map +1 -0
  212. package/dist/providers/europepmc/diagnostics.d.ts +18 -0
  213. package/dist/providers/europepmc/diagnostics.d.ts.map +1 -0
  214. package/dist/providers/europepmc/diagnostics.js +23 -0
  215. package/dist/providers/europepmc/diagnostics.js.map +1 -0
  216. package/dist/providers/openalex/adapter.d.ts +53 -0
  217. package/dist/providers/openalex/adapter.d.ts.map +1 -0
  218. package/dist/providers/openalex/adapter.js +313 -0
  219. package/dist/providers/openalex/adapter.js.map +1 -0
  220. package/dist/providers/openalex/client.d.ts +18 -0
  221. package/dist/providers/openalex/client.d.ts.map +1 -0
  222. package/dist/providers/openalex/client.js +159 -0
  223. package/dist/providers/openalex/client.js.map +1 -0
  224. package/dist/providers/openalex/diagnostics.d.ts +19 -0
  225. package/dist/providers/openalex/diagnostics.d.ts.map +1 -0
  226. package/dist/providers/openalex/diagnostics.js +25 -0
  227. package/dist/providers/openalex/diagnostics.js.map +1 -0
  228. package/dist/providers/perplexity/adapter.d.ts +10 -8
  229. package/dist/providers/perplexity/adapter.d.ts.map +1 -1
  230. package/dist/providers/perplexity/adapter.js +68 -41
  231. package/dist/providers/perplexity/adapter.js.map +1 -1
  232. package/dist/providers/perplexity/client.d.ts +22 -12
  233. package/dist/providers/perplexity/client.d.ts.map +1 -1
  234. package/dist/providers/perplexity/client.js +18 -17
  235. package/dist/providers/perplexity/client.js.map +1 -1
  236. package/dist/providers/pubmed/adapter.d.ts +56 -0
  237. package/dist/providers/pubmed/adapter.d.ts.map +1 -0
  238. package/dist/providers/pubmed/adapter.js +425 -0
  239. package/dist/providers/pubmed/adapter.js.map +1 -0
  240. package/dist/providers/pubmed/client.d.ts +29 -0
  241. package/dist/providers/pubmed/client.d.ts.map +1 -0
  242. package/dist/providers/pubmed/client.js +153 -0
  243. package/dist/providers/pubmed/client.js.map +1 -0
  244. package/dist/providers/pubmed/diagnostics.d.ts +18 -0
  245. package/dist/providers/pubmed/diagnostics.d.ts.map +1 -0
  246. package/dist/providers/pubmed/diagnostics.js +23 -0
  247. package/dist/providers/pubmed/diagnostics.js.map +1 -0
  248. package/dist/providers/registry.d.ts.map +1 -1
  249. package/dist/providers/registry.js +16 -0
  250. package/dist/providers/registry.js.map +1 -1
  251. package/dist/providers/selection.d.ts +1 -1
  252. package/dist/providers/selection.d.ts.map +1 -1
  253. package/dist/providers/selection.js +5 -2
  254. package/dist/providers/selection.js.map +1 -1
  255. package/dist/providers/types.d.ts +28 -7
  256. package/dist/providers/types.d.ts.map +1 -1
  257. package/dist/providers/types.js +94 -6
  258. package/dist/providers/types.js.map +1 -1
  259. package/dist/providers/zai/quota.d.ts.map +1 -1
  260. package/dist/providers/zai/quota.js +29 -8
  261. package/dist/providers/zai/quota.js.map +1 -1
  262. package/dist/providers/zai/reader.d.ts.map +1 -1
  263. package/dist/providers/zai/reader.js +5 -3
  264. package/dist/providers/zai/reader.js.map +1 -1
  265. package/dist/providers/zai/repository.d.ts.map +1 -1
  266. package/dist/providers/zai/repository.js +5 -3
  267. package/dist/providers/zai/repository.js.map +1 -1
  268. package/package.json +3 -2
  269. package/skills/scoutline/SKILL.md +787 -0
  270. package/skills/scoutline/references/advanced.md +469 -0
package/README.md CHANGED
@@ -15,7 +15,7 @@
15
15
 
16
16
  ## Features
17
17
 
18
- - **Vision** - Analyze images, screenshots, diagrams, charts, videos using GLM-5V-Turbo
18
+ - **Vision** - Analyze images, screenshots, diagrams, charts, videos using GLM-5.3-Flash
19
19
  - **Search** - Real-time web search with domain and recency filtering
20
20
  - **Reader** - Fetch and parse web pages to markdown
21
21
  - **Repo** - Search and read GitHub repository code via ZRead
@@ -23,7 +23,8 @@
23
23
  - **Code Mode** - TypeScript tool chaining for agent automation
24
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
25
25
  - **Usage ledger** - Local 90-day call-usage history per provider and capability (`scoutline usage`), counters only
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)
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
+ - **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`)
27
28
 
28
29
  ## Quick Start
29
30
 
@@ -80,6 +81,35 @@ imported env key will keep overriding the saved key.
80
81
 
81
82
  Run `scoutline init --help` for the full lifecycle and exit-code reference.
82
83
 
84
+ ### Agent Registration
85
+
86
+ During `scoutline init`, every agent tool detected under your home directory
87
+ (claude, opencode, codex, gemini, qwen, copilot) gets a confirm prompt
88
+ (default yes) to register scoutline. Registering writes two things per tool:
89
+
90
+ - a **thin rules file** (always loaded — identity, one-line capability
91
+ surface, and a pointer to the full skill), and
92
+ - the **full agent skill** copied into that tool's native skills home.
93
+
94
+ Choices persist to the additive `agentRules` config key; undetected tools
95
+ never prompt, and a version or rule-text drift triggers a silent lazy
96
+ refresh on the next CLI run (no re-prompt). Every shared-file mutation is
97
+ idempotent, atomic, and byte-preserving outside the managed region.
98
+
99
+ Reversal is first-class:
100
+
101
+ ```bash
102
+ scoutline init --unregister
103
+ ```
104
+
105
+ It removes owned rule files and skill copies, strips pointer lines, marker
106
+ blocks, and JSON array entries in place, clears the stamp and `agentRules`
107
+ config key, and deletes the per-file `.scoutline-bak` backups. Those
108
+ backups are a **disaster recovery** escape hatch only — minted once on the
109
+ first mutation of a pre-existing file so you can manually recover if an
110
+ engine bug ever corrupts a file. Unregister never restores from them: your
111
+ own edits to shared files are preserved byte-for-byte by region stripping.
112
+
83
113
  ## Installation
84
114
 
85
115
  ### As an Agent Skill
@@ -157,7 +187,7 @@ selected provider does not advertise the capability (for example,
157
187
  MiniMax does not advertise `repository-exploration` or `reader`) or
158
188
  fails at runtime, Scoutline emits a stderr notice and silently
159
189
  reroutes to the next eligible configured provider in registry order
160
- `[zai, minimax, tavily, exa, brave, firecrawl, parallel, perplexity, jina, you, linkup, spider]`. Pass `--no-fallback`
190
+ `[zai, minimax, tavily, exa, brave, firecrawl, parallel, perplexity, jina, you, linkup, spider, arxiv, openalex, crossref, pubmed, europepmc]`. Pass `--no-fallback`
161
191
  (or set `SCOUTLINE_NO_FALLBACK=1`) to restore the previous strict
162
192
  single-provider, fail-loud behavior for scripting or cost-sensitive
163
193
  workflows. See
@@ -252,14 +282,58 @@ output is byte-identical to previous releases.
252
282
 
253
283
  Any provider-backed command (`search`, `read`, `crawl`, `map`, `research`, `repo`, `vision`) accepts `--save [<path>]`: after a successful run it writes a durable **clean report** — content plus a request id, nothing else — while stdout stays byte-identical. The master copy always lands in the artifact store (`~/.scoutline/artifacts/`, override `SCOUTLINE_ARTIFACTS_DIR`); `--save <path>` additionally writes an export copy (refused on an existing target unless `--save-force`). Reports are redacted through the same seam as stdout and never touched by `cache clear` or TTLs. `scoutline history list/show/stats` is the credential-free, fail-open inventory over the store's `index.json` metadata log, joined to reports by request id.
254
284
 
285
+ ### Research Journal (always-on, local-only)
286
+
287
+ Every `search`, `read`, and `research` call — batch-driven ops included —
288
+ appends a thin **journal entry** to the same store: query, provider,
289
+ timestamp, a content hash, and the **skeleton** of the result (search:
290
+ url+title list; read: url+title; research: citations). Result bodies are
291
+ never recorded — they live in the 24h response cache or in an explicit
292
+ `--save` artifact — and a warm repeat (cache hit) appends only a tiny
293
+ **repeat marker**, unless the journal holds no prior full entry under
294
+ that cache key (journal-cold, e.g. after `history clear`), in which case
295
+ the hit records a full entry instead. Entries are self-contained forever:
296
+ `cache clear` never
297
+ touches them and nothing is ever re-fetched. Journaling changes no
298
+ provider-call volume; savings come from using `history recall` instead of
299
+ re-running searches.
300
+
301
+ ```bash
302
+ scoutline history recall "rust async" # offline re-find over skeletons
303
+ scoutline history recall "rust" --capability search --limit 5
304
+ scoutline history recall "state of ai" --as-of 2026-08-01 # what the journal knew then
305
+ scoutline history note --capability search "decided on tavily for finance" # explicit entry
306
+ scoutline history export # markdown dossier, provenance-cited
307
+ scoutline history list --kind journal # journal entries only; --repeats shows markers
308
+ scoutline history clear # clears journal entries only
309
+ scoutline history clear --all # also wipes --save artifacts + masters
310
+ ```
311
+
312
+ **Privacy**: the journal is local-only (`~/.scoutline/artifacts/` — the
313
+ directory is created 0700 and the files inside 0600, never uploaded), and
314
+ query text passes the configured-secrets redaction seam before it is written. Disclosure is one prompt in
315
+ `scoutline init` (default: enabled, writing `"journal": true`); users who
316
+ never run init get the enabled default too. Escape hatches: `--no-journal`
317
+ on any single `search`/`read`/`research` call (rejected as
318
+ `UNSUPPORTED_OPTION` everywhere else), `scoutline config set journal false`
319
+ (or the init re-config menu) to stop entirely.
320
+
321
+ Scale note: the journal shares `index.json` with `--save` and appends
322
+ rewrite the whole log under a write lock. Measured appends stay well under
323
+ 100ms through ~20k entries; segmented-log/compaction is the named future
324
+ policy for larger journals.
325
+
255
326
  ## Capability Matrix
256
327
 
257
328
  The matrix below is generated from the production provider registry
258
329
  (`packages/scoutline/src/providers/registry.ts`) and reflects the
259
- release-shipped capability advertisements for every built-in provider
260
- in registry order `[zai, minimax, tavily, exa, brave, firecrawl, parallel, perplexity, jina, you, linkup, spider]`. The
261
- exact same `descriptor.capabilities()` set drives executor preflight,
262
- Provider selection, and `doctor`.
330
+ release-shipped capability advertisements; the registry order is
331
+ `[zai, minimax, tavily, exa, brave, firecrawl, parallel, perplexity, jina, you, linkup, spider, arxiv, openalex, crossref, pubmed, europepmc]`.
332
+ The matrix columns cover the shared-capability providers — the five
333
+ keyless science suppliers (arXiv, OpenAlex, Crossref, PubMed, Europe
334
+ PMC) serve only `scoutline science ...` and `doctor` (see the Science
335
+ section). The exact same `descriptor.capabilities()` set drives
336
+ executor preflight, Provider selection, and `doctor`.
263
337
 
264
338
  | Capability | Z.AI | MiniMax | Tavily | Exa | Brave | Firecrawl | Parallel | Perplexity | Jina | You.com | Linkup | Spider.cloud | Notes |
265
339
  |---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -277,7 +351,7 @@ Provider selection, and `doctor`.
277
351
  | `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 |
278
352
  | `crawl` | **No** | **No** | Yes | No | No | Yes (async) | No | No | No | No | No | Yes (sync) | Tavily sync; Firecrawl async (resumable after Ctrl-C) |
279
353
  | `map` | **No** | **No** | Yes | No | No | Yes | No | No | No | No | No | Yes | URL-set discovery; no per-page content |
280
- | `research` | **No** | **No** | Yes | Yes | **No** | **No** | Yes | Yes | Yes | Yes | Yes | No | Tavily, Exa, Parallel, Perplexity `sonar-deep-research`, Jina DeepSearch, You.com, and Linkup research report synthesis |
354
+ | `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 |
281
355
  | `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` |
282
356
  | `tools`, `tool`, `call` (Raw tools) | Yes | No | No | No | No | No | No | No | No | No | Z.AI-only; accepts but ignores `--provider` |
283
357
  | `code` (Code Mode) | Yes | No | No | No | No | No | No | No | No | No | Z.AI-only; accepts but ignores `--provider` |
@@ -355,6 +429,26 @@ from the same registry, so once a mapping is promoted it appears on
355
429
  every runtime surface automatically — there is no second support list
356
430
  to update.
357
431
 
432
+ ## Science
433
+
434
+ Keyless scholarly literature search and retrieval across five suppliers —
435
+ arXiv, OpenAlex, Crossref, PubMed, and Europe PMC. No API key is required:
436
+ the command dispatches credential-free (optional `OPENALEX_API_KEY` /
437
+ `NCBI_API_KEY` unlock higher rate limits).
438
+
439
+ ```bash
440
+ scoutline science search "graph transformers" --year 2020:2024
441
+ scoutline science search "attention" --author Vaswani --provider crossref
442
+ scoutline science get 10.1038/nature12373
443
+ ```
444
+
445
+ `science search <query>` fans out across all five suppliers by default
446
+ (`--provider <id>` pins one) and merges a deduplicated work list, with
447
+ `--author`, `--year`, `--venue`, and `--type` filters consumed only where
448
+ the supplier wire supports them (rejected with `UNSUPPORTED_OPTION`
449
+ elsewhere — never silently dropped). `science get <identifier>` fetches
450
+ one work by bare DOI, numeric PMID, or arXiv id.
451
+
358
452
  ## Usage
359
453
 
360
454
  The CLI is self-documenting. Use `--help` at any level:
@@ -368,7 +462,7 @@ scoutline doctor --help # Provider diagnostics
368
462
  scoutline quota --help # Plan usage
369
463
  scoutline cache --help # Local cache inspection, clearing, and pruning
370
464
  scoutline usage --help # Local call-usage history (usage.json ledger)
371
- scoutline history --help # Saved-artifact inventory (list/show/stats)
465
+ scoutline history --help # Saved artifacts + research journal (list/show/stats/recall/export/note/clear)
372
466
  ```
373
467
 
374
468
  ### Examples
@@ -391,6 +485,7 @@ scoutline search "security news" --recency oneDay
391
485
  # Reader - fetch web content
392
486
  scoutline read https://docs.example.com/api
393
487
  scoutline read https://blog.example.com --format text
488
+ scoutline read https://example.com/long-article --max-chars 2000
394
489
 
395
490
  # Repo - GitHub exploration
396
491
  scoutline repo tree facebook/react
@@ -428,6 +523,11 @@ scoutline search "rust vs go" --save --save-format markdown # master only
428
523
  scoutline history list --limit 5 # newest saves, from the log
429
524
  scoutline history show 20260829T142233Z-7f3a # metadata + report, joined
430
525
 
526
+ # Research journal - recall past work instead of re-searching (offline)
527
+ scoutline history recall "rust async" --limit 5 # scored re-find over skeletons
528
+ scoutline history export # cited markdown dossier
529
+ scoutline search "rust async" --no-journal # skip journaling one call
530
+
431
531
  # Config - inspect and change settings (scriptable, always redacted)
432
532
  scoutline config get # full config dump (credentials masked)
433
533
  scoutline config set routing.search tavily,brave
@@ -503,7 +603,7 @@ payload — the summary is presentation-only.
503
603
  healthy-first row ordering never changes exit codes. `--available` filters
504
604
  the `providers` array to the `availability: "ok"` rows; the
505
605
  `availableProviders` summary is unchanged by the filter.
506
- - `read` returns a schema-version-1 envelope (content read or extract read) in every output mode. `--with-images-summary`, `--no-gfm`, and `--keep-img-data-url` are passed through to the Provider request. `--max-chars` is ignored on extract reads; `--full-envelope` is silently deprecated.
606
+ - `read` returns a schema-version-1 envelope (content read or extract read) in every output mode. `--with-images-summary`, `--no-gfm`, and `--keep-img-data-url` are passed through to the Provider request. `--max-chars` is a whole-envelope budget on both shapes (extract reads trim field values only); `--full-envelope` is silently deprecated.
507
607
  - Vision tool calls automatically retry transient 5xx/network errors (default: 2 retries). Configure with `ZAI_MCP_VISION_RETRY_COUNT` (or `ZAI_MCP_RETRY_COUNT` for all tools).
508
608
  - Tool discovery can be cached to speed `tools`/`tool`/`doctor` (default: on, 24h TTL). The cache shares the unified root with the response cache; configure both via `SCOUTLINE_CACHE`, `SCOUTLINE_CACHE_TTL_MS`, `SCOUTLINE_CACHE_SIZE_MB`, and `SCOUTLINE_CACHE_DIR` (legacy aliases `ZAI_MCP_TOOL_CACHE*`, `ZAI_MCP_CACHE_DIR`, and `ZAI_CACHE*` are accepted silently).
509
609
  - The local cache lives at `~/.scoutline/` (`cache/` for responses, `tools/` for tool discovery) on every platform. Inspect, clear, or prune it with `scoutline cache stats`, `scoutline cache clear`, and `scoutline cache prune`. Prune deletes expired entries by their stored timestamp (`--older-than <24h|90m|30s|seconds>` replaces the TTL threshold; `--provider`/`--capability` narrow the response scan to v2 filenames — the tool cache is unpartitioned and is always scanned age-only).
@@ -553,21 +653,26 @@ legacy grammar; it is not wrapped in the v1 envelope.
553
653
  - Actual `.`/`..` segments, backslashes, and ASCII control characters are
554
654
  rejected. Percent escapes (`%XX`) are never decoded — they remain literal.
555
655
 
556
- ### `--max-chars` (deterministic, local)
656
+ ### `--max-chars` (Output Budget, deterministic and local)
557
657
 
558
658
  `--max-chars` is **never** a summarization model call. It is presentation
559
- projection applied to the normalized result after caching.
560
-
561
- - Absent, zero, or negative → no truncation.
562
- - `repo read` truncates `content` with the existing ellipsis rule; preserves
563
- the original length in `originalContentLength` and sets `truncated: true`.
564
- - `repo search` applies **one total budget** across `excerpts[].text` in
565
- Provider order; the final retained excerpt is truncated and later excerpts
566
- are omitted.
567
- - `repo tree` never character-limited.
568
- - `repo brief` → forwarded verbatim to every search and read call (per-call
569
- budget); the tree probe is never character-limited.
570
- - Metadata, JSON envelopes, and Tree snapshots are not part of the budget.
659
+ projection applied to the normalized result after caching: "fit everything
660
+ this command prints in ~N characters" (ADR-0007).
661
+
662
+ - Absent, zero, or negative no budget.
663
+ - `repo read` whole-envelope budget; `content` trims and later sections
664
+ drop late, repository/path never cut; preserves the original length in
665
+ `originalContentLength` and sets `truncated: true`.
666
+ - `repo search` → whole-envelope budget; excerpts trim, trailing excerpts
667
+ drop; URLs are never cut.
668
+ - `repo tree` → **rejects** the flag (`UNSUPPORTED_OPTION`).
669
+ - `repo brief` → applied **once** to the assembled brief envelope (never
670
+ forwarded per-probe); README excerpts and file bodies trim, file inventory
671
+ drops late, repository name and structure summary never cut.
672
+ - When the budget fires, the payload gains a `compaction` field and the full
673
+ untrimmed envelope is saved to the artifacts store — recover with
674
+ `scoutline history show <ref>`.
675
+ - Metadata and JSON envelopes are never part of the ladder's cut order.
571
676
 
572
677
  ### Empty results
573
678
 
@@ -681,8 +786,9 @@ always structured data.
681
786
  **Scripting impact:** any consumer that did `scoutline read URL > file.md`,
682
787
  `scoutline read URL | jq -r .content`, or `scoutline read URL --extract code |
683
788
  jq -c .[]` against v0.2 output must switch to the v1 envelope. `--max-chars`
684
- still truncates the content-read `content`; it is **ignored on extract reads**
685
- (extract reports `originalItemCount` instead). The deprecated
789
+ is a whole-envelope Output Budget on both shapes; on extract reads it trims
790
+ field values only (never drops field names or URLs; extract reports
791
+ `originalItemCount`). The deprecated
686
792
  `--full-envelope` flag is silently accepted and ignored — the envelope is
687
793
  always returned at v1.
688
794
 
package/bin/scoutline.js CHANGED
File without changes
@@ -10,9 +10,9 @@
10
10
  * selection, retries, or presentation.
11
11
  *
12
12
  * Map is the simplest of the three new Tavily capabilities: the API
13
- * returns URLs only (no per-page content), so there is no per-page
14
- * projection or truncation concern. The handler therefore needs no
15
- * `--max-chars` flag.
13
+ * returns URLs only (no per-page content), so Map is not an Output
14
+ * Budget ladder surface the dispatcher rejects `--max-chars` there
15
+ * (UNSUPPORTED_OPTION).
16
16
  */
17
17
  import type { CacheIdentity, CachedOperation } from "../lib/execution.js";
18
18
  /**
@@ -10,9 +10,9 @@
10
10
  * selection, retries, or presentation.
11
11
  *
12
12
  * Map is the simplest of the three new Tavily capabilities: the API
13
- * returns URLs only (no per-page content), so there is no per-page
14
- * projection or truncation concern. The handler therefore needs no
15
- * `--max-chars` flag.
13
+ * returns URLs only (no per-page content), so Map is not an Output
14
+ * Budget ladder surface the dispatcher rejects `--max-chars` there
15
+ * (UNSUPPORTED_OPTION).
16
16
  */
17
17
  // ===========================================================================
18
18
  // Total normalized cache decoder
@@ -22,6 +22,11 @@
22
22
  * `used` alongside the explicit percentage; `limit` and `remaining`
23
23
  * are omitted rather than fabricated. Additive under QuotaDashboard
24
24
  * schema v1.
25
+ * - A Provider whose counts are invalid but which publishes an exact
26
+ * `remaining` (e.g. Z.AI's cumulative `currentValue` past the
27
+ * window cap — GitHub #109) has `remaining` published verbatim next
28
+ * to any explicit remaining percentage; counts are omitted rather
29
+ * than derived from contradicting fields.
25
30
  * - Invalid optional counts are omitted together (not set to zero).
26
31
  * - A category that has neither a valid percentage, nor valid counts,
27
32
  * nor an explicit remaining is rejected with `QUOTA_ERROR`.
@@ -168,12 +173,14 @@ export interface QuotaWindowInputs {
168
173
  */
169
174
  explicitRemainingPercent?: number;
170
175
  /**
171
- * A Provider-supplied EXACT remaining count for a window whose limit
172
- * is unknown (GitHub #49). Used only when neither an explicit
173
- * percentage nor a valid count set is present: the built window
174
- * carries `remaining` verbatim and omits `used`, `limit`, and
175
- * `remainingPercent` nothing is inferred from tier tables or
176
- * fabricated as a percentage.
176
+ * A Provider-supplied EXACT remaining count. Two distinct uses:
177
+ * (GitHub #49) a window whose limit is unknown and neither an
178
+ * explicit percentage nor a valid count set is present the built
179
+ * window carries `remaining` verbatim and omits `used`, `limit`, and
180
+ * `remainingPercent`; and (GitHub #109) a window whose counts are
181
+ * invalid `remaining` is published verbatim next to any explicit
182
+ * remaining percentage, counts omitted. Nothing is ever inferred
183
+ * from tier tables or fabricated as a percentage.
177
184
  */
178
185
  remaining?: number;
179
186
  }
@@ -1 +1 @@
1
- {"version":3,"file":"quota.d.ts","sourceRoot":"","sources":["../../src/capabilities/quota.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"quota.d.ts","sourceRoot":"","sources":["../../src/capabilities/quota.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,11 @@
22
22
  * `used` alongside the explicit percentage; `limit` and `remaining`
23
23
  * are omitted rather than fabricated. Additive under QuotaDashboard
24
24
  * schema v1.
25
+ * - A Provider whose counts are invalid but which publishes an exact
26
+ * `remaining` (e.g. Z.AI's cumulative `currentValue` past the
27
+ * window cap — GitHub #109) has `remaining` published verbatim next
28
+ * to any explicit remaining percentage; counts are omitted rather
29
+ * than derived from contradicting fields.
25
30
  * - Invalid optional counts are omitted together (not set to zero).
26
31
  * - A category that has neither a valid percentage, nor valid counts,
27
32
  * nor an explicit remaining is rejected with `QUOTA_ERROR`.
@@ -145,6 +150,16 @@ export function buildQuotaWindow(inputs) {
145
150
  // count) before #99.
146
151
  window.used = inputs.used;
147
152
  }
153
+ else if (typeof inputs.remaining === "number" &&
154
+ Number.isFinite(inputs.remaining) &&
155
+ inputs.remaining >= 0) {
156
+ // Invalid counts but a Provider-published EXACT remaining count
157
+ // (e.g. Z.AI cumulative currentValue > cap): publish `remaining`
158
+ // verbatim next to any explicit percentage; never derive counts.
159
+ // Ordered after the #99 used-only path so every pre-existing
160
+ // accepting input keeps its exact pre-#109 shape.
161
+ window.remaining = inputs.remaining;
162
+ }
148
163
  if (isFinitePositive(inputs.durationSeconds)) {
149
164
  window.durationSeconds = inputs.durationSeconds;
150
165
  }
@@ -1 +1 @@
1
- {"version":3,"file":"quota.js","sourceRoot":"","sources":["../../src/capabilities/quota.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"quota.js","sourceRoot":"","sources":["../../src/capabilities/quota.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Science Capability Contract (DESIGN D1; PRD AC-10d).
3
+ *
4
+ * One capability file, house shape mirroring `search.ts`. Declares the
5
+ * Provider-neutral meaning shared by every science supplier: the control
6
+ * record, search/get request shapes, the normalized `ScienceWork` result,
7
+ * the supplier-partitioned cache identity, and the three capability
8
+ * interfaces (search/get/cite). This ticket ships ONLY the contract — no
9
+ * Provider, transport, or Adapter code lives here.
10
+ *
11
+ * Interfaces are compile-time only, so the validate() grammars are
12
+ * implemented as exported pure helpers (`validateScienceSearchRequest`,
13
+ * `validateScienceGetRequest`, `parseScienceIdentifier`) that the
14
+ * interfaces' validate() methods delegate to.
15
+ *
16
+ * Scope rulings encoded here:
17
+ * - `year` accepts ONLY the closed forms "2020" | "2018:2022"
18
+ * (PRD AC-7/AC-7b). Empty, malformed, and reversed ranges throw.
19
+ * - The shared validator judges ONLY `query` + `year`. `author`,
20
+ * `venue`, and `type` pass through unjudged — per-control
21
+ * accept/reject is the Adapter concern, and the `--type` union
22
+ * vocabulary (including `component` rejection) lives at command
23
+ * parse, never here.
24
+ * - Identifier grammar is BARE forms only: DOI `^10\.\d{4,9}/`,
25
+ * numeric PMID, arXiv `\d{4}\.\d{4,5}` plus the legacy
26
+ * `archive/number` form (e.g. `cs/0501001`). A `doi:` prefix is not
27
+ * one of the closed forms. Parsed once at the command layer.
28
+ */
29
+ /**
30
+ * The five science supplier ids, in the design listing order. This is the
31
+ * PROVIDER_IDS insertion order, NOT the fan-out arm order (the
32
+ * openalex-first arm ordering is an executor concern).
33
+ */
34
+ export declare const SCIENCE_SUPPLIER_IDS: readonly [
35
+ "arxiv",
36
+ "openalex",
37
+ "crossref",
38
+ "pubmed",
39
+ "europepmc"
40
+ ];
41
+ /** A science supplier id. */
42
+ export type ScienceSupplierId = (typeof SCIENCE_SUPPLIER_IDS)[number];
43
+ /**
44
+ * Science search controls. Every field is optional. The shared validator
45
+ * judges only `year`; `author`/`venue`/`type` are Adapter-mapped and pass
46
+ * through unjudged at this layer.
47
+ */
48
+ export interface ScienceControls {
49
+ /** Author filter; wire-consumed by openalex, crossref, pubmed. */
50
+ author?: string;
51
+ /** Closed forms only: "2020" | "2018:2022" (PRD AC-7/AC-7b). */
52
+ year?: string;
53
+ /** Venue filter; openalex and crossref native. */
54
+ venue?: string;
55
+ /** Content type; every supplier carries its own vocabulary. */
56
+ type?: string;
57
+ }
58
+ /**
59
+ * A science search request. `query` must contain at least one
60
+ * non-whitespace character; `validate` throws `ValidationError`
61
+ * otherwise.
62
+ */
63
+ export interface ScienceSearchRequest {
64
+ query: string;
65
+ controls?: Readonly<ScienceControls>;
66
+ }
67
+ /**
68
+ * A science get request. `identifier` must be one of the bare closed
69
+ * forms (DOI, numeric PMID, arXiv id — see `parseScienceIdentifier`).
70
+ */
71
+ export interface ScienceGetRequest {
72
+ identifier: string;
73
+ }
74
+ /**
75
+ * Normalized science work. Adapters populate this from their supplier
76
+ * response; commands merge, deduplicate, project, and present
77
+ * downstream. Supplier-only fields are discarded. Every field except
78
+ * `title` and `url` is optional — suppliers differ in coverage (e.g.
79
+ * Crossref lacks abstracts; arXiv serves preprints only).
80
+ */
81
+ export interface ScienceWork {
82
+ title: string;
83
+ url: string;
84
+ /** Persistent identifiers as supplied by the responding source. */
85
+ identifiers?: {
86
+ doi?: string;
87
+ pmid?: string;
88
+ arxivId?: string;
89
+ };
90
+ authors?: string[];
91
+ year?: number;
92
+ venue?: string;
93
+ /** Abstract; absent when the supplier carries none. */
94
+ summary?: string;
95
+ citationCount?: number;
96
+ pdfUrl?: string;
97
+ openAccess?: boolean;
98
+ type?: string;
99
+ language?: string;
100
+ updated?: string;
101
+ }
102
+ /**
103
+ * Identity used to read and write a supplier-partitioned science cache
104
+ * entry. `credentialFingerprint` is the full lowercase SHA-256 hex digest
105
+ * of the active credential, or the empty string for keyless suppliers
106
+ * (keyless responses are user-independent, so the shared partition is
107
+ * correct). `request` is the normalized Capability request.
108
+ */
109
+ export interface ScienceCacheIdentity {
110
+ readonly supplier: ScienceSupplierId;
111
+ readonly capability: "science.search" | "science.get" | "science.cite";
112
+ readonly credentialFingerprint: string;
113
+ readonly request: Readonly<ScienceSearchRequest | ScienceGetRequest>;
114
+ }
115
+ /**
116
+ * Science search Capability contract. Every supplier Adapter that
117
+ * supports search implements this interface and is consumed by the
118
+ * science executor.
119
+ */
120
+ export interface ScienceSearchCapability {
121
+ /**
122
+ * Validate a request before any supplier access. Throws
123
+ * `ValidationError` for an empty or whitespace-only query and for a
124
+ * malformed `year` control; `UnsupportedOptionError` for controls the
125
+ * Adapter does not accept. Validation must occur before transport
126
+ * construction.
127
+ */
128
+ validate(request: ScienceSearchRequest): void;
129
+ /** Build the cache identity; called only after `validate` succeeds. */
130
+ cacheIdentity(request: ScienceSearchRequest): ScienceCacheIdentity;
131
+ /** Invoke the supplier and return normalized works; no retries here. */
132
+ invoke(request: ScienceSearchRequest, signal?: AbortSignal): Promise<readonly ScienceWork[]>;
133
+ }
134
+ /**
135
+ * Science get Capability contract. Identifier-addressed single-work
136
+ * fetch: the identifier is parsed once (DOI/PMID/arXiv-id) and routed to
137
+ * suppliers serving that id type.
138
+ */
139
+ export interface ScienceGetCapability {
140
+ /**
141
+ * Validate a request before any supplier access. Throws
142
+ * `ValidationError` when the identifier is outside the grammar
143
+ * (`parseScienceIdentifier` returns null).
144
+ */
145
+ validate(request: ScienceGetRequest): void;
146
+ /** Build the cache identity; called only after `validate` succeeds. */
147
+ cacheIdentity(request: ScienceGetRequest): ScienceCacheIdentity;
148
+ /** Invoke the supplier and return one normalized work; no retries here. */
149
+ invoke(request: ScienceGetRequest, signal?: AbortSignal): Promise<ScienceWork>;
150
+ }
151
+ /**
152
+ * Science cite Capability contract. Typed but not shipped in v1 (PRD
153
+ * Non-goal: no science cite) — the type exists so provider descriptors
154
+ * can reference it later without contract churn. Ships when needed.
155
+ */
156
+ export interface ScienceCiteCapability {
157
+ /** Identifier grammar plus citation direction. */
158
+ validate(request: ScienceGetRequest): void;
159
+ cacheIdentity(request: ScienceGetRequest): ScienceCacheIdentity;
160
+ invoke(request: ScienceGetRequest, signal?: AbortSignal): Promise<readonly ScienceWork[]>;
161
+ }
162
+ /**
163
+ * The science Capability surface an Adapter exposes. `cite` is named in
164
+ * the contract but ships later; it is absent here in v1.
165
+ */
166
+ export interface ScienceCapability {
167
+ search: ScienceSearchCapability;
168
+ get: ScienceGetCapability;
169
+ }
170
+ /** The identifier kinds the closed grammar recognizes. */
171
+ export type ScienceIdentifierKind = "doi" | "pmid" | "arxiv";
172
+ /**
173
+ * Classify a bare science identifier. Returns `"doi"`, `"pmid"`, or
174
+ * `"arxiv"` when the identifier matches one of the closed forms, null
175
+ * otherwise. Bare forms only — prefixed input (e.g. `doi:10.1038/…`)
176
+ * returns null. Parsed once at the command layer; routing to suppliers
177
+ * serving that id type happens downstream.
178
+ */
179
+ export declare function parseScienceIdentifier(identifier: string): ScienceIdentifierKind | null;
180
+ /**
181
+ * Validate a science search request. Judges only the `query` (at least
182
+ * one non-whitespace character) and the `year` control grammar.
183
+ * `author`, `venue`, and `type` pass through unjudged — per-control
184
+ * accept/reject is the Adapter concern.
185
+ */
186
+ export declare function validateScienceSearchRequest(request: ScienceSearchRequest): void;
187
+ /**
188
+ * Validate a science get request. The identifier must be one of the bare
189
+ * closed forms (`parseScienceIdentifier` non-null); anything outside the
190
+ * grammar throws `ValidationError`.
191
+ */
192
+ export declare function validateScienceGetRequest(request: ScienceGetRequest): void;
193
+ //# sourceMappingURL=science.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"science.d.ts","sourceRoot":"","sources":["../../src/capabilities/science.ts"],"names":[],"mappings":"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"}