Closes the core pipeline: the `cph` CLI checks an engineering file and compiles a PDF. cph-check — phases (a) load → (b) structural (known-kind set) → (c) schema → (d) typst compile → (e) render-coverage. Compile is gated: skipped if (a)-(c) produced any Error (broken input would only add noise); `check` compiles every declared target (dedup identical diags), `build` compiles the one requested. Render-coverage emits a non-blocking RenderIgnored *warning* when a (kind, target) has no render rule — severity pinned via RENDER_IGNORED_SEVERITY const citing spec Diagnostic.renderIgnoredSeverity + ADR-0005. No double-emit: unknown/missing parts are skipped downstream. API: check(root, engine) -> CheckReport, build(root, engine, target) -> (Option<pdf>, CheckReport). cph-cli — clap: `cph check <path>` (exit 1 on any Error, warnings → 0) and `cph build <path> --target <name> [-o out]` (default target student, default out <path>/build/<target>.pdf). Diagnostics → stderr via Display, results → stdout. --render-dir override. End-to-end on examples/TH-141 (39 parts): `check` → 0 errors/0 warnings; `build` → real PDF student 9pp/395KB, teacher 12pp/474KB. Broken-element check (unclosed delimiter in a stmt.typ) → span-accurate `error[E-TYPST-COMPILE]: unclosed delimiter --> lemmas/…/stmt.typ:7:8`, exit 1. Workspace: fmt + clippy -D warnings + test all green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
crates/
These crates implement the rule-based lesson checker that aligns to the
semantic master in spec/: it reads an engineering-file (one lesson, ADR-0005)
laid out per ADR-0008 (declarative manifest.toml + per-element
element.toml), validates structure and content, and emits diagnostics.
cph-diag (the shared diagnostic vocabulary), cph-model (the ADR-0008 loader),
and cph-typst (the typst World / compile / span-mapping layer) are
deliberately reusable by future components such as an exporter, which is why
they live in this repo-wide crates/ directory rather than under any single
component; cph-schema (kind JSON Schemas + validation), cph-check
(orchestration + render-coverage) and cph-cli (the cph command-line
entrypoint) are the checker proper.
Crate map
| crate | owner | role |
|---|---|---|
cph-diag |
WU-1 | shared diagnostic vocabulary (Severity, DiagCode, Diagnostic, SourceSpan) — reusable |
cph-model |
WU-1 | parses the ADR-0008 layout into an in-memory ordered Lesson — reusable |
cph-schema |
WU-3 | the 4 stdlib kind JSON Schemas + structural validation |
cph-typst |
WU-4 | typst World, driver generation, compile, PDF, span mapping — reusable |
cph-check |
WU-5 | orchestration: render-coverage and the full check pipeline |
cph-cli |
WU-5 | the cph command-line entrypoint |
Build
# from the repository root (the cargo workspace root)
cargo build # all crates
cargo test # cph-diag + cph-model unit/integration tests
cargo clippy --all-targets -- -D warnings
cargo fmt --check