Orchestration Log: When this skill is activated, append a log entry to
outputs/orchestration_log.md:### Skill Activation: LaTeX Engine **Timestamp:** [current date/time] **Actor:** AI Agent (latex-engine) **Input:** [brief description of the export request] **Output:** [brief description of what was produced — e.g., "Compiled paper.tex to PDF (24 pages), no errors"]
LaTeX Engine
Core Principle
The paper machine works in markdown throughout Phases 1-5 for speed and flexibility. This engine is the final production step: it takes the completed draft.md, references.bib, and figures/ and produces a submission-ready LaTeX project with compiled PDF using the arxiv-style template (https://github.com/kourgeorge/arxiv-style).
Prerequisites
Required files in the working directory:
draft.md— complete paper draft from Phase 5references.bib— BibTeX file from literature searchfigures/— directory with generated PNG figures (optional but recommended)
Required system packages for PDF compilation:
texliveor equivalent LaTeX distribution withpdflatexandbibtex- Install if missing:
apt-get install -y texlive-latex-base texlive-latex-extra texlive-fonts-recommended texlive-bibtex-extra
Plugin files used:
templates/arxiv.sty— the arxiv-style LaTeX style filescripts/md_to_latex.py— the markdown-to-LaTeX converter
When to Activate
- User says "export to LaTeX", "generate PDF", "make it submission-ready"
- After Phase 5 (Assembly) completes in the paper machine pipeline
- User explicitly asks for
.texoutput - User mentions arXiv submission preparation
Conversion Pipeline
Step 1: Prepare the LaTeX Project Directory
Create a latex/ subdirectory with the proper structure:
latex/
├── arxiv.sty ← copied from templates/
├── paper.tex ← generated by md_to_latex.py
├── references.bib ← copied from working dir
├── figures/ ← copied from working dir
│ ├── fig_method_*.png
│ ├── fig_results_*.png
│ └── ...
└── paper.pdf ← compiled output
Step 2: Run the Converter
import sys, shutil
from pathlib import Path
# Paths
plugin_dir = Path(".") # or wherever the plugin is
work_dir = Path(".") # project working directory
latex_dir = work_dir / "latex"
latex_dir.mkdir(exist_ok=True)
# Copy arxiv.sty
shutil.copy(plugin_dir / "templates" / "arxiv.sty", latex_dir / "arxiv.sty")
# Copy references.bib
shutil.copy(work_dir / "references.bib", latex_dir / "references.bib")
# Copy figures
figures_src = work_dir / "figures"
if figures_src.exists():
figures_dst = latex_dir / "figures"
if figures_dst.exists():
shutil.rmtree(figures_dst)
shutil.copytree(figures_src, figures_dst)
# Run converter
sys.path.insert(0, str(plugin_dir / "scripts"))
from md_to_latex import md_to_latex, compile_pdf
tex_content = md_to_latex(
md_path=str(work_dir / "draft.md"),
bib_path=str(work_dir / "references.bib"),
title=None, # auto-detect from draft.md
authors=None, # user provides or TODO marker
header_right="A Preprint",
)
tex_path = latex_dir / "paper.tex"
tex_path.write_text(tex_content, encoding="utf-8")
print(f"LaTeX written: {tex_path}")
Step 3: Compile to PDF
# Compile: pdflatex → bibtex → pdflatex → pdflatex
pdf_path = compile_pdf(str(tex_path))
if pdf_path:
print(f"PDF ready: {pdf_path}")
else:
print("Compilation had issues — check paper.log")
Step 4: Validate Output
After compilation, verify:
- Citation resolution: Check for undefined references in the
.logfile - Figure inclusion: Verify all
\includegraphicspaths resolve - BibTeX entries: Check that all
\citep/\citetkeys exist in.bib - Page count: Report total pages
- TODO markers: List any remaining
% TODO:comments
import re
log_path = latex_dir / "paper.log"
if log_path.exists():
log_text = log_path.read_text(encoding="utf-8", errors="ignore")
# Undefined references
undef = re.findall(r"Citation `([^']+)' undefined", log_text)
if undef:
print(f"⚠️ Undefined citations: {undef}")
# Missing figures
missing_figs = re.findall(r"File `([^']+)' not found", log_text)
if missing_figs:
print(f"⚠️ Missing figures: {missing_figs}")
# Page count
pages = re.findall(r"Output written on .+ \((\d+) page", log_text)
if pages:
print(f"📄 PDF: {pages[0]} pages")
# TODO markers in .tex
tex_text = tex_path.read_text(encoding="utf-8")
todos = re.findall(r"% TODO: (.+)", tex_text)
if todos:
print(f"📝 Remaining TODOs ({len(todos)}):")
for t in todos:
print(f" - {t}")
Citation Conversion Details
The converter handles these citation patterns:
| Markdown Pattern | LaTeX Output |
|---|---|
(Smith, 2023) | \citep{smith2023} |
(Smith & Jones, 2023) | \citep{smithjones2023} |
(Smith et al., 2023) | \citep{smithetal2023} |
Smith (2023) | \citet{smith2023} |
Smith et al. (2023) | \citet{smithetal2023} |
(Smith, 2023; Jones, 2024) | \citep{smith2023, jones2024} |
Resolution process:
- Parse all BibTeX entries → extract (LastName, Year) pairs
- For each citation in markdown, match against the BibTeX index
- Exact match → use BibTeX key directly
- Fuzzy match → try without accents, partial first name
- No match → generate fallback key, leave
% TODOcomment
Author Block
Authors can be provided in three ways:
Option A: Via command arguments
--author "Tobias Blask;;University of Applied Sciences;;blask@university.de"
--author "Co-Author Name;;Other University;;coauthor@uni.de"
Option B: Via the converter function
tex = md_to_latex(
md_path="draft.md",
bib_path="references.bib",
authors=[
"Tobias Blask;;HTW Berlin;;tobias.blask@htw-berlin.de",
"Co-Author;;Institution;;email@inst.de",
],
)
Option C: Edit the .tex file directly The generated .tex has a clear author block section to edit manually.
Table Conversion
Markdown tables are converted to LaTeX booktabs tables:
| Column A | Column B | Column C |
|----------|----------|----------|
| Data 1 | Data 2 | Data 3 |
Becomes:
\begin{table}[htbp]
\centering
\begin{tabular}{lll}
\toprule
\textbf{Column A} & \textbf{Column B} & \textbf{Column C} \\
\midrule
Data 1 & Data 2 & Data 3 \\
\bottomrule
\end{tabular}
\end{table}
For concept matrix tables (which can be wide), the converter wraps in \adjustbox{max width=\textwidth}.
Figure Handling
From figure-engine (LaTeX already in draft.md):
If the draft already contains \begin{figure}...\end{figure} blocks (from the figure-engine),
they are passed through as-is.
From markdown images:
 is converted to:
\begin{figure}[htbp]
\centering
\includegraphics[width=\linewidth]{figures/filename.png}
\caption{Caption}
\label{fig:auto_label}
\end{figure}
Troubleshooting
| Problem | Solution |
|---|---|
arxiv.sty not found | Ensure arxiv.sty is copied to the same directory as paper.tex |
Citation undefined | BibTeX key mismatch — check references.bib has the expected keys |
Missing figure | Check figures/ directory is in the latex/ folder |
Font not found | Install texlive-fonts-recommended |
natbib errors | Ensure natbib package is installed (texlive-latex-extra) |
Compilation hangs | Check for infinite loops in .tex — usually malformed tables |
arXiv Submission Preparation
For arXiv upload, the user needs:
paper.tex— the generated .tex filearxiv.sty— the style filereferences.bib— OR the.bblfile (generated during compilation)figures/— all PNG figures
Important: arXiv doesn't always process .bib files correctly. To be safe:
- Copy the contents of `