Back to skills
extension
Category: Productivity & OfficeNo API key required

paper-summarize

After research-hub ingests a cluster of cited papers, fill the per-paper Key Findings + Methodology + Relevance sections in BOTH Obsidian markdown and the Zotero child note. Use when the user says \"fill the TODO Key Findings/Methodology blocks left by research-hub auto\", \"I just ran auto and don't know what these papers are about\", or \"summarize the papers in cluster X\". Invokes a supported LLM CLI on each paper's abstract. NOT for summarizing the user's own manuscript draft — that's `paper-memory-builder`. NOT for cluster-level briefs — that's `research-hub notebooklm generate`. This skill is per-cited-paper only. If the user says \"extract claims from these papers\", disambiguate before acting: their own manuscript draft → `paper-memory-builder`; a cross-paper comparison matrix → `literature-triage-matrix`; per-cited-paper Key Findings → this skill.

personAuthor: TashanworldhubOpenAPI

paper-summarize

The auto pipeline ingests metadata + abstract only — Summary / Key Findings / Methodology / Relevance stay as [TODO] skeletons in both Obsidian and Zotero. Cluster-level summarization (NotebookLM brief, crystals) does NOT fill per-paper notes. So after auto, the user has nothing scannable per paper without opening the PDF.

This skill fills that gap. One LLM call per paper, JSON-validated, written to both vault systems atomically (rollback the markdown change if Zotero write fails so the two stay in sync).

When to use

Trigger phrases:

  • "Summarize the papers in cluster X."
  • "Fill the TODO Key Findings for X."
  • "I just ran auto X and the notes are empty — give me real summaries."
  • "Update Zotero notes for cluster X with what each paper actually says."

Not for:

  • Generating a single CLUSTER-LEVEL summary — that's research-hub notebooklm generate (NotebookLM brief).
  • Filling Q&A on the cluster — that's research-hub crystal emit/apply.
  • Reading PDFs — abstract-only by design. PDF parsing is out of scope; the LLM is told to mark "[PDF needed]" if abstract is too thin.
  • Verifying brief vs source — that's notebooklm-brief-verifier.

Inputs

  • Cluster slug (must already exist in the vault under raw/<slug>/)
  • Optional LLM CLI override (claude, codex, gemini, opencode, aichat, cursor, or configured custom adapter)
  • Optional --apply flag (default off, dry-run)

The skill reads each paper's frontmatter (DOI, year, zotero-key) + the ## Abstract body block. Papers with empty abstract get a "PDF needed" marker rather than hallucinated findings.

Outputs

For each paper, three sections are rewritten:

  1. Obsidian markdown at raw/<cluster>/<paper-slug>.md:

    • ## Key Findings callout block (3–5 bullets)
    • ## Methodology callout block (one sentence)
    • ## Relevance callout block (1–2 sentences linking to the cluster topic)
    • Anchor IDs (^findings, ^methodology, ^relevance) preserved.
  2. Zotero child note for the paper's parent item (looked up via zotero-key frontmatter):

    • Existing note HTML overwritten with <h1>Summary + Abstract + Key Findings <ul> + Methodology + Relevance.
    • If no child note exists, one is created.

Both writes must succeed for a paper to count as "applied". A Zotero write failure rolls back the markdown change so the two systems stay in sync.

Failure modes

  • No LLM CLI on PATH: prompt is saved to <vault>/.research_hub/artifacts/<cluster>/summarize-prompt.md. The user pipes it through their LLM manually and re-runs with --apply, or calls the apply_cluster_summaries MCP tool with the parsed payload. Exit code 0; ok=True.
  • LLM returns malformed JSON: report is ok=False with error="LLM response had no parseable JSON object". No writes.
  • Paper slug in payload not in cluster: that entry is skipped with reason logged; other entries still applied.
  • Empty key_findings / methodology / relevance: entry skipped.
  • Zotero write fails for one paper: that paper's markdown change is rolled back; other papers still applied.

Verification

This skill's contract is exercised end-to-end by the test suite. The suites stub the LLM CLI but execute real Obsidian markdown writes against a fixture vault and real Zotero child-note writes against a mocked Zotero adapter. Rollback semantics (markdown rolls back if Zotero write fails) are explicitly tested.

# Run the full paper-summarize suite (23 tests)
python -m pytest -q \
  tests/test_v069_summarize.py \
  tests/test_v073_parallel_summarize.py \
  tests/test_v080_resummarize.py

Coverage breakdown:

| Test file | Count | What it covers | |---|---|---| | tests/test_v069_summarize.py | 17 | Prompt builder shape, validator (rejects unknown slugs / empty fields / wrong types), Obsidian + Zotero apply path, rollback when Zotero fails, no-LLM-on-PATH fallback | | tests/test_v073_parallel_summarize.py | 3 | Parallel summarize across multiple clusters, ordering, error isolation | | tests/test_v080_resummarize.py | 3 | Re-summarize behaviour: idempotent on same input, overwrite on different LLM output, --no-zotero path |

For a manual smoke check against a live vault:

# Dry-run (emit prompt + show LLM output, no writes)
research-hub summarize --cluster <slug>

# Live run (writes to Obsidian + Zotero)
research-hub summarize --cluster <slug> --apply

# Override LLM
research-hub summarize --cluster <slug> --llm-cli codex --apply

# Obsidian-only (skip Zotero — useful when Zotero is offline)
research-hub summarize --cluster <slug> --apply --no-zotero

After applying, scan raw/<cluster>/*.md — every paper's ## Key Findings callout should have real bullets instead of [TODO].

Operating notes

  • Findings-first: the prompt instructs the LLM to state the result, not "The paper shows that…".
  • Anchored to the abstract: every Key Finding must trace to something the abstract claims. The LLM is told to mark uncertain claims with [likely].
  • Idempotent: re-running on a cluster with already-filled findings will overwrite them with whatever the LLM produces this run. Use --no-zotero or --no-obsidian if you want to preview one side first.
  • Same dual-write discipline as the abstract-sync helpers in .scratch/: one transactional unit per paper.