iftypeset (pubstyle) — deterministic Markdown→HTML→PDF, rule registry, QA gates
Find a file
codex 83d783f365
Some checks failed
ci / ci (push) Has been cancelled
audit_report: allow tables to split; keep h4 with content
2026-01-08 23:03:17 +00:00
.forgejo/workflows iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
app iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
docs docs: add zero-context explainer 2026-01-08 20:49:59 +00:00
fixtures iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
forgejo iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
scripts iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
spec audit_report: allow tables to split; keep h4 with content 2026-01-08 23:03:17 +00:00
src/iftypeset audit_report: allow tables to split; keep h4 with content 2026-01-08 23:03:17 +00:00
tests render: keep headings with next blocks 2026-01-08 22:50:34 +00:00
tools iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
.dockerignore iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
.gitignore Initial iftypeset pipeline 2026-01-03 20:29:35 +00:00
AGENTS.md iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
Dockerfile iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
pyproject.toml iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
README.md iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
requirements.txt iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00
STATUS.md iftypeset: document CI pipeline + Playwright + font contract 2026-01-08 18:10:41 +00:00

iftypeset (pubstyle) — publication-quality typesetting pipeline

This project is a thin, deterministic runtime for turning Markdown into highquality HTML/PDF using:

  • A machinereadable rule registry (Chicago / Bringhurst pointers; paraphrased rules only)
  • Typeset profiles (spec/profiles/*.yaml) that map typographic intent → render tokens
  • Postrender QA gates (spec/quality_gates.yaml) that fail builds when layout degrades

It is designed to be embedded into constrained workers (e.g. Forgejo PDF export with --network=none) and also run as a standalone CLI.

Status: working spec + seeded rule registry. See STATUS.md.

Constraints (non-negotiable)

  • No bulk OCR/transcription of Chicago/Bringhurst into this repo (copyright).
  • Rule records are paraphrases only, backed by pointers (e.g. CMOS18 §X.Y pNNN (scan pMMM)).
  • Chicago OCR (when needed) must be ephemeral (extract just enough to locate pointers; do not store page text).
  • Optional profile webtypography_nc is CC BY-NC 4.0 (non-commercial only). See docs/18-webtypography-nc.md.

Quickstart (current)

From ai-workspace/iftypeset/:

  • (Optional) Install deps into a venv: python3 -m venv .venv && . .venv/bin/activate && python -m pip install -r requirements.txt
  • Install the console entrypoint: python3 -m pip install -e .
  • Validate spec + rebuild indexes: iftypeset validate-spec --spec spec --build-indexes
  • One-shot CI pipeline (recommended): iftypeset run --input fixtures/sample.md --out out --profile web_pdf --degraded-ok
  • Multi-doc run (directory or glob): iftypeset run --input fixtures --out out --profile web_pdf --degraded-ok
  • Lint Markdown (emits out/lint-report.json + out/manual-checklist.md): iftypeset lint --input fixtures/sample.md --out out --profile web_pdf
  • Lint with auto-fix + post-fix diagnostics: iftypeset lint --input fixtures/sample.md --out out --profile web_pdf --fix --fix-mode rewrite --lint-fixed
  • Render HTML + CSS: iftypeset render-html --input fixtures/sample.md --out out --profile web_pdf
  • Run QA gates (HTML fallback if no PDF): iftypeset qa --out out --profile web_pdf
  • Render PDF (if an engine is installed): iftypeset render-pdf --input fixtures/sample.md --out out --profile web_pdf
  • Coverage + trust contract + HTML index: iftypeset report --spec spec --out out (writes out/report/index.html)
  • Environment/determinism report: iftypeset doctor --spec spec --out out
  • Portable review bundle: iftypeset bundle --out out (writes out/iftypeset-bundle.tar.gz)
  • Run self-check tests: python3 -m unittest discover -s tests -p 'test_*.py'
  • Inspect profiles/gates/rules:
    • iftypeset profiles list
    • iftypeset gates show --profile web_pdf
    • iftypeset rules list --category links
    • iftypeset rules show HOUSE.LINKS.URLS.PREFER_HTTPS

If you do not want to install the console entrypoint, you can still run:

  • PYTHONPATH=src python3 -m iftypeset.cli <command> ...

Config file (iftypeset.yaml)

You can set repo defaults in ./iftypeset.yaml. CLI flags always win.

Example:

defaults:
  spec: spec
  out: out
  profile: web_pdf
lint:
  fail_on: must
  degraded_ok: true
run:
  skip_pdf: false
  require_pdf: false
  engine: playwright

To use a different config path: iftypeset --config /path/to/iftypeset.yaml <command> ...

Enforcement limits (read this)

  • Not all rules are automated. Manual rules (tagged manual_checklist=true) appear in out/manual-checklist.md.
  • PDF QA is heuristic. It depends on text extraction and will miss some layout failures.
  • Renderer variance exists. Profiles aim for determinism, but output still depends on the PDF engine + fonts.
  • Trust contract is explicit. Run iftypeset report to generate out/trust-contract.md with current limits.

Lint suppression (explicit, auditable)

You can suppress specific rules in a document when needed:

  • Inline directive (applies to the next non-empty line):
    • <!-- iftypeset:ignore CMOS.PUNCTUATION.PARENS_BRACKETS.BALANCE -->
  • Front matter allowlist:
    • iftypeset_ignore: [CMOS.PUNCTUATION.PARENS_BRACKETS.BALANCE, LINK.WRAP.RISK]

Suppression works by rule id or diagnostic code and should be used sparingly.

Session resilience (avoid “lost work”)

If a chat/session resets, trust the repo, not the transcript:

  • Quick resume: ./scripts/resume.sh
  • Audit repo state: ./scripts/audit.sh
  • Run CI sanity checks: ./scripts/ci.sh
  • Create a portable restore point: ./scripts/checkpoint.sh "short note"

Details: docs/07-session-resilience.md Handoff snapshot: docs/08-handoff.md Project status: docs/09-project-status.md Downloadable summary: docs/11-project-summary.md Rendering pipeline: docs/17-rendering-pipeline.md Non-commercial WebTypography profile: docs/18-webtypography-nc.md Agent notes: AGENTS.md External review pack: docs/14-external-review.md Docker runtime: docs/15-docker.md

PDF renderers

render-pdf defaults to playwright and does not fall back silently.

  • playwright (preferred; supports header/footer templates and avoids Chromium CLI “date/path” headers/footers)
  • Optional (explicit --engine only): wkhtmltopdf, weasyprint

If no engine is present, the command exits with a clear message but still leaves HTML artifacts for QA.