lcert_build.bundle
Build LCERT-1 certificate bundles from your own analysis.
Everything else in this toolkit consumes certificates. This produces them, so that a checker you already have — thermal, timing, DRC, model evaluation, anything that computes a bound — can emit results a third party re-derives without trusting you.
What this does not do, on purpose. It computes no physics and no bounds. You
supply the intervals; this assembles the commitment spine around them and derives
the admission verdict from your numbers. That boundary is not a promise, it is
lcert_build.assert_no_analysis() and a test that runs it over this package.
The one opinionated behaviour: Bundle.build() verifies what it just
wrote and raises if the result is not what you asked for. Writing a bundle that
does not verify is always a bug, and finding out at the consumer is too late.
A bundle under construction.
::
Bundle("out/thermal")
.preregister({"criterion": "Tj stays below 85 C"})
.bound("hotspots", quantity="junction temperature", unit="K",
threshold=358.15, direction="below", loci=intervals)
.evidence("solver.log")
.build()
Record what you declared before measuring.
Not decoration. A bundle whose acceptance criteria were written after the result is a bundle whose criteria mean nothing, and the preregistration is manifest-covered so it cannot be edited afterwards without detection.
Add an interval-bound certificate.
loci is an iterable of (lo, hi) pairs: your outward-rounded
enclosure of quantity at each locus. direction is "below" or
"above".
If your intervals are not a sound enclosure, this produces a certificate that verifies and is still wrong — no verifier can tell, and none claims to. Rounding outward is your job and it is the load-bearing one.
Record a number that is reported, not certified.
KPIs are committed so they cannot be edited after the fact, but they carry no proof obligation. Nothing is admitted on the strength of one.
Attach a file — a log, a mesh, a model — under the manifest.
The bytes are covered by the Merkle root, so the evidence cannot be swapped after the fact. Nobody re-derives anything from it; it is there so a human investigating a certificate has the trail.
Write the bundle, verify it, and return (path, fingerprint).
The fingerprint is the trust anchor: publish it somewhere the bundle is not, because a bundle that carries its own anchor proves nothing.
Raises unless the verdict is expect. Pass expect="REFUTED" if you
are deliberately producing a failing bundle — for a test, say — and
allow_vacuous=True if certifying nothing is genuinely intended.
The bundle could not be built, or did not verify once built.
The bundle certifies nothing, and that was not declared as intended.