--- name: latex-health-check description: "Compile all LaTeX projects and report cross-project build consistency. Use when checking whether a collection of papers builds cleanly. Not for rendered visual inspection after a clean build; use $latex-polish." allowed-tools: - Read - Edit - Write - Glob - Grep - Bash(latexmk*) - Bash(pdflatex*) - Bash(biber*) - Bash(bibtex*) - Bash(ls*) - Bash(mkdir*) - Bash(cp*) - Bash(cmp*) - Bash(head*) - Bash(ln*) - Bash(wc*) - Bash(readlink*) argument-hint: "[project-path | 'all' | 'quick']" --- # LaTeX Health Check: Self-Healing Build Agent > Compile all LaTeX projects, auto-fix known errors iteratively, and verify cross-project consistency (symlinks, shared bibliographies, Overleaf separation). ## When to Use - Periodically (weekly) to catch build rot before it becomes debugging sessions - After major infrastructure changes (template updates, symlink reorganisation) - Before submission season to verify all papers compile cleanly - When the user says "check my LaTeX", "build health", "compile everything" ## Modes | Mode | Trigger | What it does | |------|---------|-------------| | **Single project** | Path argument | Compile + fix + verify one project | | **All projects** | `all` argument | Discover and compile every LaTeX project | | **Quick** | `quick` argument | Compile only, no fixes, report errors | ## Phase 1: Discover LaTeX Projects Find all directories containing a `\documentclass` in a .tex file: Search locations in this order, checking that each exists: - an explicit path argument; - the current project; - project roots declared by the current repository or client guidance; - `~/Projects/` as a portable fallback for `all` mode. For each discovered project, record: - Project name (directory name) - Main .tex file path - Whether it has a `.latexmkrc` - Whether it has an `out/` directory - Whether it's inside a `paper/` subdirectory (Overleaf-linked) ## Phase 2: Build Loop (per project) For each project: ### 2a. Pre-flight - Resolve the byte-identical `templates/build-config/.latexmkrc` bundle from the installed `latex` skill; stop if it is unavailable. - If `.latexmkrc` is missing, copy the resolved canonical verbatim. If it exists, compare it byte-for-byte; report divergence and do not overwrite it without explicit migration approval. - Allow `.latexmkrc.local` for project-specific paths, dependencies, `$bibtex_use`, `$clean_ext`, or `@default_files`, but flag any `$pdf_mode` assignment. - Create `out/` directory if missing ### 2b. Compile ```bash cd && latexmk -interaction=nonstopmode 2>&1 ``` **Engine selection:** Do NOT hardcode `-pdf`. The canonical recursively infers pdfLaTeX, XeLaTeX, or LuaLaTeX from the requested driver and local dependencies. Passing `-pdf` overrides this and breaks Unicode-engine projects. Let latexmk read `.latexmkrc`. ### 2c. Parse log Extract from `out/*.log`: - Error count (lines starting with `!`) - LaTeX/package warning count (`Warning`-tagged lines) - Overfull/underfull box count — use the detection recipes in [`../shared/overfull-boxes.md`](../shared/overfull-boxes.md), NOT a `Warning` grep (box lines carry no `Warning` token) - Undefined citation count - Missing package count ### 2d. Auto-fix (up to 3 iterations) For each error, apply the known fix from the database: | Error pattern | Fix | |--------------|-----| | Missing package `X` | Add `\usepackage{X}` — but NEVER try `xltabular` or `ltablex` (use `longtable` instead) | | Undefined citation `key` | Check .bib file exists and is referenced; check for typos via edit distance | | Overfull/underfull box | Flag location + width per [`../shared/overfull-boxes.md`](../shared/overfull-boxes.md) — do NOT auto-fix prose (only safe auto-fix is adding `microtype` when absent) | | tcolorbox `=` or `,` in title | Wrap title in braces: `title={...}` | | Font encoding warning | Add `\usepackage[T1]{fontenc}` if missing | | Missing `\begin{document}` | Check for corrupted preamble | | Broken symlink in `\input{}` or `\includegraphics{}` | Find the target and report | | Build artifacts in source dir | Flag — offer to move to `out/` | After each fix, recompile. Max 3 iterations per project. **Why 3 iterations (not 5)?** `latex` runs up to 5 iterations on a single project with deep error analysis. This skill trades depth for breadth — 3 iterations is enough to catch the common fleet-wide issues (missing packages, broken symlinks, stale cache) without spending excessive time on any one project. If a project still has errors after 3 iterations, mark it as ERROR and recommend running `latex` on it directly for deeper diagnosis. ### 2e. Record result ```json { "project": "project-name", "path": "/full/path", "status": "OK | FIXED | ERROR", "errors_initial": 3, "errors_final": 0, "fixes_applied": ["added fontenc", "fixed tcolorbox title"], "warnings": 2, "undefined_citations": 0 } ``` ## Phase 3: Cross-Project Checks After all projects are compiled: 1. **Symlink integrity** — verify all symlinks in skills/, agents/, rules/, hooks/ resolve 2. **Shared .bib consistency** — if multiple projects reference the same .bib file (e.g., via symlink), verify they're all pointing to the same version 3. **Overleaf separation** — scan every `paper/` directory for forbidden file types (.py, .R, .csv, .ipynb, etc.) 4. **Template consistency** — check if projects using the working paper template have diverged from the current template version ## Phase 4: Report Generate a summary report: ``` LaTeX Health Check — YYYY-MM-DD Projects scanned: N Compiled OK: N (list) Fixed and OK: N (list + fixes applied) Still broken: N (list + remaining errors) Skipped: N (list + reason) Cross-project issues: Broken symlinks: N Overleaf violations: N Template drift: N Warnings (not auto-fixed): Overfull hboxes: N across M projects Underfull hboxes: N across M projects ``` Print to stdout. If `--save` flag or 10+ projects scanned, also write to `log/latex-health/YYYY-MM-DD.md`. ### 4.1 Output verification (before commit) When writing the report file, emit an outputs manifest and run the shared verifier per [`_shared/verify-outputs.md`](../_shared/verify-outputs.md): 1. Write manifest to `/.claude/state/outputs-manifest-.json` listing every file written this invocation, paths relative to the project root. 2. Run: ```bash uv run python "/_shared/verify_outputs.py" \ --manifest "$MANIFEST" \ --project-root "$PROJECT_ROOT" ``` 3. If the verifier exits non-zero, **do not commit**. Surface the missing-files list and stop. Closes the "hallucinated outputs" failure class (commit `b2cff75`, 2026-04-18). Skip this sub-step entirely if `--save` was not passed and no log file was written. ## What This Skill Does NOT Do - Does NOT fix overfull/underfull boxes (requires human judgment on rewording) - Does NOT modify paper content (only build configuration and missing packages) - Does NOT push to git (compilation fixes should be reviewed first) - Does NOT touch Overleaf-synced files without permission (per overleaf-separation rule) ## Cross-References | Skill | Relationship | |-------|-------------| | `latex` | Single-project deep fix (5 iterations). This skill runs a lighter version (3 iterations) at fleet scale. For ERROR projects, recommend running `latex` directly. | | `latex` | Canonical `.latexmkrc` resolution, migration rules, and single-project deep compilation. | | `audit-project-research` | Checks project structure (directories, files). This skill checks build health. | | `bib-validate` | Validates bibliography entries. This skill checks if citations compile. | | `latex-template` | Checks preamble alignment with the working paper template. Complementary: run after health-check to ensure preamble consistency. |