diff --git a/src/imf/export.py b/src/imf/export.py index 5c194dc..5c2fc0b 100644 --- a/src/imf/export.py +++ b/src/imf/export.py @@ -536,8 +536,11 @@ def build_int8_static_zip( vs dynamic 4.5701, not separated; +8% CPU decode). Calibration walks the model's own fp32 decode over ``calibration_texts`` across framings (prefill, single steps, 8-token windows). Metadata - precision becomes ``int8``: PRECISIONS is closed, so the static - recipe is carried by the zip name and the gate by the value. + precision becomes ``int8`` (PRECISIONS is closed; the gate is + int8's 2pp limit) and the id gains an ``-int8static`` suffix: + published filenames derive from id+precision, so without the + slug variant this artifact publishes under, it would clobber the + dynamic-int8 asset (filenames derive from id+precision). Graph-only work; gates (parity, margins) are the caller's.""" import tempfile @@ -581,8 +584,13 @@ def build_int8_static_zip( nodes_to_exclude=head_matmul_names(tmp / dec), ) + base_meta = ModelMetadata.from_yaml(meta_text) + # ids must end in major.minor (schema contract), so the variant + # rides inside the slug: {slug}-int8static-{version} + base_slug, _, base_version = base_meta.id.rpartition("-") metadata = dc_replace( - ModelMetadata.from_yaml(meta_text), precision="int8" + base_meta, precision="int8", + id=f"{base_slug}-int8static-{base_version}", ) with zipfile.ZipFile(fp32_zip) as src, zipfile.ZipFile( out_zip, "w", zipfile.ZIP_DEFLATED diff --git a/tests/test_imf_export.py b/tests/test_imf_export.py index 181561e..a834bfa 100644 --- a/tests/test_imf_export.py +++ b/tests/test_imf_export.py @@ -219,13 +219,17 @@ def static_zip( def test_static_zip_declares_int8_and_validates_strict(static_zip: Path) -> None: - """The closed PRECISIONS set has no 'int8-static': the recipe lives - in the zip name, the gate (int8's 2pp cer_delta limit) in the value.""" + """Precision stays `int8` (closed PRECISIONS set — the recipe is the + zip name, the gate int8's 2pp limit) and the id carries the + -int8static suffix: publish_model derives the canonical filename + from id+precision, so without the suffix the static asset would + clobber the shipped dynamic-int8 one.""" strict = validate_zip(static_zip, strict=True) assert strict.ok, strict.errors with zipfile.ZipFile(static_zip) as zf: meta = yaml.safe_load(zf.read("metadata.yaml")) assert meta["precision"] == "int8" + assert meta["id"] == "fixture-int8static-1.0" def test_static_zip_graphs_use_both_quant_recipes(static_zip: Path) -> None: