Full-Paper Markdown Reader — Router Routing protocol First distinguish creating a reader from answering a question or translating an excerpt. For a source-linked question, read and inspect only the relevant source material; reuse existing source-map IDs when available. Do not regenerate the reader or require a full source map before answering. For an explicit excerpt request, apply extraction, translation, and grounding rules to that excerpt. The full-artifact workflow below applies when the user requests a reader or full-paper translation. For a new task, load the core and matching resources…

is not balanced.\",\r\n line_number(text, offset),\r\n )\r\n return None\r\n\r\n\r\ndef validate_markdown(text: str) -> tuple[list[Finding], list[str], list[str]]:\r\n findings: list[Finding] = []\r\n fence_ranges, math_fence_ranges, fence_findings = fenced_ranges(text)\r\n findings.extend(fence_findings)\r\n without_fences = mask_ranges(text, fence_ranges)\r\n\r\n display_ranges, display_findings = display_math_ranges(without_fences)\n findings.extend(display_findings)\n\n normalized_displays: dict[str, list[int]] = {}\n for start, end in display_ranges:\n body = without_fences[start + 2 : end - 2].strip()\n normalized = re.sub(r\"\\s+\", \"\", body).rstrip(\",.;\")\n if normalized:\n normalized_displays.setdefault(normalized, []).append(start)\n for offsets in normalized_displays.values():\n if len(offsets) > 1:\n findings.append(\n Finding(\n \"WARN\",\n \"DUPLICATE_DISPLAY_EQUATION\",\n \"The same display equation appears more than once; use one shared E... block for the bilingual pair.\",\n line_number(text, offsets[1]),\n )\n )\n\n prose = mask_ranges(without_fences, display_ranges)\n\r\n inline_problem = find_inline_dollar_problem(prose)\r\n if inline_problem:\r\n findings.append(inline_problem)\r\n\r\n # Mask inline math before looking for raw commands in prose.\r\n inline_tokens = list(re.finditer(r\"(?\u003c!\\\\)(?\u003c!\\$)\\$(?!\\$)\", prose))\r\n inline_ranges = [\r\n (inline_tokens[i].start(), inline_tokens[i + 1].end())\r\n for i in range(0, len(inline_tokens) - 1, 2)\r\n ]\r\n plain_prose = mask_ranges(prose, inline_ranges)\r\n for match in LATEX_COMMAND_RE.finditer(plain_prose):\n findings.append(\n Finding(\r\n \"FAIL\",\r\n \"BARE_LATEX\",\r\n f\"LaTeX command '{match.group(0)}' appears outside a math block.\",\r\n line_number(text, match.start()),\r\n )\n )\n\n for line_match in CHINESE_LINE_RE.finditer(plain_prose):\n line_text = line_match.group(0)\n if \"\\t\" in line_text:\n findings.append(\n Finding(\n \"FAIL\",\n \"TAB_IN_CHINESE_MATH_PROSE\",\n \"A tab appears in a Chinese line; this can indicate a corrupted command such as \\\\tau.\",\n line_number(text, line_match.start()),\n )\n )\n for pseudo_match in PAREN_PSEUDO_MATH_RE.finditer(line_text):\n findings.append(\n Finding(\n \"FAIL\",\n \"PARENTHESIZED_PSEUDO_MATH\",\n f\"Use math delimiters instead of ordinary parentheses: {pseudo_match.group(0)!r}.\",\n line_number(text, line_match.start() + pseudo_match.start()),\n )\n )\n\r\n anchors = EQUATION_ANCHOR_RE.findall(text)\r\n duplicates = sorted({item for item in anchors if anchors.count(item) > 1})\r\n for equation_id in duplicates:\r\n findings.append(\r\n Finding(\"FAIL\", \"DUPLICATE_EQUATION_ID\", f\"Duplicate equation anchor: {equation_id}.\")\r\n )\r\n\r\n if anchors:\r\n numeric = [int(item[1:]) for item in anchors]\r\n expected = list(range(1, len(numeric) + 1))\r\n if numeric != expected:\r\n findings.append(\r\n Finding(\r\n \"WARN\",\r\n \"NONSEQUENTIAL_EQUATION_IDS\",\r\n \"Equation anchors should follow reading order without gaps: E001, E002, ...\",\r\n )\r\n )\r\n\r\n display_count = len(display_ranges) + len(math_fence_ranges)\r\n if display_count and not anchors:\r\n findings.append(\r\n Finding(\r\n \"FAIL\",\r\n \"MISSING_EQUATION_ANCHORS\",\r\n \"Display equations exist, but paper.md has no E... anchors.\",\r\n )\r\n )\r\n if display_count >= 3 and not re.search(r\"^#{1,6}\\s+(?:公式索引|Equation Index)\\s*$\", text, re.MULTILINE | re.IGNORECASE):\r\n findings.append(\r\n Finding(\r\n \"WARN\",\r\n \"MISSING_EQUATION_INDEX\",\r\n \"Three or more display equations require an equation index.\",\r\n )\r\n )\r\n\r\n image_paths = [match.group(1).strip().split()[0].strip(\"\u003c>\") for match in MARKDOWN_IMAGE_RE.finditer(text)]\r\n return findings, anchors, image_paths\r\n\r\n\r\ndef equation_entries(data: dict[str, Any]) -> list[dict[str, Any]]:\r\n entries: dict[str, dict[str, Any]] = {}\r\n for item in data.get(\"blocks\", []):\r\n if isinstance(item, dict) and item.get(\"type\") == \"equation\" and isinstance(item.get(\"id\"), str):\r\n entries[item[\"id\"]] = item\r\n for item in data.get(\"equations\", []):\r\n if isinstance(item, dict) and isinstance(item.get(\"id\"), str):\r\n entries[item[\"id\"]] = {**entries.get(item[\"id\"], {}), **item}\r\n return list(entries.values())\r\n\r\n\r\ndef validate_source_map(\r\n source_map_path: Path, anchors: list[str], markdown_image_paths: list[str]\r\n) -> list[Finding]:\r\n findings: list[Finding] = []\r\n try:\r\n data = json.loads(source_map_path.read_text(encoding=\"utf-8\"))\r\n except (OSError, json.JSONDecodeError) as exc:\r\n return [Finding(\"FAIL\", \"INVALID_SOURCE_MAP\", f\"Cannot parse source map: {exc}\")]\r\n\r\n if not isinstance(data, dict):\r\n return [Finding(\"FAIL\", \"INVALID_SOURCE_MAP\", \"Source map root must be a JSON object.\")]\r\n\r\n entries = equation_entries(data)\r\n map_ids = [item.get(\"id\") for item in entries]\r\n duplicates = sorted({item for item in map_ids if map_ids.count(item) > 1})\r\n for equation_id in duplicates:\r\n findings.append(Finding(\"FAIL\", \"DUPLICATE_SOURCE_MAP_ID\", f\"Duplicate source-map ID: {equation_id}.\"))\r\n\r\n for item in entries:\r\n equation_id = item.get(\"id\")\r\n if not isinstance(equation_id, str) or not EQUATION_ID_RE.fullmatch(equation_id):\r\n findings.append(Finding(\"FAIL\", \"INVALID_EQUATION_ID\", f\"Invalid equation ID: {equation_id!r}.\"))\r\n continue\r\n if equation_id not in anchors:\r\n findings.append(\r\n Finding(\r\n \"FAIL\",\r\n \"SOURCE_MAP_ORPHAN\",\r\n f\"Source-map equation {equation_id} has no matching paper.md anchor.\",\r\n )\r\n )\r\n if not isinstance(item.get(\"page\"), int) or item[\"page\"] \u003c 1:\r\n findings.append(Finding(\"FAIL\", \"MISSING_PAGE\", f\"{equation_id} needs a positive page number.\"))\r\n if item.get(\"confidence\") not in {\"high\", \"medium\", \"low\"}:\r\n findings.append(\r\n Finding(\"FAIL\", \"MISSING_CONFIDENCE\", f\"{equation_id} needs high, medium, or low confidence.\")\r\n )\r\n latex = item.get(\"latex\")\r\n image_path = item.get(\"image_path\")\r\n if not (isinstance(latex, str) and latex.strip()) and not (\r\n isinstance(image_path, str) and image_path.strip()\r\n ):\r\n findings.append(\r\n Finding(\"FAIL\", \"MISSING_REPRESENTATION\", f\"{equation_id} needs latex or image_path.\")\r\n )\r\n if isinstance(image_path, str) and image_path.strip():\r\n candidate = (source_map_path.parent / image_path).resolve()\r\n if not candidate.is_file():\r\n findings.append(\r\n Finding(\"FAIL\", \"MISSING_EQUATION_IMAGE\", f\"{equation_id} image does not exist: {image_path}.\")\r\n )\r\n if image_path not in markdown_image_paths:\r\n findings.append(\r\n Finding(\r\n \"FAIL\",\r\n \"UNUSED_EQUATION_IMAGE\",\r\n f\"{equation_id} image_path is not displayed in paper.md: {image_path}.\",\r\n )\r\n )\r\n\r\n for equation_id in anchors:\r\n if equation_id not in map_ids:\r\n findings.append(\r\n Finding(\r\n \"FAIL\",\r\n \"MISSING_SOURCE_MAP_ENTRY\",\r\n f\"paper.md equation {equation_id} has no matching source-map equation entry.\",\r\n )\r\n )\r\n return findings\r\n\r\n\r\ndef run_validation(paper_path: Path, source_map_path: Path | None) -> list[Finding]:\r\n try:\r\n text = paper_path.read_text(encoding=\"utf-8\")\r\n except OSError as exc:\r\n return [Finding(\"FAIL\", \"UNREADABLE_MARKDOWN\", f\"Cannot read paper.md: {exc}\")]\r\n findings, anchors, image_paths = validate_markdown(text)\r\n if source_map_path is not None:\r\n findings.extend(validate_source_map(source_map_path, anchors, image_paths))\r\n elif anchors:\r\n findings.append(\r\n Finding(\r\n \"WARN\",\r\n \"SOURCE_MAP_NOT_CHECKED\",\r\n \"Equation anchors exist, but --source-map was not provided.\",\r\n )\r\n )\r\n return findings\r\n\r\n\r\ndef self_test() -> int:\r\n with tempfile.TemporaryDirectory() as directory:\r\n root = Path(directory)\r\n (root / \"assets/equations\").mkdir(parents=True)\r\n (root / \"assets/equations/E002.png\").write_bytes(b\"test\")\r\n good_markdown = \"\"\"# Paper\r\n\u003ca id=\"E001\">\u003c/a>\r\n**Source:** p.1 E001 · Eq. (1)\r\n\r\n$\n\\\\frac{a}{b} = c\n$\n\n**中文:** 其中 $a$、$b$ 和 $c$ 保持原始数学符号。\n\n\u003ca id=\"E002\">\u003c/a>\n**Source:** p.2 E002 · low confidence\r\n\r\n![Original equation E002](assets/equations/E002.png)\r\n\"\"\"\r\n good_map = {\r\n \"blocks\": [\r\n {\"id\": \"E001\", \"type\": \"equation\", \"page\": 1, \"confidence\": \"high\", \"latex\": \"\\\\\\\\frac{a}{b}=c\", \"image_path\": None},\r\n {\"id\": \"E002\", \"type\": \"equation\", \"page\": 2, \"confidence\": \"low\", \"latex\": None, \"image_path\": \"assets/equations/E002.png\"},\r\n ]\r\n }\r\n paper = root / \"paper.md\"\r\n source_map = root / \"source_map.json\"\r\n paper.write_text(good_markdown, encoding=\"utf-8\")\r\n source_map.write_text(json.dumps(good_map), encoding=\"utf-8\")\r\n good_findings = run_validation(paper, source_map)\r\n if good_findings:\r\n print(\"Self-test failed: valid fixture was rejected.\", file=sys.stderr)\r\n for item in good_findings:\r\n print(asdict(item), file=sys.stderr)\r\n return 1\r\n\r\n bad_markdown = \"\"\"# Broken\r\n\u003ca id=\"E001\">\u003c/a>\nRaw formula: \\\\frac{a}{b}\n**中文:** 其中 (I_0) 为峰值强度。\n$\nx+y\n\"\"\"\n paper.write_text(bad_markdown, encoding=\"utf-8\")\r\n bad_findings = run_validation(paper, None)\r\n bad_codes = {item.code for item in bad_findings if item.severity == \"FAIL\"}\r\n required = {\"BARE_LATEX\", \"UNBALANCED_DISPLAY_MATH\", \"PARENTHESIZED_PSEUDO_MATH\"}\n if not required.issubset(bad_codes):\r\n print(f\"Self-test failed: missing expected failures {sorted(required - bad_codes)}.\", file=sys.stderr)\r\n return 1\r\n\r\n print(\"Self-test passed.\")\r\n return 0\r\n\r\n\r\ndef parse_args() -> argparse.Namespace:\r\n parser = argparse.ArgumentParser(description=__doc__)\r\n parser.add_argument(\"paper\", nargs=\"?\", type=Path, help=\"Path to paper.md\")\r\n parser.add_argument(\"--source-map\", type=Path, help=\"Path to source_map.json\")\r\n parser.add_argument(\"--strict\", action=\"store_true\", help=\"Treat warnings as validation failures\")\r\n parser.add_argument(\"--json\", action=\"store_true\", dest=\"json_output\", help=\"Print machine-readable JSON\")\r\n parser.add_argument(\"--self-test\", action=\"store_true\", help=\"Run built-in valid and invalid fixtures\")\r\n args = parser.parse_args()\r\n if not args.self_test and args.paper is None:\r\n parser.error(\"paper is required unless --self-test is used\")\r\n return args\r\n\r\n\r\ndef main() -> int:\r\n args = parse_args()\r\n if args.self_test:\r\n return self_test()\r\n\r\n findings = run_validation(args.paper, args.source_map)\r\n failed = any(item.severity == \"FAIL\" or (args.strict and item.severity == \"WARN\") for item in findings)\r\n payload = {\r\n \"ready\": not failed,\r\n \"strict\": args.strict,\r\n \"summary\": {\r\n \"fail\": sum(item.severity == \"FAIL\" for item in findings),\r\n \"warn\": sum(item.severity == \"WARN\" for item in findings),\r\n },\r\n \"findings\": [asdict(item) for item in findings],\r\n }\r\n if args.json_output:\r\n print(json.dumps(payload, ensure_ascii=False, indent=2))\r\n elif findings:\r\n for item in findings:\r\n location = f\" line {item.line}\" if item.line else \"\"\r\n print(f\"[{item.severity}] {item.code}{location}: {item.message}\")\r\n print(f\"Ready: {'yes' if not failed else 'no'}\")\r\n else:\r\n print(\"No math validation findings. Ready: yes\")\r\n return 1 if failed else 0\r\n\r\n\r\nif __name__ == \"__main__\":\r\n raise SystemExit(main())\r\n","content_type":"text/x-python; charset=utf-8","language":"python","size":17840,"content_sha256":"252c6d0998801d24a459e40e48a4125c4a07b8ee639bb28fab8e0f3c5a2b66f1"},{"filename":"static/core/output-contract.md","content":"# Output contract\n\nPrefer these outputs:\n\n- `paper.md` for the full-paper Markdown artifact\n- `source_map.json` for stable source anchors\n- `translation_notes.md` for terminology, uncertainty, and layout notes\n- `assets/` for extracted figures, tables, and equation crops when needed\n- `reader.html` only when the user explicitly wants a browser preview\n\nDo not hide missing information. If the source is incomplete, label the output as draft mode.\n\n## Pre-response verification\n\nBefore final response, verify:\n\n- `paper.md` contains `**Original:**` and `**中文:**` block pairs\n- every image/table link used in `paper.md` exists under `assets/`\n- every figure/table in `assets/` has a corresponding Markdown block and source pointer\n- display equations render inside `$...$` (or a fenced `math` block), and inline equations render inside `$... nature-reader — Skillopedia \n- mathematical content is unchanged across the bilingual explanation: only prose is translated, each display equation is shown once, and Chinese text never uses `(I_0)`-style pseudo-math\n- no bare LaTeX commands such as `\\\\frac`, `\\\\sum`, or `\\\\begin{...}` appear as ordinary prose\n- every display equation has an `E...` anchor and a matching equation entry in `source_map.json`\n- every low-confidence or image-only equation points to an existing file under `assets/equations/`\n- `source_map.json` parses as JSON and includes source block IDs\n- `translation_notes.md` records skipped, uncertain, or draft-mode content\n\nRun the deterministic math check before delivery:\n\n```bash\npython scripts/validate_reader_math.py paper.md --source-map source_map.json\n```\n\nAdd `--strict` for a published or reusable artifact. The command checks delimiters, bare LaTeX, equation IDs, source-map linkage, and equation fallback paths.\n\n## Tooling guidance\n\n- If the input is a PDF, load the `pdf` skill first for extraction and OCR guidance.\n- If the user asks for a richer browser view, use `web-artifacts-builder` or `frontend-design` only as a preview layer on top of the Markdown workflow.\n- If the user wants citation-level grounding to original text, keep the source map explicit and do not lose the page or block IDs.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2159,"content_sha256":"05d1ffda81d01c3241a7ff6ff3574243c3c967da942f3cd0f0fa12c32891be26"},{"filename":"static/core/principles.md","content":"# Core principles (reader)\n\nUse this skill to turn a research paper into a complete Markdown reading artifact. The default output should read like a bilingual paper companion, not a summary dump:\n\n- keep the extractable prose, paragraph structure, and section flow\n- show original text and Chinese translation together at block level\n- extract figures and tables as assets and place them at the first substantive mention or interpretation point\n- render equations as Markdown math with stable equation anchors; never expose bare LaTeX commands as ordinary prose\n- keep captions attached to figures/tables with English caption text and Chinese caption translation\n- preserve stable page and block anchors for traceability\n- write a complete `paper.md` by default, plus `source_map.json`, `translation_notes.md`, and `assets/`\n\nThis skill is for papers, preprints, and conference proceedings across disciplines. It is not limited to Nature-family journals. Honor an explicit request for a summary, excerpt, or source-linked answer at that scope; no separate summarization skill is required. Citation-only searches belong to the appropriate citation workflow.\n\n## Non-negotiable defaults\n\nWhen the user requests a reader, `中英文对照`, `原文对照`, `全文翻译`, or invokes `nature-reader` without a narrower deliverable, produce a paragraph-level bilingual reader by default. An explicit question, summary, or excerpt request takes precedence; do not expand it into full-paper processing.\n\nDo not replace the reader with:\n\n- a Chinese-only summary\n- a paper review without original/translation alignment\n- figure captions without figure/table crops\n- a list of key points detached from source locations\n- only the abstract, introduction, or selected highlights\n\nIf constraints prevent full processing, still create a draft reader and clearly label missing pages, missing figures/tables, untranslated blocks, or low-confidence OCR/crops in `translation_notes.md`.\n\n## Core principle\n\nTranslate for meaning, not for style. Preserve the paper's structure, evidence, hedging, terminology, equations, units, and citation markers. Keep the output in prose paragraphs unless the source itself is tabular or list-like. Do not collapse the paper into keyword bullets or slide-style notes.\n\nEquations are first-class source blocks. Give every display equation an `E001`, `E002`, ... anchor and put valid inline math inside `$... nature-reader — Skillopedia or display math inside `$...$`. If the expression cannot be transcribed confidently, crop the original formula into `assets/equations/`, show that image in `paper.md`, and label any best-effort LaTeX as low confidence. Never guess missing symbols or leave commands such as `\\\\frac` and `\\\\sum` outside a math delimiter.\n\nThe reading file should help a reader move between:\n\n- original text\n- translated text\n- source location\n- figure or table evidence\n\nEach substantive source block should have a stable anchor and a visible bilingual pair:\n\n```markdown\n\u003ca id=\"S001\">\u003c/a>\n**Source:** p.1 S001\n\n**Original:** [source paragraph]\n\n**中文:** [faithful Chinese translation]\n```\n\n## Copyright caution\n\nFor copyrighted publisher PDFs, keep chat responses short and point to the local artifact. In local `paper.md`, include the bilingual reader only for the user-provided source file or clearly lawful open-access content; avoid reproducing large copyrighted text directly in chat.\n\n## Quality bar\n\nGood output feels like a paper reader, not a machine translation dump. It should let a reader:\n\n- read the paper in two languages\n- see where a claim came from\n- inspect the nearby figure or table\n- read equations directly in the Markdown viewer or inspect the original crop when transcription is uncertain\n- move through a complete Markdown file without losing source traceability\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3807,"content_sha256":"b4c0f9ee57b8d83ecee683e4b37637a331562b0b18cf77f249bf8c8975e1bd97"},{"filename":"static/core/workflow.md","content":"# Reading workflow\n\nUse steps 1-5 when creating a reader. For source-linked questions, go directly to step 6 and inspect the relevant source blocks; do not rebuild the artifact. For an explicit excerpt request, scope extraction and translation to that excerpt.\n\n## 1. Identify the source and paper type\n\nThe source-format fragment loaded for this job covers how to extract from the specific input. At a high level, also identify the paper type so you know how tightly to couple text, figures, and captions:\n\n- discovery or mechanism paper\n- methods or algorithm paper\n- resource or dataset paper\n- conference paper\n- review or perspective\n\n## 2. Build a full-document source map before translating\n\nIf the user provides a full paper, process the entire document. Do not stop at the abstract, introduction, or a few representative pages unless the user explicitly asks for a preview.\n\nCreate stable IDs for source blocks:\n\n- `S001`, `S002`, ... for body text\n- `C001`, `C002`, ... for captions\n- `F001`, `F002`, ... for figures\n- `T001`, `T002`, ... for tables\n- `E001`, `E002`, ... for display equations\n\nFor each block, capture: page number, block type, original text, translation, reading-order index, nearby figure or table references, first substantive figure/table mention when applicable, and confidence level when extraction is uncertain. For equations, also capture the printed equation number (if any), normalized LaTeX, bounding box, and original-crop path when a visual fallback is needed.\n\nKeep the source map stable so later questions can point back to the same IDs. For long papers, add a page index so the reader can jump across the whole document without losing location.\n\n## 3. Translate conservatively\n\nTranslate every extractable substantive block with these rules:\n\n- preserve technical terms unless a standard Chinese equivalent is clearly better\n- keep gene names, protein names, formulas, model names, and symbols intact\n- keep citations, superscripts, subscripts, and numeric values unchanged\n- do not collapse methods details into vague prose\n- keep paragraph order and section order unless the user asks for restructuring\n- mark uncertain text instead of guessing when OCR or layout extraction is weak\n- keep the source's paragraph form; do not convert dense prose into bullet-point keywords\n- do not silently skip Methods, limitations, data availability, code availability, competing interests, or extended captions\n- if the paper is too long for one pass, write `paper.md` incrementally by page/section and mark pending blocks rather than switching to summary mode\n\nRender inline expressions with `$... nature-reader — Skillopedia and display equations with `$...$`. Do not put equations in ordinary code spans or code fences. For low-confidence OCR, custom macros that the target renderer cannot support, or image-only formulae, follow `references/equation-handling.md`: show the original crop and an explicitly labelled best-effort transcription rather than raw or guessed LaTeX.\n\nIf a sentence contains multiple claims, keep the translation readable but do not split away the original evidence chain. Build the Terminology Ledger (`../../../nature-shared/core/terminology-ledger.md`) as you translate so recurring terms stay consistent across the whole document.\n\n## 4. Extract and place figures and tables near the relevant discussion\n\nCrop each figure/table into `assets/` and place it near its first substantive mention, keeping the caption attached with both original and Chinese caption text. For the full placement and tight-crop rules, and the figure/table block shape, open `references/figure-extraction.md`.\n\n## 5. Generate the Markdown file\n\nDefault output is a single full-paper `paper.md` file. It must include:\n\n- metadata header\n- a short page/section index\n- page-level or section-level divisions for long papers\n- paragraph-level original/Chinese pairs for all extractable substantive text\n- figure and table blocks placed near the relevant discussion\n- rendered equation blocks with stable `E...` anchors and visible source locations\n- a compact equation index when the paper contains three or more display equations\n- source anchors on every substantive text, figure, caption, and table block\n- a terminology table for recurring technical terms (from the Terminology Ledger)\n- a short `阅读提示` / `critical reading notes` section only after the bilingual body, not as a replacement for it\n- short uncertainty notes only when extraction is weak\n\nDo not add an interactive Q&A panel or follow-up widget in the Markdown deliverable. If a browser preview is explicitly requested, a companion `reader.html` can be generated as a secondary artifact, but the Markdown file remains the primary output.\n\nBefore delivery, run `scripts/validate_reader_math.py paper.md --source-map source_map.json`. Resolve every failure. Use `--strict` when preparing a reusable or published artifact.\n\n## 6. Answer follow-up questions with source grounding\n\nAnswer questions from the relevant paper evidence. Reuse exact block IDs and page numbers from an existing reader; without one, cite verified source locations without inventing IDs. For the full grounding rules, open `references/grounding-rules.md`.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5213,"content_sha256":"8920654b3e23b6e8a6a729292ec92aab8340ef009421c6073656e4aaf21bb411"},{"filename":"static/fragments/source/doi-arxiv.md","content":"# Source: DOI or arXiv identifier\n\nThe user gave a bare DOI or arXiv id/link that must be resolved before reading.\n\n- Resolve the identifier to the actual article first:\n - arXiv → the abstract page, then the PDF (and HTML/LaTeX source when available).\n - DOI → the publisher landing page, then the open-access PDF or HTML if lawfully available.\n- After resolving, this becomes a `pdf-text`, `scanned-pdf`, or `html` job — load that fragment and follow it for extraction. This fragment only covers retrieval.\n- Capture bibliographic metadata (title, authors, venue, year, DOI/arXiv id) for the `paper.md` metadata header.\n- Prefer the open-access version (arXiv, author copy, PMC) when the version of record is paywalled. Note which version was read in `translation_notes.md`, since arXiv and published versions can differ.\n- When lawful arXiv HTML or TeX source is available, prefer its equation source over PDF text extraction, but still verify numbering and symbols against the rendered paper.\n- If the identifier cannot be resolved or only the abstract is reachable, build a draft reader from what is available and clearly mark the rest as not retrieved. Do not fabricate body text.\n- Apply the copyright caution to the resolved artifact.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1251,"content_sha256":"c8b8d006f04f34b703021d9b76b3e62d17212b839fbe37a11a8e34baf86854d9"},{"filename":"static/fragments/source/html.md","content":"# Source: publisher or preprint HTML\n\nThe source is an HTML page (publisher site, preprint server, or similar).\n\n- Extract the article body; strip site navigation, cookie banners, related-article rails, reference-manager widgets, and advertisements.\n- Keep the section structure and paragraph order from the article markup.\n- Figures and tables are usually separate image/HTML elements — capture each figure image and its caption, and place per `references/figure-extraction.md`. Reconstruct HTML tables faithfully rather than screenshotting them when the markup is clean.\n- Preserve inline math (MathML/LaTeX/images), superscript citation markers, and links to the reference list. Prefer accessible MathML or publisher-provided LaTeX over OCR, normalize it to `$... nature-reader — Skillopedia or `$...$`, and retain image formulae as equation crops when no trustworthy machine-readable form exists.\n- Respect the copyright caution: for paywalled or all-rights-reserved pages, keep chat output short and point to the local artifact. Reproduce full bilingual text only for clearly lawful open-access content.\n- If the page is JavaScript-rendered and content is missing, note what could not be retrieved instead of inventing it.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1206,"content_sha256":"136a004201a8ad77e7af5ac8233d8a90cd39f33d7349fe215b4a7946e26b995e"},{"filename":"static/fragments/source/pasted-text.md","content":"# Source: pasted text or notes\n\nThe user pasted prose or notes directly, with no retrievable original layout or page images.\n\n- Treat the pasted text as the source of truth. Build the source map and bilingual pairs from it.\n- Page numbers may be unknown. Use sequential block IDs (`S001`, `S002`, ...) and, where the paste shows section headings, use section-level anchors instead of page anchors. Note in `translation_notes.md` that page anchors are unavailable.\n- There are usually no figure/table images. Do not invent crops. If the text references figures/tables, keep the references and captions as text blocks and note that the visual assets were not provided.\n- If the paste is clearly partial (for example abstract and intro only), build the reader for what was given and label it draft mode; do not backfill missing sections from memory.\n- Preserve any citation markers, equations, and symbols exactly as pasted. Keep valid existing math delimiters; normalize unmistakable raw LaTeX into `$... nature-reader — Skillopedia or `$...$`, but mark ambiguous or incomplete expressions instead of guessing missing delimiters or symbols.\n- Keep the bilingual reader format; do not collapse pasted prose into a summary just because layout metadata is missing.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1236,"content_sha256":"bee3ad0473e686b2bc76fe8c532dc967795019f067fefcd84cf7eed82475bb2f"},{"filename":"static/fragments/source/pdf-text.md","content":"# Source: selectable-text PDF\n\nThe PDF has an extractable text layer. Load the `pdf` skill first for extraction guidance.\n\n- Extract the text layer directly; do not OCR text that is already selectable.\n- Process the whole document, not just the first pages. Build the source map (step 2) across every page.\n- Watch for multi-column layouts: recover natural reading order rather than top-to-bottom raw stream order.\n- Keep ligatures, hyphenated line breaks, superscripts, subscripts, and math intact; rejoin words split across line breaks.\n- Detect display equations as independent `E...` blocks. Plain-text extraction often destroys fractions, matrices, alignment, and symbol placement, so verify each equation against the rendered PDF page before writing LaTeX.\n- Use native math objects or embedded LaTeX when available. If visual verification still leaves ambiguity, crop the original equation and use the low-confidence fallback in `references/equation-handling.md`.\n- Figures and tables are images embedded in the page — crop them per `references/figure-extraction.md`; do not paste the page text of a table where the table image belongs.\n- If some pages have a text layer and others are scanned, treat the scanned pages with the `scanned-pdf` rules and mark them with a confidence note.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1295,"content_sha256":"2f61a2253524683fbe899859c944dc86b20be7f1cf95712d1299a769265caef7"},{"filename":"static/fragments/source/scanned-pdf.md","content":"# Source: scanned PDF (OCR required)\n\nThe PDF is image-only or has an unreliable text layer. Load the `pdf` skill first for OCR guidance.\n\n- OCR every page; do not assume a usable text layer exists.\n- Record a confidence level for each block in the source map, and mark low-confidence blocks explicitly in `translation_notes.md` rather than guessing.\n- Preserve the original wording where OCR is confident; flag, do not silently \"correct\", garbled text.\n- Be careful with numerals, units, symbols, gene/protein names, and chemical formulas — OCR errors here change meaning. Cross-check against context and mark uncertainty.\n- Treat every display equation as an image-first `E...` block: crop the original formula before attempting math OCR. Show the crop in `paper.md`; include OCR-derived LaTeX only as a visibly low-confidence convenience layer until every symbol is verified.\n- Never silently repair or guess a scanned equation from surrounding prose.\n- Figures and tables are page regions: crop them per `references/figure-extraction.md`. For low-quality scans, a tight correct crop still beats a wide noisy one.\n- If pages are skewed, rotated, or partly cut off, note the affected pages and translate only what is legible.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1230,"content_sha256":"e0e7a8343c13952befcc674047dff3488eb2e9640c5740299e6b4a4d0a764d47"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Full-Paper Markdown Reader — Router","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Routing protocol","type":"text"}]},{"type":"paragraph","content":[{"text":"First distinguish creating a reader from answering a question or translating an excerpt. For a source-linked question, read ","type":"text"},{"text":"references/grounding-rules.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" and inspect only the relevant source material; reuse existing source-map IDs when available. Do not regenerate the reader or require a full source map before answering. For an explicit excerpt request, apply extraction, translation, and grounding rules to that excerpt. The full-artifact workflow below applies when the user requests a reader or full-paper translation.","type":"text"}]},{"type":"paragraph","content":[{"text":"For a new task, load the core and matching resources below. Reuse already loaded guidance on follow-ups; load more only when the task needs it.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"1. Load the manifest and the core layer","type":"text"}]},{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"manifest.yaml","type":"text","marks":[{"type":"link","attrs":{"href":"manifest.yaml","title":null}}]},{"text":". It declares the ","type":"text"},{"text":"source_format","type":"text","marks":[{"type":"code_inline"}]},{"text":" axis, the allowed values, and the file paths each value maps to.","type":"text"}]},{"type":"paragraph","content":[{"text":"Also read every file listed under ","type":"text"},{"text":"always_load","type":"text","marks":[{"type":"code_inline"}]},{"text":". These hold the core principles, the reading workflow, and the output contract that apply to every reading job, plus the shared Terminology Ledger used to build the recurring-term table.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"2. Detect the source format","type":"text"}]},{"type":"paragraph","content":[{"text":"Decide the ","type":"text"},{"text":"source_format","type":"text","marks":[{"type":"code_inline"}]},{"text":" value using the manifest's ","type":"text"},{"text":"detect:","type":"text","marks":[{"type":"code_inline"}]},{"text":" hint and the user's input:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pdf-text","type":"text","marks":[{"type":"code_inline"}]},{"text":" — selectable-text PDF. Default.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scanned-pdf","type":"text","marks":[{"type":"code_inline"}]},{"text":" — image-only or OCR-required PDF.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"html","type":"text","marks":[{"type":"code_inline"}]},{"text":" — publisher or preprint HTML page.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"doi-arxiv","type":"text","marks":[{"type":"code_inline"}]},{"text":" — a bare DOI or arXiv link that must be resolved first.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pasted-text","type":"text","marks":[{"type":"code_inline"}]},{"text":" — pasted prose or notes with no retrievable original layout.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"State the detected value in one short line to the user before processing, so they can correct you cheaply. A source may map to more than one value (for example a DOI that resolves to a PDF); load the resolution fragment first, then the fragment for the resolved artifact.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"3. Load the matching fragment(s)","type":"text"}]},{"type":"paragraph","content":[{"text":"Read the file mapped for the detected ","type":"text"},{"text":"source_format","type":"text","marks":[{"type":"code_inline"}]},{"text":". Do ","type":"text"},{"text":"not","type":"text","marks":[{"type":"strong"}]},{"text":" read every fragment in ","type":"text"},{"text":"static/","type":"text","marks":[{"type":"code_inline"}]},{"text":". Load only what step 2 selected.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"4. Build the reader using the loaded material","type":"text"}]},{"type":"paragraph","content":[{"text":"Apply the loaded fragments in this priority order:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Core principles (","type":"text"},{"text":"core/principles.md","type":"text","marks":[{"type":"code_inline"}]},{"text":") — bilingual reader by default, translate for meaning, never degrade to a summary, copyright caution.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Source-format fragment — how to extract text, figures, and tables for this input.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Reading workflow (","type":"text"},{"text":"core/workflow.md","type":"text","marks":[{"type":"code_inline"}]},{"text":") — the six-step source-map-first process.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Output contract (","type":"text"},{"text":"core/output-contract.md","type":"text","marks":[{"type":"code_inline"}]},{"text":") — required files and the pre-response verification checklist.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Build the Terminology Ledger as you translate (","type":"text"},{"text":"../nature-shared/core/terminology-ledger.md","type":"text","marks":[{"type":"code_inline"}]},{"text":"); it becomes the ","type":"text"},{"text":"paper.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" recurring-term table and the ","type":"text"},{"text":"source_map.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" glossary.","type":"text"}]},{"type":"paragraph","content":[{"text":"If constraints prevent full processing, still create a draft reader and label missing pages, figures, or low-confidence crops in ","type":"text"},{"text":"translation_notes.md","type":"text","marks":[{"type":"code_inline"}]},{"text":". Do not switch to summary mode.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"5. Reach for references only when needed","type":"text"}]},{"type":"paragraph","content":[{"text":"The files under ","type":"text"},{"text":"references/","type":"text","marks":[{"type":"code_inline"}]},{"text":" are deep references, not defaults. Open them on demand per the ","type":"text"},{"text":"references.on_demand","type":"text","marks":[{"type":"code_inline"}]},{"text":" table in the manifest:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"detailed figure/table cropping and placement → ","type":"text"},{"text":"references/figure-extraction.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"exact field schema for ","type":"text"},{"text":"paper.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"source_map.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"references/output-spec.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"equations, mathematical expressions, chemical formulae, or image-only formulae → ","type":"text"},{"text":"references/equation-handling.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"answering follow-up questions with source citations → ","type":"text"},{"text":"references/grounding-rules.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]}]},"metadata":{"date":"2026-11-02","name":"nature-reader","author":"@skillopedia","source":{"stars":51879,"repo_name":"nature-skills","origin_url":"https://github.com/Yuan1z0825/nature-skills/blob/HEAD/skills/nature-reader/SKILL.md","repo_owner":"Yuan1z0825","body_sha256":"999a5c1b116558133d0389ce6c1bbc3dc9cf5242d1be2870358789769d97a84e","cluster_key":"a7464f6d47df55293366ad9418b42062eec75c57bf011b8dd9e7a028ccaa1138","clean_bundle":{"format":"clean-skill-bundle-v1","source":"Yuan1z0825/nature-skills/skills/nature-reader/SKILL.md","text_bytes":63613,"source_commit":"69817e4dad8bfc52fa4e59a9d8355e4264a4d3a7","skills_sh_rank":1734,"attachment_count":19,"text_attachments":19,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/nature-reader/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"education-research","category_label":"Education"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"education-research","metadata":{"author":"Community contribution, refactored into static/dynamic layers","version":"2.1.1"},"import_tag":"skills-sh-top20k-2026-11","description":"Create source-grounded Chinese-English paper readers with aligned text, figures, tables, and equations. Use for 全文翻译、中英文对照、论文精读 or source-linked questions about a paper; respect a requested excerpt or question without generating a full reader."}},"renderedAt":1793666004694}

Full-Paper Markdown Reader — Router Routing protocol First distinguish creating a reader from answering a question or translating an excerpt. For a source-linked question, read and inspect only the relevant source material; reuse existing source-map IDs when available. Do not regenerate the reader or require a full source map before answering. For an explicit excerpt request, apply extraction, translation, and grounding rules to that excerpt. The full-artifact workflow below applies when the user requests a reader or full-paper translation. For a new task, load the core and matching resources…