3.9 KiB
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 (
*.mdand anout/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
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
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)
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)
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)
iftypeset qa --out out --profile web_pdf
Reports (human artifact hub + trust contract)
iftypeset report --spec spec --out out
Outputs a clickable hub:
out/report/index.htmlout/trust-contract.mdandout/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.jsonout/manual-checklist.md(and optionally.json)out/render.html+out/render.cssout/render.pdf(when a PDF engine is available)out/layout-report.jsonout/qa-report.jsonout/run-summary.jsonout/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:
- CLI flags
iftypeset.yaml- profile defaults
- 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
mustvsshould - 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
iftypesetas “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).