* feat(skill): add documents family skill (PDF / Word / Excel / PowerPoint) One family skill for PDF, Word (.docx), Excel (.xlsx), and PowerPoint (.pptx) per the family-skill rule (epub precedent): shared workflow in SKILL.md (scope, content model, template, render, validate, deliver) with per-format load-on-demand references, generation templates per format, a stdlib validation script (--json, structural sanity + render check with graceful degradation), one fixture per format, a unittest suite, six output-quality eval cases spanning all four formats, a human README, the README.md index entry, and regenerated catalogs. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix(skill): dispatch PDF renderer args per binary in documents validation The render check passed pdftoppm-only flags (-png/-r/-f/-l) to mutool and ghostscript, which reject them, so a machine with only mutool or gs would false-FAIL valid PDFs. Dispatch per-renderer argument sets (pdftoppm -png; mutool draw -o; gs -sDEVICE=png16m) and cover the dispatch with a unit test. Also: count PDF pages via the /Count page-tree fallback (page objects can hide in compressed ObjStm streams), drop the stale "unsupported input" exit-2 claim from the docstring, and stop labeling skipped files with a FAIL check. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * style(skill): drop redundant local tempfile import in renderer dispatch test Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --------- Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
4.5 KiB
Output-Quality Validation — All Four Formats
Last Updated: 2026-08-03
Load this reference when you need to verify a produced document before
delivery, regardless of format. It is step 5 (validate) of the shared
workflow in SKILL.md, expanded into a checklist that applies to PDF, Word,
Excel, and PowerPoint alike, plus the exact behavior of the validation script.
Why validate at all
The most common document defects are structural, not typographical: a file that opens in one application and corrupts in another, a spreadsheet whose cells are invisible to formulas, a deck whose slides do not render. Structural validation catches these before delivery, cheaply and deterministically, and a render check catches the next class (layout, fonts, overflow) whenever a renderer is available.
Two layers of checking
1. Structural sanity (always available, stdlib only)
The validation script checks properties that any reader depends on:
| Format | Checks |
|---|---|
%PDF- header, %%EOF trailer, at least one page object |
|
| Word (.docx) | ZIP container, [Content_Types].xml, word/document.xml well-formed |
| Excel (.xlsx) | ZIP container, [Content_Types].xml, xl/workbook.xml + worksheet parts well-formed |
| PowerPoint (.pptx) | ZIP container, [Content_Types].xml, ppt/presentation.xml + slide parts well-formed |
These checks need no third-party packages, so validation always runs.
2. Render check (best effort, graceful)
When an external renderer is installed, the script additionally renders the
file — pdftoppm/mutool/gs rasterize PDF page 1; LibreOffice converts
Office formats to PDF. When no renderer is available for a format, the render
check reports unavailable in the JSON and exits 0: a missing renderer is an
environment fact, not a document defect. Never block delivery on a render
check you could not run; say so in the provenance instead.
Running the validation script
python3 scripts/validate-documents.py report.pdf brief.docx data.xlsx deck.pptx
python3 scripts/validate-documents.py --render-check --json report.pdf data.xlsx
Exit codes:
- 0 — every file passes structural validation (and any attempted render succeeded, or no renderer was available).
- 1 — at least one file fails structure or an attempted render failed.
- 2 — usage/I/O error (missing or unreadable path).
JSON report (--json): top-level status is ok, fail, unavailable, or
error; each file carries per-check results and a render object. The
summary block gives the pass/fail/skip/error counts.
Content-completeness checks
Structure passing does not mean the content is right. Before delivery, confirm the artifact matches the agreed scope:
- Expected sections present — the scope's headings/slides/sheets all exist.
- No placeholder remnants — no unresolved
[fill: ...]markers,TODOtext, or lorem ipsum from the template. - Data intact — for Excel, spot-check cell values against the source data; for prose, check a few paragraphs verbatim.
- Metadata set — title/author where the reader displays it.
Visual and layout quality
Renderer-dependent, so verify when a renderer is available or by opening the artifact:
- No overflow — text fits boxes/cells/slides; no clipped content.
- No missing glyphs — fonts embedded (PDF) or available (Office); no
tofuboxes. - Consistent styling — headings use styles; decks use one layout family.
- Page/slide count matches the scope — no blank trailing pages/slides.
Accessibility basics
Accessibility is part of output quality, not a separate concern:
- PDF — tagged PDFs with real text (not scans) and a reading order.
- Word — heading styles (they become the navigation/outline), alt text on images, real tables with header rows.
- Excel — header rows on row 1, no blank separator rows inside tables, meaningful sheet names.
- PowerPoint — alt text on images, sensible shape reading order, notes.
The deliverable gate
A document is ready to deliver when:
scripts/validate-documents.pyexits 0 on it (structure passed).- The render check is
ok(renders) or honestly reported asunavailable(no renderer present). - Content-completeness and visual checks pass against the scope.
- The provenance records the content model, template version, and validation result, so the artifact can be regenerated and re-verified.
Anything less is a known deviation — record it rather than hiding it.