latex-engine — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited latex-engine (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Orchestration Log: When this skill is activated, append a log entry tooutputs/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"]``
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).
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:
texlive or equivalent LaTeX distribution with pdflatex and bibtexapt-get install -y texlive-latex-base texlive-latex-extra texlive-fonts-recommended texlive-bibtex-extraPlugin files used:
templates/arxiv.sty — the arxiv-style LaTeX style filescripts/md_to_latex.py — the markdown-to-LaTeX converter.tex outputCreate 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 outputimport 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}")# 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")After compilation, verify:
.log file\includegraphics paths resolve\citep/\citet keys exist in .bib% TODO: commentsimport 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}")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:
% TODO commentAuthors can be provided in three ways:
Option A: Via command arguments
--author "Tobias Blask;;University of Applied Sciences;;[email protected]"
--author "Co-Author Name;;Other University;;[email protected]"Option B: Via the converter function
tex = md_to_latex(
md_path="draft.md",
bib_path="references.bib",
authors=[
"Tobias Blask;;HTW Berlin;;[email protected]",
"Co-Author;;Institution;;[email protected]",
],
)Option C: Edit the .tex file directly The generated .tex has a clear author block section to edit manually.
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}.
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}| 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 |
For arXiv upload, the user needs:
paper.tex — the generated .tex filearxiv.sty — the style filereferences.bib — OR the .bbl file (generated during compilation)figures/ — all PNG figuresImportant: arXiv doesn't always process .bib files correctly. To be safe:
paper.bbl (generated during compilation)paper.tex replacing the \bibliography{references} line\bibliographystyle and \bibliography linesThe converter can prepare this automatically with --arxiv-bundle (copies .bbl inline).
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.