6.7 KiB
iftypeset external review pack (public technical overview)
This document is a self-contained brief for external reviewers. It explains what the project does, what is implemented today, how to verify it locally, and what limitations remain. It does not include any copyrighted book text.
Scope and non-negotiables
- No Chicago/Bringhurst text is stored here. Rules are paraphrases with pointer refs only.
- The runtime is deterministic by design, but PDF output still depends on the chosen renderer and fonts.
- QA is rule- and heuristic-based; it does not claim perfect layout verification.
What iftypeset is
iftypeset is a deterministic Markdown -> HTML -> PDF pipeline with:
- a machine-readable rule registry (NDJSON) with paraphrased rules + pointers
- profiles that map typographic intent into CSS tokens
- lint + QA gates that surface layout failures and fail builds in CI
The core value is not "pretty PDF." It is verifiable, repeatable quality gates and explicit limits.
What is implemented now
Runtime surface (CLI):
validate-spec,report,lint,render-html,render-pdf,qa,emit-css,run- introspection:
profiles list,gates show,rules list,rules show
Artifacts produced:
out/lint-report.json,out/manual-checklist.md/jsonout/render.html,out/render.css,out/render.pdf(if renderer present)out/layout-report.json,out/qa-report.jsonout/coverage-report.json,out/coverage-summary.mdout/trust-contract.md/jsonout/report/index.html(HTML index of all artifacts)out/run-summary.json(CI-style run summary)
Quick verification (local)
From the repo root:
python3 -m venv .venv
. .venv/bin/activate
python3 -m pip install -r requirements.txt
python3 -m pip install -e .
iftypeset validate-spec --spec spec --build-indexes
iftypeset run --input fixtures/sample.md --out out --profile web_pdf --degraded-ok --skip-pdf
iftypeset report --spec spec --out out
Expected files after a successful run:
out/run-summary.jsonout/report/index.htmlout/lint-report.jsonout/render.htmlout/layout-report.jsonout/qa-report.json
If you have a PDF engine installed, omit --skip-pdf and expect out/render.pdf + out/render-log.json.
Proof points (code excerpts)
Console entrypoint (shows the CLI is installed as a tool):
[project.scripts]
iftypeset = "iftypeset.cli:main"
CI pipeline definition (ensures spec validation + report + tests run):
run_step "validate-spec" env PYTHONPATH=src python3 -m iftypeset.cli validate-spec --spec spec --build-indexes
run_step "report" env PYTHONPATH=src python3 -m iftypeset.cli report --spec spec --out out --build-indexes
run_step "tests" python3 -m unittest discover -s tests -p 'test_*.py'
End-to-end integration test (lint -> render -> qa):
lint = subprocess.run([... "lint", "--input", fixture, "--out", out_dir, "--profile", "web_pdf"], ...)
render = subprocess.run([... "render-html", "--input", fixture, "--out", out_dir, "--profile", "web_pdf"], ...)
qa = subprocess.run([... "qa", "--out", out_dir, "--profile", "web_pdf"], ...)
CI-style run command writes a single summary artifact:
{
"ok": true,
"exit_code": 0,
"started_at_utc": "...",
"finished_at_utc": "...",
"steps": [
{"name": "validate-spec", "rc": 0, "ok": true},
{"name": "lint", "rc": 0, "ok": true},
{"name": "render-html", "rc": 0, "ok": true},
{"name": "render-pdf", "rc": 3, "ok": false},
{"name": "qa", "rc": 0, "ok": true},
{"name": "report", "rc": 0, "ok": true}
]
}
Rule registry (how to read it)
- NDJSON files in
spec/rules/**.ndjson - Schema in
spec/schema/rule.schema.json - Pointers in
source_refs(e.g.,CMOS18 §X.Y pNNN (scan pMMM)orHOUSE §... pN) - No verbatim book text is stored in this repo
Example record shape (paraphrased, non-quoted):
{
"id": "HOUSE.LINKS.URLS.PREFER_HTTPS",
"category": "links",
"severity": "should",
"enforcement": "lint",
"rule_text": "Prefer https links in published outputs."
}
Lint and manual checklist
- Automated rules are enforced in
src/iftypeset/linting.py. - Non-automated rules are tagged
manual_checklist=trueand emitted toout/manual-checklist.md. - This ensures reviewers see what still needs human validation.
QA (HTML + PDF)
HTML analysis:
- detects overfull tokens, table/code overflow risk, long URL wrapping risk
PDF analysis (heuristic):
- uses Poppler (
pdfinfo,pdftotext -layout) to extract per-page text - detects widows/orphans, stranded headings, overfull lines
- warnings are explicit about heuristic limits
Renderers
render-pdf uses the requested engine (default: playwright):
playwright(preferred; supports header/footer templates)wkhtmltopdf(explicit--engine wkhtmltopdfonly)weasyprint(explicit--engine weasyprintonly)
If no engine is present, render-pdf returns exit code 3 and QA continues with HTML.
Trust contract
iftypeset report generates:
out/trust-contract.mdout/trust-contract.json
These explicitly state:
- enforced vs manual coverage
- QA limitations
- determinism assumptions
This is the preferred artifact for external review.
Production readiness (what is true today)
Verified by CI and tests:
- spec validation and coverage reporting are deterministic
- lint emits JSON + manual checklist and is stable across runs
- HTML rendering is deterministic given the same inputs
- QA gates are enforced with explicit exit codes
runprovides a single CI-friendly summary artifact
Known limitations:
- PDF QA is heuristic, not geometry-accurate
- PDF output depends on renderer + font availability, but
render-log.jsonrecords font resolution/embedding and profiles can enforce a strict fonts contract to prevent silent fallbacks - not all rules are automated; manual checklist remains required
Where to look in the repo
- CLI:
src/iftypeset/cli.py - Linting:
src/iftypeset/linting.py - QA:
src/iftypeset/qa.py - Rendering:
src/iftypeset/rendering.py - Rule schema:
spec/schema/rule.schema.json - Rule batches:
spec/rules/**.ndjson - Profiles:
spec/profiles/*.yaml - Trust contract:
out/trust-contract.md(generated) - Report index:
out/report/index.html(generated)
Forgejo integration (worker)
The Forgejo worker can load the iftypeset-web_pdf theme (vendored CSS). See:
forgejo/README.mdin this repoworker/pdf/README.mdin the forgejo-pdf repo
Contact and review checklist
For external review, please verify:
iftypeset runsucceeds and producesout/run-summary.jsonout/report/index.htmllinks to all expected artifactsout/trust-contract.mdreflects the current enforcement splitout/manual-checklist.mdexists and is non-empty