---
name: yogsoth-ai/paper-fetch
source: https://app.decimal.ai/s/yogsoth-ai-paper-fetch@1/SKILL.md
source_sha256: a8705c30ad3b
---

# Paper Fetch

If the caller already has the paper — a local `.md`/`.txt`/`.pdf` path, or a direct
HTTP(S) PDF URL (path ends in `.pdf`, ignoring query and fragment) — read it
directly before considering any search route. Record `source_channel` as
`local_file`, `local_pdf`, or `direct_pdf`. If the read fails, return `not_found`
and do not fall back to alphaxiv, Semantic Scholar, bioRxiv, or medRxiv.

The pipeline's sole entry point: retrieves a paper and lands it on disk. It checks
the cache first, reads already-identified sources (local files, direct PDF URLs)
with no search at all, and otherwise uses the fixed fallback (alphaxiv → Semantic
Scholar routing → bioRxiv/medRxiv → not_found).
Decoupled from `literature-engine`'s `literature-research`/`literature-search`/
`literature-overview` — this SOP holds its own retrieval calls rather than delegating.

## Why an already-supplied file still enters through this SOP

Skipping straight to a reading SOP with the caller's own path looks like it saves
a step, but 13 downstream SOPs take `meta_path` and read only section line ranges
(`star-awarding` reads method + results; `first-pass-skim`'s "headings only, never
bodies" constraint holds *because* it is handed shallow ranges). A bare path
carries no index, and a bare `.pdf` carries no extracted text at all.

So the thing to skip is the **four-channel search**, not the landing and indexing.
That is what Step 1 does: no network lookup, same landing step, same output
contract. Tactics keep passing `paper_ref` through unchanged and never learn there
was a new input form.

## Landed layout

```
context/papers/<timestamp>-<title-slug>/
  source.md            the paper, as fetched
  source.meta.json     metadata + line-number section index
```

All landed filenames are lowercase. `<title-slug>` is lowercased, non-alphanumerics collapsed to hyphens, Windows-illegal characters (`: * ? " < > |`) stripped, truncated to 60 chars against path-length limits.

## Execution

Subagent — spawned via spawn-agent skill.

## Why Subagent

Multi-step retrieval with direct-PDF handling and domain-inference judgment calls
(is a Semantic-Scholar miss a bio signal or a "just not indexed anywhere" signal?)
benefits from a dedicated context that can hold the whole decision tree without the
noise of whatever task will consume its output next.

## Why it lands files instead of returning text

A paper runs 60-80k tokens. Returning it as `full_text` means every downstream SOP pays that cost again, and the orchestrating tactic carries it in its own window on top. Landing it once and returning a path means: re-reading the same paper across tactics costs one cache check rather than one fetch; SOPs that need only part of the paper read only that part; the orchestrator holds paths, not text.

## Why a section index, not pre-cut slices

`source.meta.json` records where each section *is* (line ranges) rather than shipping pre-cut slices. Slicing is a per-consumer concern — `unit-segmentation` already declares `scope: full_text | abstract | intro_only`, `research-question-appraisal` wants intro + abstract, `engineering-config-grading` wants method + experiments + appendix. Pre-cutting would mean this SOP has to know every downstream SOP's definition of "the part I need", and would need editing every time one is added. An index is neutral: consumers do their own offset reads against `source.md`.

This also makes `first-pass-skim`'s defining constraint (skim headings and captions, never section bodies) hold by construction rather than by self-restraint — it is handed line ranges for the shallow parts only.

## Cache lookup is by identifier, not directory name

Directories are named `<timestamp>-<title-slug>`, but `paper_ref` may arrive as an arXiv ID, a DOI, a URL, a local file path, or a title, and matching an arXiv ID against a title-derived directory name fails. So the lookup scans `context/papers/*/source.meta.json` and matches on `identifier` or `title_slug` — both are recorded precisely so any form of `paper_ref` resolves. For a local file, `identifier` is its absolute path, so re-running a tactic on the same file is a cache hit rather than a second copy.

Matching tolerates case and punctuation differences in titles but is deliberately not fuzzy: a missed cache hit costs one redundant fetch, while a false hit silently reads the wrong paper for the rest of the pipeline.

## Why Not Built on literature-engine

`literature-overview`/`literature-search`/`literature-research` already have an alphaxiv-primary/SS-supplementary pattern, but none has a bioRxiv/medRxiv branch or an explicit "can't retrieve → halt" contract, and this package is deliberately decoupled from that pipeline's scope (see `context/2026-08-07-15-15-paper-fetch-sop-design.md` and spec §9). Do not refactor this SOP to import those skills later without revisiting that decision explicitly.

## Full design reference

`context/2026-08-07-15-15-paper-fetch-sop-design.md` — the channel decision-flow rationale (why alphaxiv's coverage list is the domain signal, why an SS miss still routes to bio rather than dead-ending). The landing / index / cache design is in `context/2026-08-07-23-01-sop-io-contract-simulation.md` §4, option C.

<!-- BEGIN available-tables (generated) -->

## Available SOPs

Optional, no fixed order; the final leaf is always a sop.

| SOP | When to use |
| --- | --- |
| spawn-agent | Spawn a customized CC subagent with full MCP tool access. |

<!-- END available-tables (generated) -->