Skip to content
Research
Skill

/paper-narrative

Judge and reshape the story told by an entire paper figure deck. Use when writing or revising a paper to derive a grounded brief from the manuscript and captions, review the full deck as a handling editor, and hand an ordered figure arc to `figure-composer`.

BOOST
From plugin
open-science
5.5k25 skills
Install
$ npx -y skills add aipoch/open-science --skill paper-narrative --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/paper-narrative

Context preview

The summary Claude sees to decide when to auto-load this skill.

Judge and reshape the story told by an entire paper figure deck. Use when writing or revising a paper to derive a grounded brief from the manuscript and captions, review the full deck as a handling editor, and hand an ordered figure arc to `figure-composer`.

SKILL.md

paper-narrative.SKILL.md
name: paper-narrative
description: 'Judge and reshape the story told by an entire paper figure deck. Use when writing or revising a paper to derive a grounded brief from the manuscript and captions, review the full deck as a handling editor, and hand an ordered figure arc to `figure-composer`.'
license: Apache-2.0

Paper Narrative — manuscript → brief → figure arc → editorial loop

`paper-narrative` is the outermost figure workflow. It judges the paper-level story before `figure-composer` designs any one figure. The inputs are the work itself: a manuscript (or abstract), figure captions, and the current full deck.

Open-Science Notebook call

Every `notebook_execute` request whose `code` uses a function named in this skill includes this skill ID:

{ "kernelSkillIds": ["paper-narrative"], "code": "print(paper_brief_schema())" }

`kernelSkillIds` contains the skill ID; function calls belong in `code`. This request is complete as written: call the named functions directly and do not add an import or discovery step.

Required inputs and trust labels

Keep these inputs distinct throughout the workflow:

  • `manuscriptVersionId`: immutable manuscript Artifact Version (an abstract-only

manuscript is allowed) and the reviewed manuscript text read from it.

  • `abstractText`: reviewed abstract text when available; use it for bounded brief

reasoning while retaining the full manuscript Version as source provenance.

  • `captionsVersionId`: immutable captions Artifact Version and the reviewed

per-figure caption or claim text read from it.

  • `deckVersionId`: immutable deck Artifact Version containing every current

figure in review order.

  • `rulesVersionId`: immutable design-rules Artifact Version, used only as a

reference so the editor judges story rather than visual craft.

  • `figureDataVersionIds`: immutable data Artifact Versions grouped by figure.
  • `figureWidthMmByFigure`: reviewed positive venue width for each figure; the

downstream composer must not invent this physical output constraint.

Manuscript, captions, deck, and data are source inputs. Every brief, review, arc, move, omission, and proposed analysis is model-generated and requires human review. Never describe generated text as manuscript evidence or source data. Preserve the input Version identities when publishing or delegating downstream work.

1. Reason from manuscript and captions

Load the reviewed manuscript/abstract and captions content into the JavaScript control-plane request. Obtain `paper_brief_schema()` in Python first. Then call the current tool-less Host model and require JSON only:

const briefSchema = paperBriefSchemaFromNotebook
const Ajv2020 = require('ajv/dist/2020').default
const validateBrief = new Ajv2020({ allErrors: true }).compile(briefSchema)
const briefSourceText = abstractText || manuscriptText
let repair = ''
let brief
for (let attempt = 1; attempt <= 2; attempt += 1) {
  const prompt =
    `Return JSON only. The complete paper_brief JSON Schema is:\n${JSON.stringify(briefSchema)}\n` +
    `Manuscript Artifact Version: ${manuscriptVersionId}\n` +
    `Captions Artifact Version: ${captionsVersionId}\n` +
    `Reviewed abstract/manuscript source:\n${briefSourceText}\n\nCaptions/claims:\n${captionsText}\n\n` +
    `Pitch is the grandest supportable one-sentence claim, not the method. ` +
    `Vision is the killer application: what readers can now do. ` +
    `Name the audience and the single most-arresting image.` +
    repair
  if (Buffer.byteLength(prompt, 'utf8') > 64 * 1024) {
    throw new Error(
      'paper brief prompt exceeds host.llm 64 KiB UTF-8 limit; provide a reviewed abstract or shorter captions'
    )
  }
  const briefDraft = await host.llm(prompt)
  if (briefDraft.stopReason !== 'end_turn') {
    throw new Error(`paper brief inference stopped with ${briefDraft.stopReason}`)
  }
  let candidate
  let problem
  try {
    candidate = JSON.parse(briefDraft.text)
    if (validateBrief(candidate)) {
      brief = candidate
      break
    }
    problem = JSON.stringify(validateBrief.errors)
  } catch (error) {
    problem = error instanceof Error ? error.message : String(error)
  }
  if (attempt === 2) throw new Error('invalid paper brief after corrective retry')
  repair =
    `\nPrevious response was invalid: ${problem}. Repair it and return JSON only. ` +
    `Previous response:\n${briefDraft.text.slice(0, 8000)}`
}

`host.llm` does not enforce a caller-provided schema. The code therefore checks the UTF-8 request budget, requires `stopReason === "end_turn"`, parses JSON, and validates with the same bundled Ajv 2020 implementation used elsewhere in the control plane. Prefer the reviewed abstract because a full manuscript commonly exceeds the hard 64 KiB prompt limit; never silently truncate source text. If a corrective retry still fails, stop. Do not fill missing required fields with guesses. After validation, attach the immutable figure/data references from the source claim table. Then review every field — pitch, vision, audience, most-arresting asset, and every figure claim — before continuing. Fix unsupported wording explicitly; never silently treat the first model draft as approved.

2. Review the full deck as a handling editor

Generate the task with `narrative_review_task(reviewedBrief, deckVersionId, rulesVersionId)` and obtain `narrative_review_schema()` in Python. Dispatch one reviewer from `repl_execute`. All three work inputs are explicit alongside the deck; the schema makes the expected model result reviewable:

const collectStructuredBatch = async (requests) => {
  const receipts = await host.delegate(requests, { wait: false })
  const children = await host.collect(
    receipts.children.map(({ frameId, attemptId }) => ({ frameId, attemptId })),
    { returnWhen: 'all', timeoutSeconds: 1800 }
  )
  return children.map((child) => {
    if (!child || child.status !== 'completed' || child.error) {
      throw new Err
Read more
Ships withopen-science

The open-source AI research workbench for scientific research and agent workflows. Local-first, model-agnostic desktop app with extensible skills, MCP tools and connectors, Python/R execution and traceable artifacts for reproducible research on macOS, Windows and Linux.

Get the whole plugin
Stats
5,469
Stars
506
Forks
Active
Maintenance
TypeScript
Language
Apache-2.0
License
23m ago
Last commit
3mo ago
Created
13h ago
Added

Repo: aipoch/open-science

Other skills on open-science.