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
2017 skills4 agents21 commands

Claude Code

$ npx -y skills add TobiasBlask/open-paper-machine --skill review-engine --agent claude-code

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
@tobiasblask
Ships withopen-academic-paper-machine

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

2017 skills4 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
20
Star history of TobiasBlask/open-paper-machine on GitHub, a chart by star-history.com

More skills from other plugins.

prompt-lookup

prompt-lookup

Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use…

@gh-f@gh-fInstall Skill
ppt-master

ppt-master

AI-driven presentation workflow for generating editable PPTX decks and slides, reconstructing page visuals, creating reusable…

@hugohe3@hugohe3Install Skill
morph-ppt

morph-ppt

Use this skill when the user wants a .pptx with smooth cross-slide animation — PowerPoint Morph transitions, Keynote-style…

officecli12d33k
@iofficeai@iofficeaiInstall Skill

Questions about review-engine.

Which coding agents can use review-engine?
review-engine installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.