# `iftypeset` as Document CI (the mental model) `iftypeset` should behave like **eslint + a renderer + a preflight tool + a report generator**. Rendering is *one* stage. The product is: **profiles + gates + artifacts + exit codes**. This document is the “shared understanding” for humans and Codex sessions. --- ## The pipeline **Input:** Markdown (plus assets) **Profile:** `web_pdf`, `print_pdf`, `dense_tech`, `memo`, `slide_deck` **Pipeline:** `validate → lint → render → qa → report` **Output:** - Machine artifacts (`*.json`, optionally `*.sarif`) - Human artifacts (`*.md` and an `out/report/index.html`) - Deterministic outputs (or explicit nondeterminism in the trust contract) - Exit codes that CI can gate on (no “looks good on my machine”) --- ## The one command humans and CI want ```bash iftypeset run --input docs/spec.md --profile web_pdf --out out ``` Expected behavior: - Runs the full pipeline. - Writes artifacts under `out/`. - Exits **non-zero** when must-level gates fail. - Prints a short, boring summary to stdout (what failed, where to look). --- ## Subcommands (when you want control) ### Spec + registry ```bash iftypeset validate-spec --spec spec --build-indexes iftypeset profiles list iftypeset gates show --profile web_pdf iftypeset rules list --category links iftypeset rules show HOUSE.LINKS.URLS.PREFER_HTTPS ``` ### Lint (source-level) ```bash iftypeset lint --input docs/spec.md --profile web_pdf --out out iftypeset lint --input docs/spec.md --profile web_pdf --out out --fix --fix-mode rewrite ``` ### Rendering (adapter-based) ```bash iftypeset render-html --input docs/spec.md --profile web_pdf --out out iftypeset render-pdf --input docs/spec.md --profile web_pdf --out out ``` ### Post-render QA (where the money is) ```bash iftypeset qa --out out --profile web_pdf ``` ### Reports (human artifact hub + trust contract) ```bash iftypeset report --spec spec --out out ``` Outputs a clickable hub: - `out/report/index.html` - `out/trust-contract.md` and `out/trust-contract.json` --- ## Exit codes (CI-friendly) The CLI should be unambiguous: - `0`: pass (no failing gates) - `1`: gate failed (must violations / gate thresholds breached) - `2`: usage/config error (bad flags, missing profile, missing input) - `3`: internal/tool error (renderer crash, missing dependency) If we ever add “nondeterminism detected” as a separate code, it must be documented here and in `app/CLI_SPEC.md`. --- ## Artifacts (what you keep) The durable contract is: everything important is written to `out/` and is stable across runs. Minimum set: - `out/lint-report.json` - `out/manual-checklist.md` (and optionally `.json`) - `out/render.html` + `out/render.css` - `out/render.pdf` (when a PDF engine is available) - `out/layout-report.json` - `out/qa-report.json` - `out/run-summary.json` - `out/trust-contract.{md,json}` - `out/report/index.html` The trust contract must state, in plain language: - what is enforced automatically vs manual checklist - QA limitations (what we detect vs what we currently miss) - determinism assumptions (renderer version, fonts, locale) --- ## Configuration Repo defaults live in `iftypeset.yaml`. Priority order: 1. CLI flags 2. `iftypeset.yaml` 3. profile defaults 4. hard defaults Humans need predictable overrides because humans are chaos. --- ## Profiles are the product A profile is a contract, not a vibe: - which rules apply - which are `must` vs `should` - which incidents fail gates - which tokens/CSS are used - which renderer(s) are recommended Everything emitted should name the profile explicitly. --- ## Traps to avoid - Treating `iftypeset` as “pretty PDF generator” instead of CI for doc quality. - Shipping false authority (big rule counts) without a clear enforced/manual split. - Overfitting to one renderer (adapters are the point). - Sneaking copyrighted text into the repo (paraphrase + pointer discipline is non-negotiable).