id: ADR-0031
title: Commit every generated source and diff it in CI; never generate in build.rs
status: accepted
date: 2026-09-13
deciders: [paul-heyse]
level: decision
principles: [DM-52, DM-23, DM-48, DM-53]
blueprint: [§4.2, §18.3, §21.5]
review: not-required: a convention stated in §4.2; neither review raised a finding against it
evidence: Proposed
supersedes: []
superseded-by: null
revisit: Generation becomes slow enough that an explicit step is a friction point, or a generated artifact needs a host-specific input a checkout cannot supply
verification: rust / codegen-diff (cargo xtask codegen --check); scripts/check_generated.py in python / lint and pre-commit
ADR-0031: Commit every generated source and diff it in CI; never generate in build.rs
Context
Blueprint §4.2 generates typed relation views, builders, validators, migrations, the Python contract classes, documentation and the Ipopt bindgen output from the registry, and requires the emitted source to be committed.
Scope
Binds where generated code lives, how it is regenerated and how drift is detected. What is generated is §4.2’s subject.
Drivers
A build.rs generator makes the build depend on the host and hides the diff; a generated file that is not committed cannot be reviewed, and the Python contract classes are part of the public API.
Options
Generate in build.rs — rejected: no reviewable diff, and the bindgen step needs the solver container’s headers. Generate on demand and gitignore — rejected: the diff is the review.
Outcome
cargo xtask codegen [--only relations|python|docs|bindgen] writes the four generated paths; every generated file carries // @generated by pse-schema <fingerprint>, #![rustfmt::skip] and a blanket lint allow with a reason. cargo xtask codegen --check runs git diff --exit-code plus an untracked-file check.
Consequences
A registry change is a two-part commit: the registry edit and the regeneration. A prettyplease upgrade is itself a regeneration commit.
Compensating controls
.gitattributes marks the generated paths linguist-generated; the agent settings deny edits under them; check_generated.py holds a sha256 manifest of python/pse/contracts/.
Confirmation
rust / codegen-diff is a required check and runs in the solver container so the bindgen output is regenerated against the pinned headers.
Pros and cons
Committing generated code inflates diffs; not committing it removes the only place the generator’s output is reviewed.
More information
Blueprint §4.2 (what is generated), §18.3 (bindgen output), §21.5 (Python contracts); ADR-0012.
Status history
- 2026-09-13 — accepted with the repository-seeding pull request (backfilled from blueprint revision 3).