opencode-bioresearcher 1.11.1 → 1.13.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 (25) hide show
  1. package/README.md +110 -49
  2. package/agents/bioresearcher-dr-worker.md +32 -20
  3. package/connector-meta.json +6 -5
  4. package/index.js +146 -61
  5. package/package.json +4 -2
  6. package/skill-bundle.json +3 -5
  7. package/skills/bioresearcher-deep-research/SKILL.md +52 -6
  8. package/skills/bioresearcher-deep-research/references/analysis-methods.md +15 -0
  9. package/skills/bioresearcher-deep-research/references/article-literature.md +36 -18
  10. package/skills/bioresearcher-deep-research/references/cartography.md +190 -0
  11. package/skills/bioresearcher-deep-research/references/diseases.md +1 -1
  12. package/skills/bioresearcher-deep-research/references/drugs.md +5 -4
  13. package/skills/bioresearcher-deep-research/references/functional-genomics.md +7 -3
  14. package/skills/bioresearcher-deep-research/references/genes.md +5 -3
  15. package/skills/bioresearcher-deep-research/references/patents.md +9 -3
  16. package/skills/bioresearcher-deep-research/references/rate-limiting-auth.md +7 -2
  17. package/skills/bioresearcher-deep-research/references/report-template.md +17 -0
  18. package/skills/bioresearcher-deep-research/references/tool-selection.md +8 -5
  19. package/skills/bioresearcher-deep-research/references/utility-config.md +2 -2
  20. package/skills/bioresearcher-deep-research/references/worker-protocol.md +16 -1
  21. package/skills/bioresearcher-onboard/SKILL.md +114 -0
  22. package/skills/bioresearcher-onboard/scripts/bootstrap.ps1 +96 -0
  23. package/skills/bioresearcher-onboard/scripts/bootstrap.sh +127 -0
  24. package/skills/bioresearcher-onboard/scripts/onboard.mjs +512 -0
  25. package/loader.js +0 -3
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: bioresearcher-deep-research
3
- description: "Deep biomedical research orchestrator powered by the biomcp MCP server: clarifies the question, aligns research area plan with user, decomposes into 2-5 aspects, researches each aspect via subagents (sequential fallback), and synthesizes a fully cited report. Use for deep research, literature review, clinical trials, drugs, genes, variants, diseases, patents, PubMed, functional genomics, biomcp."
3
+ description: "Deep biomedical research orchestrator powered by the biomcp MCP server: clarifies the question, aligns research area plan with user, decomposes into 2-5 aspects, researches each aspect via subagents (sequential fallback), and synthesizes a fully cited report; optional map-first empirical cartography for category/landscape questions. Use for deep research, literature review, clinical trials, drugs, genes, variants, diseases, patents, PubMed, functional genomics, biomcp."
4
4
  license: Apache-2.0
5
5
  compatibility: "Any Agent Skills harness (opencode, Claude Code, Codex, Cursor, Gemini CLI) with the biomcp MCP server connected; the Claude Code plugin bundles the server and the bioresearcher-dr-worker subagent; a subagent/Task tool is optional - a sequential fallback is provided. The allowed-tools mcp__ entries apply on Claude Code only"
6
6
  metadata:
7
- version: "1.7.0"
7
+ version: "1.9.0"
8
8
  source: "opencode-bioresearcher-plugin@1.7.2"
9
9
  allowed-tools: Read Write Bash Task mcp__plugin_bioresearcher_biomcp mcp__biomcp
10
10
  ---
@@ -31,6 +31,10 @@ Harness-agnostic: works with or without a subagent/Task tool.
31
31
  generates the bibliography from the merged ledger, and `vet-references.py`
32
32
  audits the result (structural + NCBI) - producing `final_report.md` and, by
33
33
  default, `final_report.html` (the `no-html` prefix skips rendering).
34
+ - Optionally (map-first mode, for category-discovery questions) maps the
35
+ field's method/category landscape empirically BEFORE plan review via
36
+ scoped + anti-pinned cartography workers - see
37
+ `references/cartography.md`.
34
38
 
35
39
  ## When to use (triggers)
36
40
 
@@ -41,6 +45,8 @@ Harness-agnostic: works with or without a subagent/Task tool.
41
45
  - Gene / variant / disease questions (annotations, associations, evidence).
42
46
  - Patent landscape or prior-art questions.
43
47
  - Multi-entity questions spanning several of the above.
48
+ - Category/landscape discovery ("what methods/approaches/classes exist for
49
+ X", "landscape of X") - offer the map-first mode (Step 1).
44
50
 
45
51
  Single-fact lookups (e.g. "what is the HGNC symbol for HER2") do not need the
46
52
  full workflow - answer directly with the matching biomcp tool using
@@ -50,16 +56,16 @@ full workflow - answer directly with the matching biomcp tool using
50
56
 
51
57
  The biomcp MCP server (npm package [`biomcp`](https://www.npmjs.com/package/biomcp),
52
58
  canonical source [yeyuan98/biomcp-ts](https://github.com/yeyuan98/biomcp-ts) pinned to
53
- `biomcp@1.4.0`) connected to the harness. For automated zero-dependency local
59
+ `biomcp@1.6.0`) connected to the harness. For automated zero-dependency local
54
60
  setup, run the `bioresearcher-onboard` skill.
55
61
 
56
62
  Recommended client command (all features):
57
63
 
58
64
  ```json
59
- ["npx", "-y", "-p", "biomcp@1.4.0", "-p", "webr@0.6", "-p", "mysql2@3", "biomcp"]
65
+ ["npx", "-y", "-p", "biomcp@1.6.0", "-p", "webr@0.6", "-p", "mysql2@3", "biomcp"]
60
66
  ```
61
67
 
62
- Requires Node.js >= 22.13. Verify with `npx -y biomcp@1.4.0 doctor` (exit 0 =
68
+ Requires Node.js >= 22.13. Verify with `npx -y biomcp@1.6.0 doctor` (exit 0 =
63
69
  healthy). API keys are optional except where noted in
64
70
  `references/rate-limiting-auth.md`.
65
71
 
@@ -82,6 +88,7 @@ mid-query never trigger.
82
88
  | `no-interview` | Skip the interview workflow entirely (both Step 1 questions and Step 2 plan review) |
83
89
  | `light-research` | Combine and/or pick only the top TWO aspects (Step 2) |
84
90
  | `no-html` | Skip the Step 6 HTML rendering (markdown-only output) |
91
+ | `map-first` | Run empirical field cartography (Step 1.5) before plan review, for category-discovery questions - see `references/cartography.md` |
85
92
 
86
93
  ## Workflow
87
94
 
@@ -103,6 +110,29 @@ answer your own questions. If the query carries `no-interview`, skip to Step 2.
103
110
  unattended session: write questions and chosen defaults to
104
111
  `reports/<TOPIC>/assumptions.md` and cite that file in Limitations.
105
112
 
113
+ **Map-first offer (conditional):** if the query is category-discovery shaped
114
+ (the deliverable is a taxonomy/landscape: "what methods/approaches/classes/
115
+ evidence types exist", "landscape of", "how is X done across ..."), include
116
+ ONE additional interview question offering empirical cartography (recommend
117
+ ON); if accepted, confirm the PRIMARY SCOPE in the same message per
118
+ `references/cartography.md`. Entity-anchored queries: never ask. The
119
+ `map-first` prefix forces the mode on without the question. When the mode is
120
+ off (not offered or declined), Steps 1-6 run exactly as if this feature did
121
+ not exist.
122
+
123
+ ### Step 1.5: Cartography (map-first mode only)
124
+
125
+ Skipped entirely when map-first is off. Dispatch cartographers per
126
+ `references/cartography.md`: 2 focus-tier axes scoped to the confirmed
127
+ primary scope (synthesis-mining, boundary-vocabulary) plus 1-2 anti-pinned
128
+ context axes, using the same tier dispatch, ledger discipline, and
129
+ completion gates as Step 4 (cartographer template and anti-pinning contract
130
+ live in the reference). Then merge the axis maps into
131
+ `reports/<TOPIC>/category_taxonomy.md` (tiered categories, coverage audit
132
+ against >= 2 scope-internal syntheses, unanchored leads); the venue-sweep
133
+ remediation axis fires only when syntheses are scarce. Cartography ledgers
134
+ land in `evidence/` and merge in Step 5a like any aspect ledger.
135
+
106
136
  ### Step 2: Decompose & Review Plan
107
137
 
108
138
  Comprehend the inquiry and identify 2-5 critical research aspects (top 2 under
@@ -126,6 +156,14 @@ focus, primary tools); never paste raw ABSTRACTs into the question UI.
126
156
  4. **Waiver / Degrade:** Skip plan review turn if query has `no-interview`, or
127
157
  degrade per Step 1 rules if unattended (record plan in `assumptions.md`).
128
158
 
159
+ **Map-first variant:** the plan review operates on the category taxonomy
160
+ (`references/cartography.md`): present tiers, coverage-audit results, and a
161
+ recommended selection; iterate until confirmed - this taxonomy walk-through
162
+ IS the plan review, non-waivable except by `no-interview` (autonomous
163
+ conversion records its rationale in `assumptions.md`). Selected categories
164
+ become the aspects; each still gets a full deep-dive ABSTRACT with binding
165
+ inclusion/exclusion criteria.
166
+
129
167
  Track finalized aspects in the harness's todo tool (TodoWrite or equivalent).
130
168
 
131
169
  ### Step 3: Create the output directory
@@ -226,7 +264,9 @@ Read all per-aspect reports. Summarize findings into a succinct, accurate
226
264
  final report addressing the user's inquiry, following the mandatory 6-section
227
265
  structure in `references/report-template.md` (Executive Summary, Data Sources,
228
266
  Analysis Methodology, Findings, Limitations, References - the References
229
- section itself is generated later by `render`). Reconcile conflicting findings
267
+ section itself is generated later by `render`). Under map-first, also apply
268
+ that reference's optional landscape and decision-guide sections (decision
269
+ guide default-on). Reconcile conflicting findings
230
270
  across aspects explicitly rather than silently dropping one side.
231
271
 
232
272
  Write the synthesized draft to `reports/<TOPIC>/final_report.draft.md` citing
@@ -336,9 +376,14 @@ python3 <skill_dir>/scripts/vet-references.py reports/<TOPIC>/final_report.md --
336
376
  ```
337
377
  reports/<TOPIC>/
338
378
  ├── plan.md # durable research plan (Step 3; boundaries live here)
379
+ ├── category_map_<axis>.md # per-axis cartography maps (map-first only)
380
+ ├── category_taxonomy.md # merged tiered taxonomy + coverage audit
381
+ │ # (map-first only)
339
382
  ├── evidence/
340
383
  │ ├── <aspect_1>.jsonl # per-aspect evidence ledger (worker-written)
341
384
  │ ├── <aspect_2>.jsonl
385
+ │ ├── cartography_<axis>.jsonl # cartography ledgers (map-first only;
386
+ │ │ # merge like aspect ledgers)
342
387
  │ ├── ...
343
388
  │ ├── _invalid.jsonl # merge quarantine (only when malformed lines occur)
344
389
  │ └── sources.jsonl # merged + verified ledger (Step 5a output)
@@ -395,6 +440,7 @@ reports/<TOPIC>/
395
440
  | File | Contents |
396
441
  |------|----------|
397
442
  | `references/worker-protocol.md` | Worker prompt template, file protocol, no re-delegation, retry/degrade rules |
443
+ | `references/cartography.md` | map-first mode: scopes, axis archetypes, anti-pinning contract, taxonomy + coverage audit, interaction matrix |
398
444
  | `references/tool-selection.md` | Question-type to tool decision tree; sections/limit/pagination patterns; biomcp_ prefix note |
399
445
  | `references/article-literature.md` | article_search / article_get: sources, dateRange, citations |
400
446
  | `references/clinical-trials.md` | trial_search / trial_get: filters, cursor paging, sections |
@@ -31,6 +31,7 @@ An aspect is DONE when ALL of these hold:
31
31
  | Variant evidence | Variant annotation + (if token) OncoKB + trials | variant_search, variant_get, variant_oncokb |
32
32
  | Patent landscape | 10-30 patents incl. seminal prior art | patent_search, patent_get |
33
33
  | Dataset hunt | Candidate accessions + linked publication | geo_search, sra_search, genbank_search |
34
+ | Category cartography (map-first) | 15-30 anchored categories per axis; every category >= 1 synthesis structure or >= 2 primaries | article_search, article_get |
34
35
 
35
36
  ## Source-quality rules
36
37
 
@@ -118,6 +119,20 @@ ABSTRACT; these rules govern how workers apply any such criteria.
118
119
  improvised categories); re-check rules 1-2 whenever synthesis rewords a
119
120
  claim or transcribes a number from an aspect report.
120
121
 
122
+ ## Cartography discipline (map-first mode)
123
+
124
+ - Category anchoring bar: a listed category needs >= 1 retrieved synthesis
125
+ whose structure demonstrably contains it, or >= 2 primary records -
126
+ keyword overlap is not coverage (anti-pinning contract:
127
+ `references/cartography.md`).
128
+ - Scope-relative tiers: adoption tiers (1/2/3) are relative to the primary
129
+ scope's own practice; state the reference frame, never present a tier as
130
+ absolute.
131
+ - Coverage audit: the merged taxonomy is reconciled against >= 2
132
+ scope-internal syntheses; synthesis-enumerated categories missing from
133
+ the map are added or declared as gaps - silent omission is the failure
134
+ mode this audit exists to catch.
135
+
121
136
  ## Failure modes
122
137
 
123
138
  | Symptom | Fix |
@@ -5,10 +5,11 @@ Literature search and retrieval via `article_search` / `article_get`
5
5
 
6
6
  ## Overview
7
7
 
8
- `article_search` runs federated search across up to five backends with
9
- deduplication; `article_get` retrieves one article by PMID/PMCID/DOI with
10
- optional open-access full text, annotations, and citation graphs. Both tools
11
- enforce a 30-second execution timeout.
8
+ `article_search` runs federated search across up to six backends with
9
+ deduplication; `article_get` retrieves one article by PMID/PMCID/DOI (journal
10
+ or preprint DOI) with optional annotations, citation graphs, and opt-in
11
+ full text. `article_search` enforces a 30-second execution timeout,
12
+ `article_get` 60 seconds.
12
13
 
13
14
  ## Tools
14
15
 
@@ -17,10 +18,10 @@ enforce a 30-second execution timeout.
17
18
  | Parameter | Type | Notes |
18
19
  |-----------|------|-------|
19
20
  | query | string (required) | Search query (title, abstract, or keyword) |
20
- | source | enum, optional | `pubmed`, `europepmc`, `semantic_scholar`, `pubtator`, `litsense`; omit for federated search over all |
21
+ | source | enum, optional | `pubmed`, `europepmc`, `semantic_scholar`, `pubtator`, `litsense`, `preprint_only`, `arxiv`; omit for federated search (bioRxiv/medRxiv preprints are NOT included unless `preprint_only` is explicit; the default federation does include the `arxiv` leg) |
21
22
  | limit | int 1-50, default 10 | Applied to FINAL deduplicated results, not per-source |
22
23
  | offset | int >= 0, default 0 | Result offset |
23
- | dateRange | string, optional | `YYYY-MM-DD/YYYY-MM-DD`; open-ended `2020-01-01/` or `/2023-12-31`; at least one endpoint required. Only `pubmed`, `europepmc`, `semantic_scholar` support it - NOT `pubtator`/`litsense` |
24
+ | dateRange | string, optional | `YYYY-MM-DD/YYYY-MM-DD`; open-ended `2020-01-01/` or `/2023-12-31`; at least one endpoint required. Supported by `pubmed`, `europepmc`, `semantic_scholar`, `preprint_only`, `arxiv` - NOT `pubtator`/`litsense` |
24
25
 
25
26
  Federated sources at a glance:
26
27
 
@@ -31,20 +32,34 @@ Federated sources at a glance:
31
32
  | semantic_scholar | CS/ML-adjacent and citation graph (key optional) |
32
33
  | pubtator | Biomedical entity-tagged (gene/disease/drug/variant/chemical) |
33
34
  | litsense | Sentence-level semantic match to the query |
35
+ | preprint_only | bioRxiv/medRxiv preprints only (rows carry `preprint_server`, `ppr_id`) |
36
+ | arxiv | arXiv preprint server (rows carry `arxiv_id`) |
34
37
 
35
38
  ### article_get
36
39
 
37
40
  | Parameter | Type | Notes |
38
41
  |-----------|------|-------|
39
- | id | string (required) | PMID (numeric, e.g. "12345"), PMCID ("PMC1234567"), or DOI ("10.1038/s41586-021-03819-2") |
40
- | sections | enum array, optional | `core`, `oa`, `annotations`, `graph`, `citation`, `all`; omit for core metadata only |
42
+ | id | string (required) | PMID (numeric, e.g. "12345"), PMCID ("PMC1234567"), journal DOI ("10.1038/s41586-021-03819-2"), or preprint DOI ("10.1101/YYYY.MM.NN.NNNNNN", new prefix "10.64898/...") |
43
+ | sections | enum array, optional | `core`, `oa`, `fulltext`, `annotations`, `graph`, `citation`, `all`; omit for core metadata only. `["all"]` = oa+annotations+graph+citation WITHOUT fulltext - request `["fulltext"]` separately |
41
44
  | limit | int 1-100, default 20 | Max items per section (e.g. 20 citations) |
42
45
  | citation_mode | `fast` (default) / `full` | fast ~4 s, 4 providers with auto-fallback to PubMed; full ~15-30 s, all 5 providers incl. PubMed |
43
46
  | citation_direction | `forward` / `backward` / `both` (default) | forward = articles citing this one; backward = its references |
44
-
45
- Section contents: `core` = title/authors/journal/abstract; `oa` = open-access
46
- full text (PMC OA); `annotations` = PubTator entity annotations; `graph` =
47
- citation graph; `citation` = forward citations + backward references.
47
+ | fulltext_output | `file` (default) / `inline` | `sections:["fulltext"]` output mode - see below |
48
+ | fulltext_max_chars | int 1000-200000, default 40000 | Inline-mode only cap for `fulltext` text; ignored in file mode |
49
+
50
+ Section contents: `core` = title/authors/journal/abstract; `oa` =
51
+ license/access metadata and links ONLY - status vocabulary
52
+ `open_access | free_to_read | paywalled | not_in_pmc | unknown` (a pdf_url
53
+ does not by itself mean the text is fetchable); `fulltext` = the ACTUAL
54
+ text when freely readable in PMC/Europe PMC (opt-in, never triggered by
55
+ `"all"`); `annotations` = PubTator entity annotations; `graph` = citation
56
+ graph; `citation` = forward citations + backward references.
57
+
58
+ `fulltext` is file-first: by default the complete text is written to a
59
+ server-side markdown file and the reply carries `file_path` plus an outline
60
+ (Read/Grep the file selectively). Use `fulltext_output: "inline"` (capped by
61
+ `fulltext_max_chars`) only when the harness cannot read server-side files.
62
+ `oa`/`fulltext` do not apply to preprint DOIs.
48
63
 
49
64
  ## Worked examples
50
65
 
@@ -74,25 +89,28 @@ Full metadata plus citations for a known PMID:
74
89
  | Symptom | Cause | Fix |
75
90
  |---------|-------|-----|
76
91
  | Tool error "timed out after 30000ms" | federated fan-out exceeded 30 s | retry with a single `source`, narrower `dateRange`, or `limit` lowered |
77
- | dateRange silently ignored | `source` was pubtator or litsense | filter dates client-side, or switch source to pubmed/europepmc/semantic_scholar |
92
+ | dateRange silently ignored | `source` was pubtator or litsense | filter dates client-side, or switch source to pubmed/europepmc/semantic_scholar/arxiv/preprint_only |
78
93
  | Fewer results than limit on federated search | dedup-then-limit semantics | page with `offset`; duplicates across sources collapse into one entry |
79
94
  | citation section empty in fast mode | providers returned no items (fast auto-falls back to PubMed) | retry with `citation_mode: "full"` |
80
95
 
81
- ## Field contract (biomcp >= 1.4.0)
96
+ ## Field contract (biomcp >= 1.6.0)
82
97
 
83
98
  Article records from every article tool path (`article_search`,
84
99
  `article_get`, `batch_get`, `discover`) carry: `pmid`, `pmcid`, `doi`,
85
100
  `title`, `authors` (full "LastName ForeName" strings - Vancouver initials are
86
- computed by the evidence-ledger `bib` command), `journal`, `publication_date`
87
- (raw string), `volume`, `issue`, `pages` (null when the upstream record has
88
- none, e.g. epub-ahead-of-print), plus `mesh_headings`/`publication_types`/
89
- `keywords`/`chemicals` on PubMed paths. HTML entities are decoded to UTF-8.
101
+ computed by the evidence-ledger `bib` command), `journal`, `journal_issn`,
102
+ `publication_date` (raw string), `volume`, `issue`, `pages` (null when the
103
+ upstream record has none, e.g. epub-ahead-of-print), plus `mesh_headings`/
104
+ `publication_types`/`keywords`/`chemicals` on PubMed paths. HTML entities are
105
+ decoded to UTF-8.
90
106
 
91
107
  Backend coverage notes:
92
108
 
93
109
  - Only `pubmed` and `europepmc` return locator fields (volume/issue/pages).
94
110
  - `semantic_scholar`, `pubtator`, and `litsense` records never carry
95
111
  locators.
112
+ - `preprint_only` rows carry `preprint_server`/`ppr_id` and `arxiv` rows
113
+ carry `arxiv_id`; neither carries journal locator fields.
96
114
  - LitSense hits are HINT records: `{pmid, pmcid, score, source}` only - no
97
115
  title, no abstract. Before citing a LitSense-only PMID, enrich it with
98
116
  `article_get(pmid)` (one sequential call; standard retry ladder on
@@ -0,0 +1,190 @@
1
+ # Empirical Cartography (map-first mode)
2
+
3
+ Optional Stage-1 field mapping for the deep-research skill: discover the
4
+ method/category landscape empirically BEFORE proposing the research plan,
5
+ then run the standard aspect workflow on user-selected categories. This mode
6
+ is field-, community-, and question-agnostic: it applies to any
7
+ category-discovery question in the biomedical realm (methods, approaches,
8
+ evidence classes, taxonomies, landscapes), in any discipline.
9
+
10
+ ## When map-first applies
11
+
12
+ - OFFER it (inside the Step 1 interview, one extra question, only when the
13
+ query is category-discovery shaped): the deliverable is a taxonomy or
14
+ landscape - "what methods/approaches/classes/evidence types exist for X",
15
+ "landscape of X", "how is X done across ...", "categories of X".
16
+ - Do NOT offer for entity-anchored queries (one drug, variant, trial, gene,
17
+ disease) - the default workflow is already right.
18
+ - The `map-first` prefix forces the mode on without the offer question.
19
+ - Default OFF: with map-first off, every workflow step, file, gate, and
20
+ report section is identical to the non-cartography skill. The only
21
+ default-mode addition is the conditional offer question itself.
22
+
23
+ ## Primary scope vs context scope
24
+
25
+ The user designates a PRIMARY SCOPE - the literature segment where category
26
+ recall is the success criterion - defined by any combination of community,
27
+ discipline, disease/therapeutic area, modality, technique family, organism,
28
+ data type, or question type. Everything else is CONTEXT SCOPE: mapped for
29
+ awareness, never exhaustively. The orchestrator infers a candidate primary
30
+ scope from query vocabulary (e.g. "industry-ready", "clinical practice",
31
+ "food science", "diagnostic assay development") and asks for confirmation
32
+ in the same interview message - the recall target depends on it, and users
33
+ rarely name it spontaneously. If the user declines to specify, run with the
34
+ scope implied by the query terms and record the assumption in plan.md.
35
+
36
+ ## Two-tier dispatch
37
+
38
+ Focus tier (2 workers, scoped to the primary scope, method-unpinned):
39
+
40
+ - `cartography_synthesis_mining` - transcribe the scope's OWN synthesis
41
+ ecosystem (reviews, guidelines, consensus statements, position papers,
42
+ protocol series): harvest their section structures as candidate
43
+ categories and expand via backward citations (article_get
44
+ sections=["citation"]) to founding anchors. The scope's own taxonomies
45
+ are the recall target.
46
+ - `cartography_boundary_vocabulary` - hunt categories that answer the
47
+ question's underlying information need but self-describe under different
48
+ terms: adjacent vocabulary, hypernyms, enabling/auxiliary measurements,
49
+ neighboring endpoints. Ask, per formulation of the information need:
50
+ "what does this scope call the things that do X?"
51
+
52
+ Context tier (1-2 workers, fully anti-pinned, breadth across the rest of
53
+ the field) - pick archetypes by question shape:
54
+
55
+ - `cartography_context_principle` - enumerate the distinct
56
+ experimental/analytical principles by which the question is answered;
57
+ let the categories emerge from retrieved records.
58
+ - `cartography_context_casespace` - partition the question's object space
59
+ (barriers, diseases, organisms, tissues, modalities - whatever partitions
60
+ it) and map category coverage per stratum.
61
+ - `cartography_context_segment` - sweep how OTHER communities/disciplines
62
+ frame and categorize the same question; vocabulary differences are
63
+ themselves findings.
64
+
65
+ Budget: ~15-25 biomcp calls per cartographer (hard cap 30); parallel
66
+ batches of up to 5; Tier A/B dispatch and the Tier C sequential fallback
67
+ follow SKILL.md Step 4, using the cartographer template below.
68
+
69
+ Conditional remediation axis (orchestrator-dispatched after the focus tier
70
+ returns, only when needed):
71
+
72
+ - `cartography_venue_sweep` - fires IFF the focus tier found fewer than two
73
+ field-spanning syntheses OR the interview flagged an emerging area: sweep
74
+ the primary scope's primary-literature venues for categories its thin
75
+ synthesis ecosystem under-covers.
76
+
77
+ ## Anti-pinning contract (binding on every cartographer)
78
+
79
+ 1. No method names, assay names, or category lists enter a cartographer
80
+ prompt. Focus-tier prompts pin the PRIMARY SCOPE and the question's
81
+ information need - never methods. Context-tier prompts pin nothing but
82
+ the question.
83
+ 2. A category may be listed ONLY if anchored in retrieved records: either
84
+ >= 1 retrieved synthesis whose structure demonstrably contains it, OR
85
+ >= 2 primary records found via search.
86
+ 3. Never assert a category from model memory; memory shapes query design
87
+ only. A failed query line is logged under Evidence Gaps - never turned
88
+ into a category.
89
+ 4. Probe deliberately across the assigned axis before concluding; do not
90
+ stop at the first handful of categories.
91
+
92
+ ## Cartographer prompt template
93
+
94
+ ```md
95
+ TOPIC: <TOPIC>
96
+ YOUR RESEARCH FOCUS: cartography_<axis>
97
+ AXIS: <archetype name + one-line instantiation, e.g. "case-space partition:
98
+ the variable that partitions this question's object space is <variable>">
99
+ PRIMARY SCOPE: <primary scope - focus tier only; context tier: "none -
100
+ stay anti-pinned">
101
+ MISSION: Produce an empirically anchored, high-level map of the major
102
+ method/category families for <question>, entering the field from your
103
+ axis. 15-30 categories maximum (merge near-duplicates and say so).
104
+ OUTPUT: reports/<TOPIC>/category_map_<axis>.md (title; one-paragraph scope
105
+ summary; ONE subsection per category: name, one-line description, 1-3
106
+ anchor papers as cite-key markers, maturity signals - synthesis existence,
107
+ approximate hit volume, founding era - and which queries surfaced it; then
108
+ "## Query Log" and "## Evidence Gaps" with failed query lines) plus
109
+ reports/<TOPIC>/evidence/cartography_<axis>.jsonl.
110
+ SKILL_DIR: <absolute skill dir> # Tier B only; resolve before dispatch
111
+ EXECUTION RULE: Do NOT read or inspect evidence-ledger.py or other skill
112
+ scripts; all schemas and commands are fully specified here.
113
+ ```
114
+
115
+ Tier B orchestrators additionally inline the anti-pinning contract, the
116
+ anchoring rule, the ledger discipline (worker-protocol.md rules 5-8), and
117
+ the completion-gate command. Cartographers follow every Worker rule in
118
+ `references/worker-protocol.md` (sequential calls, retry ladder, verbatim
119
+ ledger records, no bibliography) with the category map replacing the
120
+ aspect report and `check --markers category_map_<axis>.md` as the gate.
121
+
122
+ ## Taxonomy merge + coverage audit (orchestrator)
123
+
124
+ Merge all axis maps into `reports/<TOPIC>/category_taxonomy.md`:
125
+
126
+ - Deduplicated category list; per category: name, one-line description,
127
+ anchors, maturity signals, surfaced-by axes (cross-axis confirmation is
128
+ a robustness signal), and an adoption tier (1 = established /
129
+ industry-grade, 2 = discovery-grade, 3 = emerging/niche) - tiers are
130
+ scope-relative and the taxonomy must say so explicitly.
131
+ - "## Coverage Audit" section: reconcile the merged map against the
132
+ enumerated method/category lists of >= 2 scope-internal syntheses. Any
133
+ category a synthesis enumerates that the map lacks must be added (with
134
+ anchors) or explained as a declared gap. If the scope yielded fewer than
135
+ 2 syntheses, anchor the audit on cross-axis overlap instead and flag
136
+ synthesis scarcity (this also triggers the venue-sweep remediation).
137
+ - "## Unanchored Leads" section: suspected-but-unanchored territories,
138
+ listed as the query lines tried - never as categories.
139
+
140
+ ## Interaction matrix
141
+
142
+ | Mode | Behavior |
143
+ |------|----------|
144
+ | Default, heuristic fired | Step 1 interview includes ONE offer question ("empirical field mapping first?" - recommend ON) and, if accepted, primary-scope confirmation in the same message; nothing else changes |
145
+ | Default, heuristic not fired | Identical to the non-cartography skill: no question, no cartography files |
146
+ | `map-first` | Cartography on without the offer question; the interview still runs (scope + clarifiers) unless `no-interview` is also present |
147
+ | `map-first` + `no-interview` | Cartography on; taxonomy -> plan conversion is autonomous: record the category-selection rationale and coverage-audit outcome in plan.md + assumptions.md, and state in the report Limitations that scope selection was not user-reviewed |
148
+ | `no-interview` alone | Identical to the non-cartography skill (Step 1 is skipped, so no offer fires) |
149
+
150
+ Cartography does NOT waive the Step 2 plan review: with map-first on (and
151
+ no `no-interview`), the taxonomy walk-through IS the plan review - present
152
+ the taxonomy with tiers, coverage-audit results, and a recommended category
153
+ selection, then iterate with the user until the plan is confirmed (same
154
+ rounding rules as Step 2). Selected categories become the Step 3 aspects
155
+ (standard deep-dive ABSTRACTs; the taxonomy's inclusion signals seed the
156
+ ABSTRACT boundaries; the set may exceed 5 when the user insists - batch
157
+ dispatches accordingly). Categories discovered but not selected stay
158
+ citable: their cartography ledgers merge into sources.jsonl in Step 5a
159
+ like any aspect ledger, and the report carries them in the optional
160
+ landscape section (`references/report-template.md`).
161
+
162
+ ## Report integration
163
+
164
+ - Landscape section (map-first only): one line per discovered-but-
165
+ unselected category, citing its cartography anchors - acknowledged, not
166
+ researched; the report must say so.
167
+ - Decision guide by question scenario (map-first default-on): one compact
168
+ "scenario -> recommended method sequence -> tier -> caveat" table per
169
+ user-confirmed question scenario, built only from ledger-verified
170
+ sources, tiers labeled scope-relative.
171
+ - The field's own taxonomy disagreements (syntheses classifying the same
172
+ subject differently) are reported in Analysis Methodology or Findings,
173
+ never silently resolved.
174
+
175
+ ## Degradation + consistency
176
+
177
+ - No subagent tool: run axes sequentially in the main conversation (same
178
+ contract, leaner budgets).
179
+ - Server unavailable: cartography cannot run - proceed with the default
180
+ workflow and say so explicitly.
181
+ - map-first OFF: behavior is identical to the non-cartography skill
182
+ (steps, files, gates, report structure). The existing agent-test
183
+ deep-research suite (q01-q07) is the regression guarantee and stays
184
+ unchanged.
185
+
186
+ ## Out of scope / future work
187
+
188
+ - Report update mode (re-running an existing report): a verify-and-refresh
189
+ worker tier for previously covered core areas - deliberately NOT part of
190
+ map-first, which always researches from scratch.
@@ -80,7 +80,7 @@ Trial landscape directly (name accepted):
80
80
 
81
81
  | Symptom | Cause | Fix |
82
82
  |---------|-------|-----|
83
- | `_error: Disease ... not found` from disease_trials | invalid/unresolvable ID | call `disease_search` first and copy the exact ID; supported formats are MONDO/DOID/OMIM (message text) plus EFO/Orphanet/CUI accepted by the resolver |
83
+ | `_error: Disease 'X' not found. Try disease_search...` from disease_trials | invalid/unresolvable ID | call `disease_search` first and copy the exact ID; supported formats are MONDO/DOID/OMIM/UMLS CUI (message text) plus EFO/Orphanet accepted by the resolver |
84
84
  | disease_get 0 hits for a raw name | the tool wants an ID, not a name | resolve via `disease_search`, or use `disease_trials`/`disease_drugs` which accept names |
85
85
  | Sections empty | over-narrow section set or sparse annotation for rare diseases | try `sections: ["all"]` and note data sparsity in the report |
86
86
 
@@ -6,7 +6,7 @@ Drug identity, regulatory status, labels, adverse events, and targets via
6
6
  ## Overview
7
7
 
8
8
  `drug_search` finds drugs by name/mechanism/keyword (MyChem-backed);
9
- `drug_get` returns per-drug detail with sections spanning US/EU/WHO
9
+ `drug_get` returns per-drug detail with sections spanning US/WHO
10
10
  regulatory data, FDA labels (safety), FAERS adverse events, targets, and
11
11
  indications; `drug_trials` cross-links to clinical trials.
12
12
 
@@ -25,7 +25,7 @@ indications; `drug_trials` cross-links to clinical trials.
25
25
  | Parameter | Type | Notes |
26
26
  |-----------|------|-------|
27
27
  | name | string (required) | Drug name, e.g. "imatinib", "aspirin" |
28
- | sections | enum array, optional | `core`, `us_regulatory`, `eu_regulatory`, `who_regulatory`, `safety`, `targets`, `indications`, `adverse_events`, `all` |
28
+ | sections | enum array, optional | `core`, `us_regulatory`, `who_regulatory`, `safety`, `targets`, `indications`, `adverse_events`, `all` |
29
29
  | limit | int 1-100, default 20 | For `adverse_events`, caps the number of ranked reaction rows |
30
30
 
31
31
  Section semantics (important - commonly confused):
@@ -34,7 +34,7 @@ Section semantics (important - commonly confused):
34
34
  |---------|----------|
35
35
  | core | identity, identifiers, description |
36
36
  | us_regulatory | US brand name + `fda_status` (e.g. approved) - NOT full labels, NOT approval history |
37
- | eu_regulatory / who_regulatory | EMA / WHO regulatory summaries |
37
+ | who_regulatory | WHO Prequalification products: `{prequalified, products, note}` - prequalification listing, not regulatory summaries |
38
38
  | safety | FDA LABEL TEXT: box_warning, warnings, adverse_reactions - this is where label prose lives |
39
39
  | adverse_events | FDA FAERS adverse reactions RANKED by report count - no filters (no patient age/sex/date/reaction filtering) |
40
40
  | targets | drug targets |
@@ -65,7 +65,7 @@ Regulatory snapshot + targets + indications in one call:
65
65
 
66
66
  ```json
67
67
  {"name": "trastuzumab",
68
- "sections": ["us_regulatory", "eu_regulatory", "targets", "indications"]}
68
+ "sections": ["us_regulatory", "who_regulatory", "targets", "indications"]}
69
69
  ```
70
70
 
71
71
  ## Failure modes
@@ -75,6 +75,7 @@ Regulatory snapshot + targets + indications in one call:
75
75
  | us_regulatory is surprisingly thin | it only carries brand name + fda_status | label text (warnings, box warning, adverse reactions) is in `safety` |
76
76
  | Wanting FAERS filtered by age/sex/date | `adverse_events` exposes ranked counts only - no filters | take the ranked list and note the limitation in the report; do not claim subgroup-level FAERS results |
77
77
  | 0 hits for a trade name | search index prefers generic/mechanism terms | `drug_search` by generic name or mechanism, then `drug_get` by the matched name |
78
+ | `sections: ["eu_regulatory"]` rejected (MCP -32602) | `eu_regulatory` was removed in biomcp 1.6.0 | drop it; US status is `us_regulatory`, WHO prequalification is `who_regulatory` |
78
79
  | Payload too large | `sections: ["all"]` on a heavily annotated drug | request only the needed sections; lower `limit` for reaction rows |
79
80
 
80
81
  ## Integration notes
@@ -44,9 +44,13 @@ not index them; the error points at ENA (https://www.ebi.ac.uk/ena).
44
44
  `format` (`genbank` default / `fasta`), `seq_start`/`seq_stop` (1-based
45
45
  inclusive region), `strand` (1 plus; 2 minus, allows seq_start > seq_stop for
46
46
  reverse slices), `max_response_bytes` (default 30,000,000; oversized errors
47
- rather than truncates). Caps: whole-record fetches max 2,000,000 bp - larger
48
- records REQUIRE a seq_start/seq_stop region (up to 10 Mb span); output
49
- `sequence_text` is truncated to its first 200,000 characters when oversized.
47
+ rather than truncates), `sequence_output` (`file` default / `inline`). Caps:
48
+ whole-record fetches max 2,000,000 bp - larger records REQUIRE a
49
+ seq_start/seq_stop region (up to 10 Mb span). Sequences over 1,000 characters
50
+ default to FILE mode: the full text is written to a server-side cache file
51
+ and the reply carries `file_path` + char counts (never truncated) - Read/Grep
52
+ the file selectively. `sequence_output: "inline"` opts back into inline
53
+ `sequence_text`, capped at its first 200,000 characters.
50
54
 
51
55
  `genbank_genes`: maps a nucleotide accession to NCBI Gene IDs (elink
52
56
  nuccore->gene) usable directly with gene_get/gene_search (entrezgene IDs) -
@@ -40,11 +40,11 @@ Protein Atlas - see pacing note below), `druggability` (DGIdb),
40
40
 
41
41
  | Tool | Parameters | Notes |
42
42
  |------|-----------|-------|
43
- | gene_diseases | symbol, limit (1-50, default 10) | DisGeNET associations NEED `DISGENET_API_KEY`; without it the tool falls back to OpenTargets gene-disease associations |
43
+ | gene_diseases | symbol, limit (1-50, default 10) | DisGeNET associations NEED `DISGENET_API_KEY`; without it the tool silently returns OpenTargets gene-disease rows (source: "opentargets") |
44
44
  | gene_drugs | symbol | Drugs targeting the gene |
45
45
  | gene_trials | symbol | Clinical trials referencing the gene |
46
46
  | gene_articles | symbol | Articles about the gene (relevance search, no recency sort) |
47
- | gene_enrich | genes (list of HGNC symbols) | Reactome pathway enrichment; returns `_error` row on failure |
47
+ | gene_enrich | genes (min 3 HGNC symbols), limit (1-100, default 30) | Reactome pathway enrichment; success returns `{pathways, total_reported, truncated}`; a single `_error` row on failure |
48
48
 
49
49
  ## Worked examples
50
50
 
@@ -77,7 +77,7 @@ Enrichment on a hit list:
77
77
  | Symptom | Cause | Fix |
78
78
  |---------|-------|-----|
79
79
  | gene_get error: not a valid HGNC symbol | alias or outdated name used | pass the official symbol, or set `smart: true` |
80
- | gene_diseases returns `_error` re DisGeNET | `DISGENET_API_KEY` missing | the tool already fell back to OpenTargets data; add the key for DisGeNET-grade associations |
80
+ | gene_diseases returns an `_error` row | BOTH DisGeNET and OpenTargets failed - not merely a missing key | without `DISGENET_API_KEY` the tool silently returns OpenTargets rows (source: "opentargets"); add the key for DisGeNET-grade associations and retry transient backend failures |
81
81
  | HPA sections slow/erroring when iterating many genes | `protein_atlas`/`expression` use an unthrottled raw fetch | pace these calls manually; other sections are server-limited |
82
82
  | gene_enrich single `_error` row | Reactome AnalysisService rejected the input | check symbols are valid HGNC; retry with a smaller list |
83
83
 
@@ -90,4 +90,6 @@ Enrichment on a hit list:
90
90
  gene expression questions with tissue profiles.
91
91
  - `ensembl_lookup` (references/ensembl-pdb.md) is the identifier/structure
92
92
  authority (stable IDs, coordinates, transcripts) for ANY Ensembl species.
93
+ - `gene_enrich` runs 15-45 s typically (~105 s worst case, its server-side
94
+ budget) - keep client tool timeouts generous (>= 120 s) for it.
93
95
  - MyGene is server-limited at 100 ms - no manual throttling.
@@ -29,7 +29,12 @@ the biomedical ones: search is bounded at 60 s, detail at 120 s.
29
29
  | seminal | boolean, optional, default true | Co-citation mining of top results to surface foundational prior art in `seminal_prior_art`; adds ~5-30 s - set `false` for the fastest bibliographic lookups |
30
30
 
31
31
  Default (no `source`) "auto" mode: queries worldwide + ppubs concurrently; if
32
- ppubs fails hard it falls back to uspto_odp once (tagged `_note`).
32
+ ppubs fails hard it falls back to uspto_odp once (noted in `warnings`). The
33
+ success payload is an envelope: `{patents, total_hits, total_hits_basis,
34
+ seminal_prior_art, mined_count, errors?, warnings?}` - backend failures
35
+ (e.g. a google_patents timeout) ride in `errors` as `{source, message}`
36
+ entries, fallback/coverage notes in `warnings`; there are no in-band marker
37
+ rows inside `patents`.
33
38
 
34
39
  ### patent_get
35
40
 
@@ -82,8 +87,9 @@ Pull claims and citations for a specific patent:
82
87
 
83
88
  ## Integration notes
84
89
 
85
- - Auto-mode `_note` fields flag backend fallbacks - mention data lineage in
86
- the report when present.
90
+ - Auto-mode envelope fields flag data lineage - `errors[]` entries
91
+ (source + message) record backend failures and `warnings[]` records
92
+ fallback/coverage notes; mention them in the report when present.
87
93
  - EPO OPS and USPTO are server-limited at ~1 s token buckets - no manual
88
94
  throttling; expect patent tools to be the slowest calls in an aspect.
89
95
  - Cite patents by publication number with a Google Patents or Espacenet URL
@@ -49,7 +49,11 @@ Everything else: call sequentially, no timers.
49
49
 
50
50
  | Tool | Budget |
51
51
  |------|--------|
52
- | article_search / article_get | 30 s |
52
+ | article_search / journal_metrics | 30 s |
53
+ | article_get | 60 s |
54
+ | gene_get / disease_get / drug_get / variant_get / pdb | 40 s |
55
+ | trial_get / variant_trials | 45 s |
56
+ | gene_enrich | up to ~105 s (keep client tool timeouts >= 120 s) |
53
57
  | patent_search | 60 s |
54
58
  | patent_get | 120 s |
55
59
  | Per-source HTTP timeout (most sources) | 15 s |
@@ -75,6 +79,7 @@ Everything else: call sequentially, no timers.
75
79
  | `CROSSREF_EMAIL` | Crossref polite pool - faster citation metadata |
76
80
  | `EPO_OPS_CONSUMER_KEY` + `EPO_OPS_CONSUMER_SECRET` | EPO OPS patent backend: worldwide search + EP/WO claims (BOTH must be set together) |
77
81
  | `USPTO_API_KEY` | USPTO Open Data Portal application search backend |
82
+ | `OPENALEX_API_KEY` | `journal_metrics`: private per-key daily budget instead of the shared keyless OpenAlex pool (free key at openalex.org) |
78
83
 
79
84
  Set keys in the MCP client's env block (opencode: `environment`; Claude/
80
85
  Codex: `env`), then restart the client - config changes never apply live.
@@ -84,7 +89,7 @@ Codex: `env`), then restart the client - config changes never apply live.
84
89
  - Patents: US search works keyless via USPTO Public Search (ppubs default US
85
90
  backend); Google Patents is a best-effort fallback.
86
91
  - Drug regulatory/FAERS data works keyless (lower limits).
87
- - Literature works keyless across all five federated sources.
92
+ - Literature works keyless across all six federated sources.
88
93
 
89
94
  ## Integration notes
90
95