Skip to content
Content
Skill

/review-engine

Activate when the user provides reviewer or co-author feedback (annotated PDF, pasted comments, or reviewer report) and wants to implement revisions. Extracts review points, maps them to paper.tex locations, classifies actions, implements changes, recompiles, and generates a

From plugin
open-academic-paper-machine
1817 skills4 agents21 commands
Install
$ npx -y skills add TobiasBlask/open-paper-machine --skill review-engine --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/review-engine

Context preview

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

Activate when the user provides reviewer or co-author feedback (annotated PDF, pasted comments, or reviewer report) and wants to implement revisions. Extracts review points, maps them to paper.tex locations, classifies actions, implements changes, recompiles, and generates a

SKILL.md

review-engine.SKILL.md
name: review-engine
description: >
  Activate when the user provides reviewer or co-author feedback (annotated PDF,
  pasted comments, or reviewer report) and wants to implement revisions. Extracts
  review points, maps them to paper.tex locations, classifies actions, implements
  changes, recompiles, and generates a change log + latexdiff. Handles the full
  revision loop from feedback to committed changes.

> **Orchestration Log**: When this skill is activated, append a log entry to `outputs/orchestration_log.md`: > ``` > ### Skill Activation: Review Engine (Round [N]) > **Timestamp:** [current date/time] > **Actor:** AI Agent (review-engine) > **Input:** [N] review points from [source] (annotated PDF / pasted text / reviewer report) > **Output:** [N] changes implemented, paper recompiled, latexdiff generated > **Human decisions:** [list of QUESTION items resolved by orchestrator] > ```

Review Engine

Core Principle

Academic revision is a structured, repeatable process: **extract feedback -> interpret -> classify -> implement -> verify**. This engine automates the entire loop. The human orchestrator approves the change plan; the engine executes it.

This skill was derived from 4 actual co-author revision rounds on a real paper (Blask & Funk, 2026). Every step reflects what we learned works — and what fails — when processing human feedback on AI-generated manuscripts.

When to Activate

  • User provides an annotated PDF (co-author or reviewer comments)
  • User pastes reviewer comments from a journal decision letter
  • User says "implement these changes", "process this review", "revision round"
  • User says "respond to reviewers", "R&R", "revise and resubmit"
  • After self-review (Phase 6) produces a critique that needs implementation

Prerequisites

  • `paper.tex` exists in `latex/` and compiles successfully (this is the baseline)
  • `pdflatex` and `bibtex` are available
  • `latexdiff` is available (for visual change tracking)
  • PyMuPDF (`fitz`) is available for PDF annotation extraction (`pip install pymupdf`)

---

Step 1: EXTRACT Review Points

The first step is to get all review points into a structured format, regardless of how the reviewer provided them.

From Annotated PDF (Co-Author Review)

This is the most common case: a co-author annotates the PDF with highlights, sticky notes, and text comments. Use `scripts/extract_annotations.py`:

import sys
sys.path.insert(0, "scripts")
from extract_annotations import extract_annotations, annotations_to_markdown

annotations = extract_annotations("path/to/annotated.pdf")
print(annotations_to_markdown(annotations))
print(f"\nTotal: {len(annotations)} annotations found")

If `scripts/extract_annotations.py` is not available, use inline PyMuPDF:

import fitz

doc = fitz.open("path/to/annotated.pdf")
annotations = []

for page_num, page in enumerate(doc, 1):
    for annot in page.annots() or []:
        entry = {
            "page": page_num,
            "type": annot.type[1],  # "Highlight", "Text", "FreeText", "StrikeOut"
            "content": annot.info.get("content", "").strip(),
            "author": annot.info.get("title", ""),
            "highlighted_text": "",
        }

        # Extract highlighted/marked text via quadpoints
        if annot.type[0] in (8, 9, 10, 11) and annot.vertices:  # Highlight, Underline, Squiggly, StrikeOut
            quad_count = len(annot.vertices) // 4
            text_parts = []
            for i in range(quad_count):
                quad = annot.vertices[i * 4:(i + 1) * 4]
                rect = fitz.Rect(
                    min(p[0] for p in quad), min(p[1] for p in quad),
                    max(p[0] for p in quad), max(p[1] for p in quad),
                )
                text_parts.append(page.get_text("text", clip=rect).strip())
            entry["highlighted_text"] = " ".join(text_parts)

        if entry["content"] or entry["highlighted_text"]:
            annotations.append(entry)

doc.close()

**Common pitfall:** The user may send the wrong PDF (without annotations). If extraction returns 0 annotations, tell the user immediately and ask them to re-send. Do NOT proceed with an empty annotation list.

From Pasted Text (Journal R&R)

Parse reviewer comments by detecting common patterns:

Reviewer 1:
Major Comments:
1. The authors should clarify...
2. The methodology section lacks...

Minor Comments:
1. On page 5, the reference to...

Split into individual review points by:

  • Numbered items ("1.", "2.", "-", "a)")
  • Reviewer sections ("Reviewer 1:", "Reviewer 2:")
  • Category headers ("Major Comments:", "Minor Comments:", "Questions:")
  • Page/line references ("page 5", "line 42", "Section 3")

From Self-Review (Phase 6 Output)

Parse the structured self-critique from `self_review.md` or the Phase 6 output. Each bullet point or numbered item becomes a review point.

Output Format

Every extraction method produces the same structure:

{
  "id": 1,
  "source": "pdf_annotation" | "pasted_text" | "self_review",
  "page": 5,                    # PDF page (if applicable)
  "type": "Highlight",          # Annotation type (if PDF)
  "reviewer": "Burkhardt Funk", # Reviewer name (if known)
  "reviewer_text": "just delete, I think ref to tab 1 is also wrong here",
  "highlighted_text": "Following Hevner et al.'s guidelines, we evaluate in three steps",
  "section_ref": null            # Will be filled in Step 2
}

---

Step 2: MAP to Source

For each review point, locate the corresponding position in `paper.tex`.

Mapping Strategy

1. **Primary: Text match.** Take the `highlighted_text` (or key phrases from `reviewer_text`) and search `paper.tex` using grep/search. Handle:

  • LaTeX commands embedded in text (`\textit{...}`, `\citep{...}`)
  • Line breaks (the PDF renders continuous text that spans multiple LaTeX lines)
  • Ligatures and special characters (fi, fl, -- vs. --)

2. **Secondary: Page-to-section estimatio

Read more
Ships withopen-academic-paper-machine

A Claude Code plugin that autonomously writes academic papers — from literature search to production-ready LaTeX/PDF. Scope note.

Get the whole plugin