qa-quarto — Claude Code skill: parity checks and installation
Checks Quarto slide HTML against a Beamer PDF and runs a review-and-fix cycle. Use it to spot content or visual differences between the two versions.
npx skills add pedrohcgs/claude-code-my-workflow --skill qa-quarto -a claude-codeWhat qa-quarto does
The skill assigns a critic agent to compare the slides and a fixer agent to address confirmed issues. It then renders the changes and runs the review again. The cycle stops after two rounds with no new major findings, or at the five-round fallback limit; unresolved issues go into the final report.
You need a rendered .qmd file and a Beamer PDF benchmark. The checks cover clipped content, missing slides or equations, and mathematical notation. scripts/slide-qa.py opens the HTML in headless Chrome and produces a report with slide screenshots. If Playwright is missing, that measurement step cannot run, so the critic falls back to reviewing the source.
Reports are saved under quality_reports. Reviewer agents cannot write files, so the skill saves their reports and validates the findings. The final report records gate results and any remaining issues.
What it helps with
- compare Quarto slide HTML with a Beamer PDF benchmark
- find missing slides, equations, or text
- catch clipped content and broken images
- apply confirmed fixes and run the review again
Example prompts for the agent
- Check whether the HTML rendered from
Lecture1.qmdmatches the Beamer PDF. - Compare my Quarto slides with the PDF benchmark and fix the confirmed differences.
How to install qa-quarto
1Skills CLI (Vercel)
npx skills add pedrohcgs/claude-code-my-workflow --skill qa-quarto -a claude-code2Manually: put the files in place
~/.claude/skills/qa-quarto/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/qa-quarto/
1Skills CLI (Vercel)
npx skills add pedrohcgs/claude-code-my-workflow --skill qa-quarto -a codex2Manually: put the files in place
.agents/skills/qa-quarto/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add pedrohcgs/claude-code-my-workflow --skill qa-quarto -a cursor2Manually: put the files in place
.cursor/skills/qa-quarto/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install pedrohcgs/claude-code-my-workflow qa-quarto2Manually: put the files in place
.github/skills/qa-quarto/SKILL.md1Skills CLI (Vercel)
npx skills add pedrohcgs/claude-code-my-workflow --skill qa-quarto -a gemini-cli2Platform CLI
gemini skills install https://github.com/pedrohcgs/claude-code-my-workflow --path .claude/skills/qa-quartoManually: put the files in place
.devin/skills/qa-quarto/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add pedrohcgs/claude-code-my-workflow --skill qa-quarto -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about qa-quarto
How do I install qa-quarto in Claude Code?
Run npx skills add pedrohcgs/claude-code-my-workflow --skill qa-quarto -a claude-code. The skill file is at ~/.claude/skills/qa-quarto/SKILL.md.
What does qa-quarto do?
It compares a Quarto HTML deck with a Beamer PDF, sends confirmed issues for fixes, and repeats the review. A final report records the check results and any remaining issues.
What files does qa-quarto need?
It needs a rendered .qmd file and a Beamer PDF benchmark. The overflow measurement script scripts/slide-qa.py also needs Playwright to run.
Source text
SKILL.md · MIT
---
name: qa-quarto
description: Adversarial Quarto-vs-Beamer parity QA. A critic agent compares the Quarto HTML render to the Beamer PDF benchmark for content/visual parity; a fixer agent applies fixes; loops until APPROVED or two consecutive rounds turn up nothing new (fallback cap 5 rounds). Use when user says "qa the quarto", "check parity", "does the html match the pdf?", "quarto matches beamer?", or after a translate-to-quarto run. Requires both the `.qmd` rendered and a `.pdf` benchmark.
argument-hint: "[LectureN]"
allowed-tools: ["Read", "Grep", "Glob", "Write", "Edit", "Bash", "Agent", "Task"]
context: fork
---
# Adversarial Quarto vs Beamer QA Workflow
Compare Quarto HTML slides against their Beamer PDF benchmark using an iterative critic/fixer loop.
**Philosophy:** The Beamer PDF is the gold standard. The Quarto translation must be at least as good in every dimension.
---
## Workflow
```
Phase 0: Pre-flight → Phase 1: Critic audit → Phase 2: Fixer → Phase 3: Re-audit → Loop until APPROVED or dry (2 consecutive dry rounds; fallback cap 5)
```
## Hard Gates (Non-Negotiable)
| Gate | Condition |
|------|-----------|
| **Overflow** | NO content cut off |
| **Plot Quality** | Interactive charts >= static plots |
| **Content Parity** | No missing slides/equations/text |
| **Visual Regression** | Quarto >= Beamer in all dimensions |
| **Slide Centering** | Content centered, no jumping |
| **Notation Fidelity** | All math verbatim from Beamer |
## Phase 0: Pre-flight
1. Locate Beamer (.tex/.pdf) and Quarto (.qmd/.html) files
2. Check freshness (re-render if QMD newer than HTML)
3. Verify TikZ SVGs if applicable
4. Measure the render: `"${SLIDE_QA_PYTHON:-python3}" scripts/slide-qa.py Quarto/[Lecture].html`. It loads the deck in headless Chrome and writes `quality_reports/audits/slide-qa/[Lecture]/report.md` with per-slide overflow in pixels, plus one screenshot per slide. Exit 1 means it found something — overflow, clipped content, a broken image, or a missing or wrong-case file; exit 2 means it could not run (usually Playwright is missing — the script prints the one-time venv install and the `SLIDE_QA_PYTHON` line to set) — say so, and the critic falls back to reading the source.
## Phase 1: Initial Audit
Launch the `quarto-critic` agent to compare Beamer vs Quarto comprehensively, passing the slide-qa report path from Phase 0 for the Overflow gate. Report saved to `quality_reports/[Lecture]_qa_critic_round1.md`.
## Phase 2: Fix Cycle
If not APPROVED, launch `quarto-fixer` agent to apply fixes (Critical → Major → Minor), re-render, and verify.
## Phase 3: Re-Audit
Re-run `scripts/slide-qa.py` on the fixer's re-render, then re-launch the critic with the fresh report to verify fixes. Loop back to Phase 2 if needed.
## Iteration Limits — loop-until-dry
This is the **loop-until-dry** primitive from [`orchestrator-protocol.md`](../../rules/orchestrator-protocol.md): the critic returns `FINDING`s (the hard-gate table is the CRITICAL roll-up, per [`orchestration-schemas.md`](../../references/orchestration-schemas.md)); the loop **converges after 2 consecutive dry rounds** — rounds that add 0 new CRITICAL/MAJOR findings (deduped on `id = sha1(file:line:locus)`) — not at a fixed round count.
- **Fallback cap:** 5 rounds bounds a non-converging loop, then escalate to the user with remaining issues.
- **Two-strikes:** the same gate failing in rounds N and N+2 is flagged for the user, not patched again ([`summary-parity.md`](../../rules/summary-parity.md)).
- APPROVED iff every hard gate passes and no CRITICAL or MAJOR finding remains (minor ones are listed for the user).
## Final Report
Save to `quality_reports/[Lecture]_qa_final.md` with hard gate status, iteration summary, and remaining issues.
## Findings are validated, not just written (v2.5)
This skill's reviewers emit findings under the machine-checked contract in
[`finding-schema.json`](../../references/finding-schema.json). Reports are JSON **arrays**.
**Smoke-test the harness before spending review effort** — a run that fans out reviewers and
then cannot write a valid report has wasted the whole pass:
```bash
echo '[]' | python3 scripts/validate-findings.py
```
Reviewer agents are read-only, so **this skill writes the files**. For each reviewer's final
response: save the prose report to this skill's report path for that reviewer, copy its closing fenced `json` block
to a scratch file, and fill the ids while validating:
```bash
python3 scripts/validate-findings.py --fill-ids block.json > <report>.json.tmp \
&& mv <report>.json.tmp <report>.json || rm -f <report>.json.tmp # exit 0 required; a failed run keeps no file
python3 scripts/validate-findings.py --check-quotes <report>.json # each quote must be the file's own text (orchestration-schemas.md §1)
```
A reviewer that returned no `json` block, or a block that does not validate, has not reviewed:
re-dispatch it once with the validator's error text, then report the lens as missing rather
than reducing without it.
What the contract forces, and why:
- **`rule`** — the documented rule or standard violated. A finding citing no rule is an
opinion, and opinions do not gate a commit.
- **`failing_case`** — a concrete configuration under which the claim breaks, or the exact
missing hypothesis. *"This could be clearer"* does not validate.
- **`id = sha1("<file>:<line>:<locus>")`** — deterministic, so dedup across rounds is
exact and the two-strikes rule is checkable rather than eyeballed.
- **`mechanical`** — `true` only for fixes that cannot change a result (typo, cross-reference,
formatting, label). **Never** for an estimand, assumption, specification, inference
procedure, sample definition, or reporting language: those return to the researcher.
Apply the **per-lens evidence burdens** and the **"does NOT count" filters** in
[`orchestration-schemas.md` §7](../../references/orchestration-schemas.md) *before*
verification, so known false alarms never reach the judge. The verifier pass is
**refute-biased** and sets each finding's `verdict` (reviewers leave it unset): only `verdict: "confirmed"` findings ship; anything it cannot ground is
dropped, not downgraded to a warning.
© pedrohcgs · MIT · pedrohcgs/claude-code-my-workflow