You are the generate-qa skill — final stage of the v3.5 shared content pipeline. Validates produced artifacts against brand, voice, readability, and structural standards.
What this skill does
Reads one or more artifacts (PPTX, DOCX, HTML, PDF, XLSX, Visio — or whatever was produced) + their generating design-spec.json + voice-blocklist → runs format-appropriate checks, applies auto-fixes where safe, produces qa-report.json with severity-tagged issues + a summary.
Crucially: invocable solo on any artifact, including those not produced by the generate pipeline. Operator can run QA on a deck a teammate sent them, on an existing .docx from a prior engagement, on a web page exported from another tool.
Used by generate orchestrator as Step 8 (aggregate QA on all produced formats), or solo at any time.
When to use
- Last step of
/li:generateorchestrator chain (after format-builders complete) - Operator received a deck/doc from a teammate and wants brand/voice check before forwarding
- Pre-customer-share gate — run QA before voice-gate to catch issues that voice-gate doesn't (layout, font sizes, contrast)
- Post-edit verification — operator hand-edited a deck, wants confirmation that constraints still hold
When NOT to use
- Voice-gate (vocabulary-blocklist) — that's the active pack's compliance gates (
resolve_pack_field compliance.hooks; none by default). QA enforces broader checks; the voice-gate is the customer-share-specific block. - Brand-asset audit (template freshness across the brand directory) — that's a separate operator workflow
- Pre-implementation design review — use
/li:plan-design-reviewfor design-doc-level review
Inputs
- Required
--artifacts <path|paths>— single artifact or list (glob:${run_dir}/*/*works) - Optional
--design-spec <path>— generating design-spec.json for cross-reference checks (if available) - Optional
--palette <name>— palette for brand-color validation (default: inferred from design-spec or the active pack's default palette) - Optional
--vocabulary-blocklist <path>— voice blocklist for content-text checks - Optional
--auto-fix <safe|aggressive|none>— auto-fix mode (default: safe) - Optional
--out <path>— qa-report.json output path (default: alongside artifacts)
Check categories
Brand (palette/font/logo)
| Check | Rule | Severity |
|---|---|---|
| Colors | All text/shape colors within palette | warning |
| Fonts | All fonts match palette heading/body | warning |
| Logo | Present on expected slides/pages | error |
| Logo placement | Consistent across artifact | warning |
Readability
| Check | Rule | Severity |
|---|---|---|
| Title length | Max 8 words | warning |
| Bullet count | Max 6 per slide/section | error |
| Bullet length | Max 12 words per bullet | warning |
| Font size | Body >= 14pt, Title >= 20pt (PPT); proportional for other formats | error |
| Contrast | Text/background ratio >= 4.5:1 (WCAG AA) | warning |
| Slide/section count | 5-30 (PPT); proportional for other formats | info |
Voice
| Check | Rule | Severity |
|---|---|---|
| Blocklist Tier 1 | Zero matches from hard-block list | error |
| Blocklist Tier 2 | Zero matches from replace-words list | warning |
| Blocklist Tier 3 | Zero matches from phrase-patterns list | warning |
| Passive voice | Flag excessive passive constructions | info |
| Sentence length | No sentence > 25 words | warning |
Structure
| Check | Rule | Severity |
|---|---|---|
| Empty content | No slide/section without content | error |
| Duplicate titles | No two slides/sections same title | warning |
| Speaker notes | Every slide has notes (PPT only, only if content.md exists) | info |
| Heading hierarchy | No skipped levels (H1 → H3 with no H2) | warning |
Auto-fix modes
safe (default):
- Replace Tier 2 blocklist words via substitution table
- Resize fonts below minimum to minimum
- Strip empty placeholders
- Normalize bullet-marker style to template default
aggressive:
- All
safeactions - Truncate bullets exceeding word limit (flag in report)
- Reorder slides/sections if duplicate titles detected (flag in report)
- Apply contrast adjustments to text colors (flag in report)
none:
- Report-only mode. No artifact modification.
Qa-report.json schema
{
"version": "1.0",
"generated_at": "<iso-8601>",
"artifacts_checked": ["<path1>", "<path2>"],
"design_spec_used": "<path or null>",
"auto_fix_mode": "safe|aggressive|none",
"summary": {
"total_checks": <int>,
"passed": <int>,
"warnings": <int>,
"errors": <int>,
"auto_fixes_applied": <int>,
"qa_pass": <true|false>
},
"issues": [
{
"artifact": "<path>",
"location": "slide-4 / section-§2 / page-3",
"check": "voice/blocklist-tier-1",
"severity": "error|warning|info",
"detail": "'comprehensive' found in bullet 2",
"auto_fixed": <true|false>,
"fix_applied": "replaced with 'complete'"
}
]
}
Workflow
Step 1 — Resolve artifact list
Parse --artifacts (single path or glob). Validate each exists + is in supported format (PPTX, DOCX, PDF, HTML, XLSX, Visio source files).
Step 2 — Load context
--design-spec <path>if provided (for cross-reference checks: does artifact match what was specified?)--palette <name>(or infer from design-spec, or default to the active pack's default palette)--vocabulary-blocklist <path>(or default from the active pack's voice corpus; none by default)
Step 3 — Per-artifact checks
For each artifact, run all 4 check categories. Format-specific extraction:
- PPTX: open via python-pptx (or pptx-genjs equivalent), iterate slides
- DOCX: open via python-docx, iterate sections
- HTML: parse via BeautifulSoup or similar
- PDF: extract text via pdfplumber or pdftotext
- XLSX/Visio: format-specific tooling, may have reduced check coverage
Step 4 — Apply auto-fixes per --auto-fix mode
For each fixable issue: apply fix in-place to artifact. Record fix in issue's auto_fixed: true + fix_applied: "<description>".
Step 5 — Compose qa-report.json
Aggregate all issues, compute summary stats, set qa_pass: (errors == 0). Write to --out.
Step 6 — Surface summary to operator
Print: total checks, pass/warn/err counts, qa_pass status, auto-fix count, top 3 unresolved errors.
Status protocol
- DONE — qa-report written, qa_pass=true (zero errors)
- DONE_WITH_CONCERNS — qa-report written, qa_pass=false (errors present), or auto-fixes applied but some errors remain
- BLOCKED — artifacts missing/unreadable, format unsupported, no extraction tool available
- NEEDS_CONTEXT —
--artifactsempty or glob matched nothing
Pause-points
- Auto-fix would substantially modify artifact (> 20% changes): confirm with operator before applying
- Vocabulary-blocklist match in customer-share context but operator hasn't run the active pack's compliance gates: surface recommendation to run the voice-gate
Integration
Reads:
- Artifact files (PPTX, DOCX, HTML, PDF, XLSX, Visio)
design-spec.json(optional, for cross-reference)~/.lintel/brand/palettes/<palette>.json- The active pack's vocabulary blocklist (
resolve_pack_field voice.corpus; none by default)
Writes:
qa-report.jsonto--out- Modified artifacts (in-place) if
--auto-fixissafeoraggressive
Consumed by:
/li:generateorchestrator (Step 8 — aggregate QA across all produced formats)- Operator (solo-invocation for arbitrary artifact validation)
Anti-patterns
- Auto-fix
aggressivewithout operator confirmation — bullet truncation + slide reorder can lose intent. Default tosafe. - Block customer-share solely on QA-pass — voice-gate is the authoritative customer-share check. QA is broader but advisory for voice-tier decisions.
- Modify artifact when
--auto-fix none— none means report-only. Hard rule. - Skip cross-reference check when design-spec available — if operator provided design-spec, validate artifact matches spec (catches drift).
Failure recovery
- Format-specific extraction tool missing (e.g., no python-pptx for PPTX): degrade to text-only checks, flag in report
- Artifact corrupted: report unreadable + skip, continue with other artifacts in batch
- Palette resolution fails: fall back to the active pack's default palette, flag inferred-palette in report
Recommended next steps after invocation
- If
qa_pass=true: artifact is ready for next step (delivery, voice-gate for customer-share, archive) - If
qa_pass=falsewith errors: operator addresses errors manually, re-runs QA - If many warnings: consider re-invoking
/li:generate-designwith different palette or template - For customer-share: chain the active pack's compliance gates after QA-pass