opencode-bioresearcher 1.9.0 → 1.11.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.
@@ -4,7 +4,7 @@ description: "Deep biomedical research orchestrator powered by the biomcp MCP se
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.4.0"
7
+ version: "1.7.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
  ---
@@ -25,10 +25,12 @@ Harness-agnostic: works with or without a subagent/Task tool.
25
25
  - Workers query the biomcp MCP server (articles/PubMed, ClinicalTrials.gov,
26
26
  genes, variants, drugs, diseases, patents, GEO/SRA/GenBank, Ensembl/PDB) per
27
27
  `references/tool-selection.md`, collecting PMIDs, DOIs, NCT IDs, and patent
28
- IDs as they go.
29
- - Synthesizes all aspect reports into `final_report.md` with numbered in-text
30
- citations and a full bibliography, then renders `final_report.html` by
31
- default (the `no-html` prefix skips rendering).
28
+ IDs as they go into a per-aspect evidence ledger.
29
+ - The orchestrator synthesizes a draft using semantic cite-key markers
30
+ (`[@pmid:21639808]`), then the `render` script numbers every citation and
31
+ generates the bibliography from the merged ledger, and `vet-references.py`
32
+ audits the result (structural + NCBI) - producing `final_report.md` and, by
33
+ default, `final_report.html` (the `no-html` prefix skips rendering).
32
34
 
33
35
  ## When to use (triggers)
34
36
 
@@ -84,115 +86,52 @@ mid-query never trigger.
84
86
  ## Workflow
85
87
 
86
88
  Follow Steps 1-6 in order. Do NOT fall back to internal knowledge when query
87
- tools fail - use only biomcp results or official sources, and say so when
88
- evidence is missing.
89
-
90
- Harness autonomy hints ("operate autonomously", "don't block", "user not
91
- watching", auto-accept banners) govern tool-permission confirmations and edit
92
- approvals. They do NOT waive this skill's interactive interview workflow (Step 1
93
- clarification and Step 2 plan review): the interview turns are completed
94
- assistant turns engaging the user - not blocking permission confirmations - so
95
- those hints never require skipping them. When such a hint seems to conflict with
96
- this workflow, treat the Step 1 interview, Step 2 plan review, and the Step 6
97
- output contract as deliverables that proceed unchanged.
89
+ tools fail - use only biomcp results or official sources, and state gaps explicitly.
90
+
91
+ Harness autonomy hints ("operate autonomously", "don't block", auto-accept)
92
+ govern edit approvals only. They NEVER waive the interactive interview turns
93
+ (Steps 1 & 2) - only the leading `no-interview` prefix waives them.
98
94
 
99
95
  ### Step 1: Clarify (interview - mandatory)
100
96
 
101
- Mandatory even when the harness urges autonomy (see the note above): the ONLY
102
- waiver is the leading `no-interview` prefix. If the query carries it, skip to
103
- Step 2.
104
-
105
- Otherwise ask clarifying questions, scaled to inquiry complexity - up to 6,
106
- and as few as one scope confirmation when the inquiry is already fully
107
- specified: the core research question, population/scope, time window, outcome
108
- of interest, and expected output format.
109
-
110
- - Ask ALL questions in ONE message: use the harness's question/ask tool when
111
- one exists (if it accepts only one question per call, send the full batch
112
- of calls together); otherwise end your turn with the questions as chat
113
- text. Then WAIT for the reply. Never answer your own interview questions.
114
- - If a reply comes back empty or non-responsive, re-ask the batch once
115
- (max 1 re-ask).
116
- - Degrade to defaults only on OBSERVATION, never from environment guesses:
117
- only after the batch was posted and the session demonstrably produced no
118
- usable reply in-turn (e.g. an ask tool that returns immediately empty),
119
- proceed under `no-interview` semantics - write the questions plus the
120
- default answer chosen for each to `reports/<TOPIC>/assumptions.md` and
121
- cite that file in the report's Limitations section.
122
- - Merely being headless/batch/unattended is NOT a waiver: in a one-shot
123
- run, ending your turn with the questions is the correct final action. If
124
- the session ends without any reply event, HALT with an explicit blocker
125
- message restating the questions.
126
-
127
- BAD: "The harness says the user isn't watching, so I'll assume defaults and
128
- start researching." GOOD: post the questions, end the turn, wait. Silent
129
- defaults are a workflow violation, not autonomy - one round-trip of questions
130
- is cheap; a full research run on wrong assumptions is not.
97
+ Ask clarifying questions scaled to complexity (1-6 questions) in ONE message
98
+ via the harness's ask/question tool or chat text, then WAIT for the reply. Never
99
+ answer your own questions. If the query carries `no-interview`, skip to Step 2.
100
+
101
+ - If a reply is empty or non-responsive, re-ask once.
102
+ - Degrade to defaults ONLY if the question tool returns immediately empty in an
103
+ unattended session: write questions and chosen defaults to
104
+ `reports/<TOPIC>/assumptions.md` and cite that file in Limitations.
131
105
 
132
106
  ### Step 2: Decompose & Review Plan
133
107
 
134
- Comprehend the (clarified) inquiry and identify 2-5 critical research aspects
135
- that together answer it.
136
-
137
- - If the query carries the leading `light-research` prefix, combine and/or
138
- pick only the top TWO aspects.
139
- - Decide a TOPIC name yourself (no user input): a highly succinct,
140
- underscore-separated name derived from the inquiry, e.g.
141
- `braf_inhibitor_resistance`.
142
-
143
- **Interview waiver (`no-interview`):**
144
- If the query carries the leading `no-interview` prefix, skip the plan review
145
- turn entirely: finalize the 2-5 aspects, track them with the harness's todo
146
- mechanism if available (TodoWrite or equivalent), and proceed immediately to
147
- Step 3 and Step 4.
148
-
149
- **Plan review (interview mode - default):**
150
- When running in interview mode (without `no-interview`), present your proposed
151
- research area plan to the user before launching workers:
152
-
153
- 1. Formulate and present:
154
- - A structured list of the 2-5 research aspects (or top 2 under
155
- `light-research`), each with an aspect title, 1-2 sentence focus summary,
156
- and primary tools/evidence sources (e.g. PubMed/articles,
157
- ClinicalTrials.gov, genes, drugs, patents).
158
- - An explicit prompt inviting user feedback and adjustments on these
159
- research areas.
160
- 2. End your turn with the plan proposal (using the harness's question/ask tool
161
- when available, or chat text) and WAIT for the user's reply. Do not spawn
162
- workers or create output directories before receiving user feedback.
108
+ Comprehend the inquiry and identify 2-5 critical research aspects (top 2 under
109
+ `light-research`). Decide a TOPIC name (succinct, underscore-separated, e.g.
110
+ `braf_inhibitor_resistance`). Each aspect's ABSTRACT defines INCLUSION and binding
111
+ EXCLUSION criteria per `references/analysis-methods.md`.
112
+
113
+ **Plan presentation budget:** keep the plan compact - one line per aspect (title,
114
+ focus, primary tools); never paste raw ABSTRACTs into the question UI.
115
+
116
+ **Plan review (default mode):**
117
+ 1. Present the 2-5 aspects to the user with tools/sources and invite feedback.
118
+ 2. End your turn (via ask tool or chat) and WAIT for the reply. Do not spawn
119
+ workers or create output directories before feedback.
163
120
  3. User feedback handling:
164
- - **Case A (approval / "looks good" / "proceed"):** Proceed directly to
165
- Step 3 and Step 4.
166
- - **Case B (default feedback - modifications without re-review request):**
167
- Incorporate the user's requested adjustments, additions, drops, or scope
168
- changes into the research aspects immediately (strictly adhering to the
169
- 2-5 aspect ceiling, or top 2 under `light-research`). Then **PROCEED
170
- DIRECTLY to Step 3 and Step 4. Do NOT ask for another round of
171
- confirmation.**
172
- - **Case C (special case - explicit re-confirmation requested):** ONLY if the
173
- user explicitly asks to review or confirm the revised plan (e.g. "show me
174
- the updated plan before starting" or "revise the plan and ask me again"),
175
- present the updated plan in a new turn and wait for confirmation before
176
- dispatching subagents (limit plan re-confirmations to at most 2 rounds).
177
- - **User inquiries during review:** If the user asks a clarifying question
178
- (e.g. "can we include pediatric trials?"), answer succinctly in 1-2
179
- sentences, incorporate the suggested scope into the relevant aspect, and
180
- proceed directly to Step 3 and Step 4 unless explicit re-confirmation was
181
- demanded.
182
-
183
- **Degrade to defaults on OBSERVATION:**
184
- Like Step 1, degrade only after the plan was posted and the session
185
- demonstrably produced no usable reply in-turn (e.g. an ask tool returning
186
- immediately empty in unattended/headless runs): proceed under the initial
187
- proposed plan, record the default plan in `reports/<TOPIC>/assumptions.md`,
188
- and cite that file in the report's Limitations section.
189
-
190
- Track the finalized aspect list with the harness's todo mechanism if available
191
- (TodoWrite or equivalent); otherwise keep it in working memory.
121
+ - **Approval / "proceed":** Proceed directly to Step 3 and Step 4.
122
+ - **Feedback / modifications:** Incorporate adjustments immediately and
123
+ PROCEED DIRECTLY to Step 3 and Step 4. Do NOT ask for another confirmation.
124
+ - **Explicit re-confirmation requested:** Only if the user explicitly asks to
125
+ review the revised plan, present it in a new turn (max 2 rounds).
126
+ 4. **Waiver / Degrade:** Skip plan review turn if query has `no-interview`, or
127
+ degrade per Step 1 rules if unattended (record plan in `assumptions.md`).
128
+
129
+ Track finalized aspects in the harness's todo tool (TodoWrite or equivalent).
192
130
 
193
131
  ### Step 3: Create the output directory
194
132
 
195
- Write a placeholder file to `reports/<TOPIC>/.gitkeep`. The write tool
133
+ Write the durable research plan to `reports/<TOPIC>/plan.md` (aspect list,
134
+ each aspect's ABSTRACT with boundaries, research items). The Write tool
196
135
  auto-creates parent directories - do NOT use bash mkdir for this.
197
136
 
198
137
  ### Step 4: Research each aspect
@@ -204,6 +143,13 @@ run the sequential tier below without fabrication - evidence gathering is
204
143
  unavailable until the server is wired (run the `bioresearcher-onboard`
205
144
  skill or see Prerequisites).
206
145
 
146
+ **Tier dispatch hierarchy:** When a subagent tool (`task` or `Task`) is
147
+ available in the harness, parallel worker dispatch (Tier A or Tier B) is
148
+ MANDATORY to maintain research parallelism and isolated worker contexts.
149
+ Subagents inherit all configured tools (biomcp, shell, filesystem) automatically;
150
+ do NOT dispatch exploratory probe tasks to test tool access.
151
+ Tier C is strictly a degraded fallback when no subagent tool exists.
152
+
207
153
  **Tier A - dedicated worker subagent (preferred when available):** if the
208
154
  harness offers the `bioresearcher-dr-worker` subagent type (installed with
209
155
  the bioresearcher Claude Code plugin; scoped name
@@ -214,11 +160,12 @@ worker reads `references/worker-protocol.md`, `references/tool-selection.md`,
214
160
  and `references/citations.md` itself at startup.
215
161
 
216
162
  **Tier B - generic subagent/Task tool:** assign each research aspect to one
217
- worker subagent, launched in parallel in batches of up to 5. Build each worker
218
- prompt from the template below. Inline into the prompt (workers may lack
219
- skill access): the worker rules, the per-domain tool cheatsheet from
220
- `references/tool-selection.md`, and the citation format summary from
221
- `references/citations.md`.
163
+ worker subagent, launched in parallel in batches of up to 5. Build each worker
164
+ prompt from the template below. Inline into the prompt (workers may lack
165
+ skill access): the worker rules, the per-domain tool cheatsheet from
166
+ `references/tool-selection.md`, the cite-key marker summary from
167
+ `references/citations.md`, and the evidence-verification discipline from
168
+ `references/analysis-methods.md`.
222
169
 
223
170
  Prompt template (Tiers A and B):
224
171
 
@@ -226,162 +173,183 @@ Prompt template (Tiers A and B):
226
173
  TOPIC: <TOPIC>
227
174
  YOUR RESEARCH FOCUS: <RESEARCH-ASPECT>
228
175
  DESCRIPTION: <ABSTRACT>
176
+ SKILL_DIR: <absolute path to this skill's directory> # Tier B only; a literal path string workers substitute into commands - NOT an env var
177
+ EXECUTION RULE: Do NOT read or inspect evidence-ledger.py or other skill scripts; all schemas and commands are fully specified here.
229
178
  ```
230
179
 
231
- ABSTRACT is <200 words describing the exact focus and a list of detailed
232
- research items.
180
+ ABSTRACT is <200 words describing the exact focus, a list of detailed
181
+ research items, and the aspect's inclusion definition + binding exclusion
182
+ criteria (negative examples welcome). Resolve `<skill_dir>`/`SKILL_DIR` to
183
+ the absolute path before dispatch, substituting it into every inlined
184
+ `<SKILL_DIR>` so Tier B workers never see a placeholder (both spellings
185
+ denote the same path; a path the worker cannot resolve is a tool the worker
186
+ does not have). Relay numeric caps from the user or plan into worker prompts
187
+ VERBATIM - they are binding, never loosened in translation.
233
188
 
234
189
  Record finished workers via the todo list. If subagents are stuck without
235
190
  progress for too long, prompt the user: "If subagents are stuck without
236
- progress for too long, interrupt and ask me to resume work." Restart failed
237
- workers as needed (retry <= 3 per worker).
238
-
239
- **Tier C - sequential (no subagent tool):**
240
-
241
- Process aspects one at a time in the main conversation. For each aspect, apply
242
- the same worker rules from `references/worker-protocol.md` (tool selection per
243
- `references/tool-selection.md`, citation discipline and the evidence ledger per
244
- `references/citations.md` and worker-protocol rule 8, retry <= 3, no
245
- re-delegation) and write the same per-aspect files (report + ledger). State
246
- which aspect is being worked on before starting each one.
247
-
248
- **All tiers, per aspect:**
249
-
250
- - Query biomcp tools per `references/tool-selection.md`; filter at the source
251
- (specific terms, `limit`, `sections`) rather than retrieving broadly.
252
- - Make MCP calls sequentially, not concurrently.
253
- - Collect identifiers for every source used: PMIDs/PMCIDs/DOIs (articles),
254
- NCT IDs (trials), patent IDs, accessions (GEO/SRA), database IDs
255
- (genes/drugs/variants).
256
- - Maintain the evidence ledger `reports/<TOPIC>/evidence/<ASPECT>.jsonl` per
257
- `references/worker-protocol.md` rule 8: after EACH biomcp call, append one
258
- record per potentially-citable source with fields copied verbatim from the
259
- tool result, batching all records from one tool result into a single
260
- `evidence-ledger.py add` call (never one call per record, never per-record
261
- scratch files); title-less records (LitSense hints) are enriched via
262
- `article_get(pmid)` before citing.
263
- - Write findings to `reports/<TOPIC>/<ASPECT>.md` (underscore-separated
264
- ASPECT name) with in-text citations [1], [2], ... and a bibliography whose
265
- entries are copied from the ledger.
266
-
267
- ### Step 5: Synthesize
191
+ progress for too long, interrupt and ask me to resume work."
192
+
193
+ **Tier C - sequential (strictly when no subagent tool exists):**
194
+ If the harness has no subagent tool (`task` / `Task`), process aspects one at a
195
+ time in the main conversation per `references/worker-protocol.md`.
196
+
197
+ **Worker completion gate (all tiers):**
198
+ When each worker finishes, before marking the aspect complete in the todo list, run:
199
+ ```bash
200
+ python3 <skill_dir>/scripts/evidence-ledger.py check \
201
+ reports/<TOPIC>/evidence/<ASPECT>.jsonl \
202
+ --markers reports/<TOPIC>/<ASPECT>.md
203
+ ```
204
+ - Exit 0: mark aspect complete in todo list.
205
+ - Exit 1:
206
+ - Trivial syntax/quarantine error in ledger: fix directly using Edit/Write.
207
+ - Missing records or unresolved markers: dispatch a top-up remediation worker
208
+ with the check diagnostic output per `references/worker-protocol.md` (max 2
209
+ remediation retries). Never guess or re-point IDs.
210
+ - If retries fail: strip the unresolved marker, qualify the claim in the
211
+ report with a caution note, log the failed ID in `## Evidence Gaps` and
212
+ `reports/<TOPIC>/assumptions.md`, and proceed.
213
+ - Without Bash/Python access: re-read the aspect ledger and confirm every marker
214
+ in `<ASPECT>.md` resolves to a ledger record before marking complete.
215
+
216
+ **Worker execution rules (summary):**
217
+ Query biomcp sequentially per `references/tool-selection.md`, append records to
218
+ `reports/<TOPIC>/evidence/<ASPECT>.jsonl` after each search using `evidence-ledger.py add`
219
+ (never invent values), and write findings with `[@key]` markers to `reports/<TOPIC>/<ASPECT>.md`
220
+ (no bibliography; PDB entries follow the dual-entity rule in `references/worker-protocol.md`).
221
+ See `references/worker-protocol.md` for full schemas.
222
+
223
+ ### Step 5: Synthesize (cite-key draft)
268
224
 
269
225
  Read all per-aspect reports. Summarize findings into a succinct, accurate
270
226
  final report addressing the user's inquiry, following the mandatory 6-section
271
227
  structure in `references/report-template.md` (Executive Summary, Data Sources,
272
- Analysis Methodology, Findings, Limitations, References) with full
273
- bibliography. Reconcile conflicting findings across aspects explicitly rather
274
- than silently dropping one side. Write the synthesized draft to
275
- `reports/<TOPIC>/final_report.md`.
228
+ Analysis Methodology, Findings, Limitations, References - the References
229
+ section itself is generated later by `render`). Reconcile conflicting findings
230
+ across aspects explicitly rather than silently dropping one side.
231
+
232
+ Write the synthesized draft to `reports/<TOPIC>/final_report.draft.md` citing
233
+ sources with the SAME semantic cite-key markers the workers used
234
+ (`[@pmid:21639808]`, `[@nct:NCT04280705]`, `[@chembl:CHEMBL1229517]`, groups
235
+ `[@a; @b]`). NEVER hand-number citations, never hand-write a References
236
+ section, and never write ad-hoc scripts to assemble the report - numbering and
237
+ bibliography come from `render` (Step 5b), which is the single numbering
238
+ authority.
239
+
240
+ When merging aspects, apply the evidence-verification discipline
241
+ (`references/analysis-methods.md`): rules 3-5 gate framework adherence -
242
+ findings that cannot be placed in the plan's framework go to Limitations with
243
+ a note, never into improvised categories; re-check rules 1-2 whenever
244
+ synthesis rewords a claim or transcribes a number from an aspect report.
276
245
 
277
246
  ### Step 5a: Merge + verify the evidence ledger
278
247
 
279
- Before composing the References section of `final_report.md`, consolidate
280
- and verify the per-aspect ledgers with the evidence-ledger script (fail-safe: network failure never
281
- blocks the report):
248
+ Consolidate and verify the per-aspect ledgers with the evidence-ledger script
249
+ (fail-safe: network failure never blocks the report):
282
250
 
283
251
  ```bash
284
252
  python3 <skill_dir>/scripts/evidence-ledger.py merge \
285
253
  -o reports/<TOPIC>/evidence/sources.jsonl 'reports/<TOPIC>/evidence/*.jsonl'
286
254
  python3 <skill_dir>/scripts/evidence-ledger.py verify \
287
255
  reports/<TOPIC>/evidence/sources.jsonl --apply
288
- python3 <skill_dir>/scripts/evidence-ledger.py keys \
289
- reports/<TOPIC>/evidence/sources.jsonl
290
- python3 <skill_dir>/scripts/evidence-ledger.py bib \
291
- reports/<TOPIC>/evidence/sources.jsonl --keys <comma-separated keys in citation order>
292
256
  ```
293
257
 
294
- - `merge` unions the per-aspect JSONLs (its own output and `_`-prefixed
295
- quarantine files are excluded automatically; malformed lines are
296
- quarantined to `evidence/_invalid.jsonl`).
258
+ - `merge` unions the per-aspect JSONLs (malformed lines quarantined to `_invalid.jsonl`).
297
259
  - `verify` cross-checks article records against NCBI esummary and backfills
298
- ONLY missing fields (epub-ahead-of-print records legitimately stay
299
- locator-less - render them without a volume/pages slot). It also sets
300
- titles on title-less records (e.g. LitSense hints the worker could not
301
- enrich).
302
- - Compose the References section of `final_report.md` by copying the `bib`
303
- output - do not re-type or paraphrase entries. Use the `keys` output (all
304
- ledger keys, sorted) to pick the citation-ordered `--keys` list for `bib`.
305
- When the script is unreachable (harnesses without filesystem access to
306
- `<skill_dir>`), re-read `reports/<TOPIC>/evidence/sources.jsonl` and transcribe
307
- entries from the records directly.
308
-
309
- ### Step 5b: Vet references (independent NCBI verification)
310
-
311
- After synthesizing `reports/<TOPIC>/final_report.md`, run the independent
312
- reference vetting script as the FINAL safety net - after the Step 5a ledger
313
- verification it is expected to be a near-no-op, but still run it:
260
+ missing fields (including authors, title, journal, locators). Records with
261
+ conflicting titles or DOIs are flagged with warnings and left unverified.
262
+ `--apply` mutates the ledger file in place; review changes via script output.
263
+
264
+ ### Step 5b: Render the final report (numbering authority)
265
+
266
+ ```bash
267
+ python3 <skill_dir>/scripts/evidence-ledger.py render \
268
+ reports/<TOPIC>/evidence/sources.jsonl reports/<TOPIC>/final_report.draft.md \
269
+ -o reports/<TOPIC>/final_report.md
270
+ ```
271
+
272
+ `render` numbers every cite-key marker by order of first appearance
273
+ (range-compressing groups), rewrites the markers in place, and appends the
274
+ References section generated from the merged ledger. Hard-fail contract
275
+ (exit 1, `final_report.md` NOT written): an unresolved citation key (with
276
+ did-you-mean suggestions), any record that would render `[MISSING ...]`, or
277
+ re-rendering an already-rendered document. On failure: fix the draft or the
278
+ ledger and re-render - citation numbers and bibliography entries are NEVER
279
+ edited by hand.
280
+
281
+ When the script is unreachable (harnesses without filesystem access to
282
+ `<skill_dir>`), deliver `final_report.draft.md` itself as the report artifact
283
+ (cite-keys stay readable and resolvable) and state the gap in the final
284
+ summary and Limitations - never hand-number citations as a workaround.
285
+
286
+ ### Step 5c: Vet references (structural audit + independent NCBI verification)
287
+
288
+ After `final_report.md` is rendered, run the independent vetting script as the
289
+ FINAL safety net:
314
290
 
315
291
  ```bash
316
292
  python3 <skill_dir>/scripts/vet-references.py reports/<TOPIC>/final_report.md --apply
317
293
  ```
318
294
 
319
- - **Fail-safe contract**: on API timeout, rate-limiting, or network failure, the
320
- script exits 0 and keeps pre-vetting citations unchanged. Non-PMID citations
321
- (clinical trials, patents, genes, web URLs) are automatically preserved.
322
- - If the script is unreachable (in harnesses without filesystem access to
323
- `<skill_dir>`), proceed directly to Step 6 without blocking.
324
- - When run without `--apply`, the script outputs clean correction suggestions
325
- for manual inspection before final HTML rendering.
295
+ - Layer 1 (offline, hard exit 1): in-text citations contiguous [1]..[N],
296
+ numbered by order of appearance, N == bibliography entry count, zero
297
+ `[MISSING ...]`/None/undefined placeholders.
298
+ - Layer 2 (fail-safe): on API timeout, rate-limiting, or network failure the
299
+ script exits 0 and keeps pre-vetting citations unchanged. Non-PMID
300
+ citations (clinical trials, patents, genes, web URLs) are preserved.
301
+ - Exit 1 means STOP: repair the draft or ledger, re-render, and re-vet.
302
+ - Warning disposition: every warning emitted during `verify` or `vet-references`
303
+ must be resolved (fixed in draft/ledger and re-rendered) or explicitly
304
+ justified in Limitations before Step 6.
305
+ - `--apply` mutates `final_report.md` in place; review printed `- OLD:` / `+ NEW:`
306
+ updates (or use `--diff` for unified diffs).
307
+ - If the script is unreachable, proceed to Step 6 with the rendered report and
308
+ state the gap in the final summary.
326
309
 
327
310
  ### Step 6: Write final report + HTML
328
311
 
329
312
  - Ensure `reports/<TOPIC>/final_report.md` is finalized and vetted.
330
- - Then render `reports/<TOPIC>/final_report.html` - ALWAYS by default,
331
- unless the query carries the leading `no-html` prefix or the user
332
- explicitly declined HTML. The markdown report is the complete deliverable;
333
- HTML is only a rendering, so never block finishing the session on it.
334
-
335
- Replace `<skill_dir>` with the full path to this skill's directory
336
- (`${CLAUDE_PLUGIN_ROOT}/skills/bioresearcher-deep-research` on Claude Code
337
- plugin installs; in harnesses that inject SKILL.md without filesystem
338
- access the script is unreachable - go straight to the gap step below).
339
- Run from the working directory containing `reports/<TOPIC>/` and anchor
340
- the output path to the `final_report.md` location:
313
+ - Then render `reports/<TOPIC>/final_report.html` (always by default, unless
314
+ `no-html` prefix was passed or user explicitly declined HTML).
315
+ The markdown report is the deliverable; HTML is only a rendering.
316
+
317
+ Anchor the output path to the `final_report.md` location:
341
318
 
342
319
  ```bash
343
320
  uv run --with markdown python <skill_dir>/scripts/markdown-to-html.py \
344
321
  reports/<TOPIC>/final_report.md -o reports/<TOPIC>/final_report.html
345
322
  ```
346
323
 
347
- Conversion ladder - attempt in order; a rung fails if its tool is missing,
348
- its command exits non-zero, or execution is denied; one attempt per rung,
349
- then fall through:
350
-
324
+ Conversion ladder (attempt in order; fall through on failure):
351
325
  1. `uv` on PATH: the command above.
352
- 2. `python3 -c "import markdown"` succeeds: run
353
- `python3 <skill_dir>/scripts/markdown-to-html.py` with the same args.
354
- 3. `pandoc` on PATH: `pandoc reports/<TOPIC>/final_report.md -o
355
- reports/<TOPIC>/final_report.html --standalone` (its styling differs
356
- from the script's GitHub-like CSS - that is not a failure).
357
- 4. No rung succeeded: keep markdown-only and state the gap explicitly in
358
- the final summary (the reason + the `bioresearcher-python-setup-uv`
359
- skill as remediation).
360
-
361
- Never install converters into the environment (no apt/pip/npm installs);
362
- `uv run --with` ephemeral overlays are the sanctioned exception. After a
363
- successful rung, verify `final_report.html` exists and is non-empty before
364
- declaring success. Do NOT read the full markdown into memory for the
365
- conversion - pass the file path. The final summary must name which
366
- artifacts exist and, when HTML is absent, why.
326
+ 2. `python3 -c "import markdown"` succeeds: run `python3 <skill_dir>/scripts/markdown-to-html.py reports/<TOPIC>/final_report.md -o reports/<TOPIC>/final_report.html`.
327
+ 3. `pandoc` on PATH: `pandoc reports/<TOPIC>/final_report.md -o reports/<TOPIC>/final_report.html --standalone`.
328
+ 4. None succeeded: keep markdown-only; state reason in summary and Limitations.
329
+
330
+ Never run apt/pip/npm installs; `uv run --with` ephemeral overlays are the
331
+ sanctioned exception. Verify `final_report.html` exists and is non-empty before
332
+ declaring success.
367
333
 
368
334
  ## Output layout
369
335
 
370
336
  ```
371
337
  reports/<TOPIC>/
372
- ├── .gitkeep
338
+ ├── plan.md # durable research plan (Step 3; boundaries live here)
373
339
  ├── evidence/
374
340
  │ ├── <aspect_1>.jsonl # per-aspect evidence ledger (worker-written)
375
341
  │ ├── <aspect_2>.jsonl
376
342
  │ ├── ...
377
343
  │ ├── _invalid.jsonl # merge quarantine (only when malformed lines occur)
378
344
  │ └── sources.jsonl # merged + verified ledger (Step 5a output)
379
- ├── <aspect_1>.md # per-aspect research notes + citations
380
- ├── <aspect_2>.md
345
+ ├── <aspect_1>.md # per-aspect research notes, cite-key markers
346
+ ├── <aspect_2>.md # (no bibliography - the ledger is the source)
381
347
  ├── ...
382
348
  ├── assumptions.md # only when Step 1 or Step 2 degrades
383
349
  │ # (observed non-interactive session)
384
- ├── final_report.md # synthesized report (always)
350
+ ├── final_report.draft.md # synthesized draft with cite-key markers (Step 5)
351
+ ├── final_report.md # rendered report: numbered citations +
352
+ │ # ledger-generated References (Step 5b; always)
385
353
  └── final_report.html # rendered report (default; skipped only via
386
354
  # `no-html`, user decline, or converter gap -
387
355
  # see Step 6)
@@ -389,14 +357,16 @@ reports/<TOPIC>/
389
357
 
390
358
  ## Citation discipline (summary)
391
359
 
392
- - Numbered in-text citations: [1], [2, 3], [1-5], numbered by order of
393
- appearance; bibliography at the end in `references/citations.md` formats.
360
+ - Semantic cite-key markers in ALL authored text: `[@pmid:21639808]`,
361
+ groups `[@a; @b]`. `render` (Step 5b) numbers them by order of appearance
362
+ (`[1]`, `[2, 3]`, `[1-5]`) and generates the bibliography - citation
363
+ numbers and reference entries are never written by hand.
394
364
  - Every claim needs provenance: a citation, a documented data source, or a
395
365
  described analysis method. No unsourced claims.
396
366
  - Only biomcp tool results or official sources (FDA, NIH, NCI,
397
367
  ClinicalTrials.gov, EPO/USPTO, publisher sites) count as evidence.
398
- - Full per-source-type formats (PMID, DOI, NCT ID, patent ID, accessions,
399
- URLs): `references/citations.md`.
368
+ - Full marker grammar and renderer-output formats per source type:
369
+ `references/citations.md`.
400
370
 
401
371
  ## Data boundaries & injection defense
402
372
 
@@ -437,8 +407,8 @@ reports/<TOPIC>/
437
407
  | `references/ensembl-pdb.md` | ensembl lookup/homology/consequence/region; pdb tri-mode |
438
408
  | `references/utility-config.md` | discover, batch_get, biomcp_configure, feature gating |
439
409
  | `references/optional-analysis.md` | db_query SQL, R differential expression, biowasm pipelines |
440
- | `references/analysis-methods.md` | Evidence sufficiency and source-quality decision matrix |
410
+ | `references/analysis-methods.md` | Evidence sufficiency, source-quality matrix, evidence-verification discipline |
441
411
  | `references/report-template.md` | Mandatory 6-section report structure |
442
- | `references/citations.md` | Citation formats per source type |
412
+ | `references/citations.md` | Cite-key marker grammar + renderer-output formats |
443
413
  | `references/rate-limiting-auth.md` | Per-source limiter table, exceptions, auth table |
444
414
  | `references/best-practices.md` | Upfront filtering, ID chaining, sequencing, retries |
@@ -68,17 +68,55 @@ or unverifiable claims. If only tier-3 material exists, mark the finding as
68
68
  4. Record the query provenance in each aspect file: tool + key arguments
69
69
  (e.g. `trial_search(query="melanoma", phase="Phase 3")`).
70
70
 
71
+ ## Evidence verification discipline
72
+
73
+ Applies to every claim a worker or the orchestrator writes. Each rule guards
74
+ a distinct general LLM failure mode. Topic-specific inclusion/exclusion
75
+ boundaries are authored per-run by the orchestrator into each aspect
76
+ ABSTRACT; these rules govern how workers apply any such criteria.
77
+
78
+ 1. Direction of causality: keyword overlap is not direction. Verify the
79
+ cited source shows the direction asserted (causes vs prevents/attenuates
80
+ vs merely correlates / serves as a marker) before using it for a causal
81
+ claim - protective and causal findings share vocabulary.
82
+ 2. Quantitative fidelity: tie every number (effect size, rate, count,
83
+ percent) to its specific source record at capture time, keyed by its
84
+ ledger key; never transcribe a value for one entity from prose about a
85
+ related entity - dense multi-entity summaries invite cross-contamination.
86
+ 3. Criterion vs keyword: matching the search terms is not satisfying the
87
+ research criterion. Check the source shows the entity meets the aspect's
88
+ inclusion definition; exclusion criteria in the plan are binding, and
89
+ keyword-matching candidates that fail them are noted as excluded, never
90
+ admitted to boost yield.
91
+ 4. Axis discipline: when the plan classifies findings along an axis, every
92
+ admitted finding must genuinely instantiate that axis; observations of a
93
+ different kind attach as secondary attributes, never as improvised
94
+ categories (e.g. an organism-level endpoint vs a molecular mechanism in
95
+ a mechanistic survey, or a legal-claim scope vs a technical feature in a
96
+ patent analysis). New categories are a plan change (orchestrator +
97
+ user), not a per-finding decision.
98
+ 5. Primary vs downstream: when attributing an effect to a mechanism, verify
99
+ the source establishes it as the initiating/primary cause rather than a
100
+ downstream consequence or a late-stage marker of an upstream process -
101
+ cascades share endpoints, so late-stage observations do not localize
102
+ origins.
103
+
71
104
  ## Synthesis rules (orchestrator)
72
105
 
73
106
  1. Read ALL aspect files before writing the final report.
74
107
  2. Structure findings by research question, not by aspect file order, when
75
108
  the aspects overlap.
76
- 3. Re-number citations across aspects into one bibliography for
77
- final_report.md.
109
+ 3. Cite with the workers' semantic cite-key markers in
110
+ `final_report.draft.md`; numbering and the bibliography come from
111
+ `render` (SKILL.md Step 5b) - never hand-number.
78
112
  4. Contradictions between aspects: present both with sources and, if
79
113
  unresolvable, list under Limitations.
80
114
  5. Confidence marking: state High/Medium/Low confidence per key finding
81
115
  based on source count and tier.
116
+ 6. Apply the evidence-verification discipline at merge time: rules 3-5 gate
117
+ framework adherence (unplaceable findings go to Limitations, never into
118
+ improvised categories); re-check rules 1-2 whenever synthesis rewords a
119
+ claim or transcribes a number from an aspect report.
82
120
 
83
121
  ## Failure modes
84
122
 
@@ -97,9 +97,9 @@ sessions rot the context and garble titles, years, and locators.
97
97
  missing fields are null, never invented).
98
98
  - Title-less hint records (LitSense) get enriched via `article_get(pmid)`
99
99
  before they may be cited.
100
- - Write the bibliography by RE-READING the ledger and copying fields - the
101
- ledger is the single source of truth for every References entry; the
102
- orchestrator merges + verifies it at Step 5a before the final report.
100
+ - Cite with `[@key]` markers; bibliography entries are GENERATED by
101
+ `evidence-ledger.py render` from the merged ledger (Step 5b) - never
102
+ hand-copied, hand-numbered, or hand-composed.
103
103
 
104
104
  ## 9. Data validation before writing
105
105
 
@@ -114,5 +114,5 @@ correct), arrays non-empty, dates plausible, and values in sane ranges.
114
114
  - [ ] IDs chained via tool cross-links, not re-searched
115
115
  - [ ] Calls sequential; no sleep timers (except HPA/GEO-download exceptions)
116
116
  - [ ] Retries capped at 3; gaps recorded
117
- - [ ] Evidence ledger updated after each call; bibliography copied from it
118
- - [ ] Findings + identifiers written to the aspect file
117
+ - [ ] Evidence ledger updated after each call and passing `check --markers <aspect>.md` (exit 0; Tier A no Bash: re-read the ledger and match the markers manually)
118
+ - [ ] Findings + `[@key]` cite markers written to the aspect file