Baselines and budgets¶
Compatibility comes first
Compare package-request baselines only with package-request measurements, and project-lock baselines only with project-lock measurements. Existing-prefix results are a separate family and cannot be compared or budgeted yet. Matching input family is necessary but not sufficient: Python, platform, build policy, and resolution context must also be compatible.
Compare a baseline¶
Record a fresh package-request measurement, then compare the same kind of measurement:
uvx uv-packsize requests==2.32.5 --json > baseline.json
uvx uv-packsize requests==2.32.5 --baseline baseline.json
uvx uv-packsize requests==2.32.5 --baseline baseline.json --comparison-json
The default is a text diff; --comparison-json writes a versioned comparison document. Measurements must have compatible definitions and resolution contexts, including requirements, Python/platform fingerprints, build policy, and resolver conditions.
An incomplete but compatible comparison completes and labels its deltas as partial; an incompatible baseline exits with status 4.
Write a baseline¶
For fresh-install or project/lock mode, save the same JSON emitted by --json:
For a locked project, write a baseline from the exact explicit inputs that CI will compare:
uvx uv-packsize --project pyproject.toml --lockfile uv.lock \
--json --write-baseline .ci/uv-packsize-baseline.json
Existing targets are left untouched unless replacement is explicit:
--write-baseline is available for fresh-install and project-lock analysis,
but not existing-prefix analysis. It cannot be combined with --baseline (and
therefore not with --comparison-json), and --overwrite-baseline requires
--write-baseline. Publication is no-clobber by default: an existing target
causes exit 3 and remains unchanged. --overwrite-baseline is the explicit
replacement opt-in.
On success, --json --write-baseline writes byte-identical JSON to stdout and
the target file, including the final newline. Text presentation options such
as --bin, --explain, --breakdown, and --contributions may change the
human report but never the saved JSON. The result is rendered, validated, and
published before the successful report or JSON is written to stdout. Render,
validation, and write failures use exit 3, send a sanitized diagnostic to
stderr, and leave stdout empty.
The atomic writer is currently POSIX-only. It creates a 0600 temporary file in an existing trusted parent directory and atomically publishes it without following symlinks or replacing an existing target unless overwrite was requested. Symlinked, unsafe-writable, or otherwise untrusted parent traversal is rejected. On Windows and other unsupported platforms, use the portable redirect fallback:
Define a budget¶
[tool.uv-packsize.budget]
max_total_logical_bytes = 52428800
max_increase_logical_bytes = 1048576
incomplete_policy = "fail"
Pass the exact policy file; there is no automatic pyproject.toml discovery:
uvx uv-packsize requests==2.32.5 --budget-config pyproject.toml
uvx uv-packsize requests==2.32.5 --baseline baseline.json \
--budget-config pyproject.toml --max-increase 524288
--max-total and --max-increase are non-negative byte limits on canonical global logical bytes. A command-line field overrides only that field from the file. An increase limit needs a compatible baseline.
A policy with a limit fails incomplete measurements by default. --incomplete-policy allow-partial suppresses only that incomplete-result violation; observed limits are still checked. A budget violation exits 5 and writes no standard output in JSON modes.
Next step¶
Add a CI check that reads the reviewed baseline without changing it.