From 8e0bd58cba36104e445cff5d9e0159764f7ba531 Mon Sep 17 00:00:00 2001 From: Paul Fidika Date: Tue, 11 Aug 2026 12:15:06 -0600 Subject: [PATCH 1/2] =?UTF-8?q?ie#656:=20cut=200.109.0=20=E2=80=94=200.108?= =?UTF-8?q?.0=20published=20WITHOUT=20pgw#1133,=20so=20master's=20number?= =?UTF-8?q?=20is=20spent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `refs/tags/v0.108.0` points at `821090c3` (ie#655), cut BEFORE pgw#1133 merged as `5e2a74ae`. Its publish failed the tree-provenance gate, a `ci.yml` dispatch on `821090c3` went green, the re-run succeeded, and PyPI's `gen_worker-0.108.0-py3-none-any.whl` (uploaded 18:09:42Z) has NO `gen_worker/convert/dtype_pins.py` and a `clone.py` that never mentions the pins. So pgw#1133's close-out line "the eventual 0.108.0 artifact contains both changes" is not what shipped, and master could not be tagged again at 0.108.0: one artifact, one number, and that number is taken. 0.109.0 carries pgw#1133 alone. The 0.107.0/0.108.0 pair was tagged without a changelog cut, so this also assembles the four fragments that DID ship in 0.108.0 into their own section, dated and attributed to the tree that carries them — the CHANGELOG now says which artifact holds what instead of implying one release contains work that predates it. --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ changelog.d/ie655.md | 5 ----- changelog.d/pgw1123.md | 12 ------------ changelog.d/pgw1127.md | 1 - changelog.d/pgw1128.md | 1 - changelog.d/pgw1133.md | 1 - pyproject.toml | 2 +- 7 files changed, 30 insertions(+), 21 deletions(-) delete mode 100644 changelog.d/ie655.md delete mode 100644 changelog.d/pgw1123.md delete mode 100644 changelog.d/pgw1127.md delete mode 100644 changelog.d/pgw1128.md delete mode 100644 changelog.d/pgw1133.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 659774a4..da3540b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,35 @@ Unreleased entries live in [`changelog.d/`](changelog.d/), one file per issue — lanes do not edit this file. A cut assembles them (`scripts/assemble_changelog.py`). +## 0.109.0 (2026-08-11) — **a dtype cast respects per-component precision pins** — the number 0.108.0 was already spent on a tree that does not carry this + +- **pgw#1133: a dtype cast is tree-wide, a precision pin is per-component — and only the LOAD half knew it.** `families.facts` states `AutoencoderKLWan -> fp32` (*"the Wan VAE is numerically fragile: bf16 latents degrade decoded frames visibly"*) and `models/loading.py` honours it on every materialize. `convert/clone.py`'s cast did not consult it at all — `quantize_components` is reached only when `is_quant`, so a plain `dtype: "bf16"` clone applied to **every** weight group in the tree. Live, on the master stack: ie#649 leg A published `vae/diffusion_pytorch_model.safetensors` at **253,806,966 B** against the **507,591,892 B** fp32 upstream, valid and classified and complete, and a serving pod would have upcast the truncation back into fp32 with nothing anywhere saying so. New `convert/dtype_pins.py` is the producer half of that one fact: it reads the TREE'S OWN `model_index.json` classes and asks `families.facts` — never a second table. A tree-wide NARROWING cast **skips** the pinned component (passthrough at source precision) and reports it in `attr_dtype_pinned_components`, because "publish a bf16 flavor of this model" has no per-component spelling that could satisfy both the request and the pin, and refusing would leave the operator with ie#649's third pod leg as the only path to the same tree; a cast that WIDENS is a no-op and is not touched. An **explicit** instruction naming a pinned component as a quant target is refused instead, typed and by name (`ComponentDtypePinError`), because that one has a repair. Two publish gates close it behind the cast: `run_clone` and `publish_flavors` both refuse a tree carrying a pinned component narrower than its pin (`ComponentDtypePinViolation`) — the clone arm compares against the SOURCE, so an upstream that ships the component narrow is still mirrorable and only OUR truncation fails. Both publish `metadata.component_dtypes`, so per-component precision is a queryable checkpoint fact instead of a byte count somebody has to notice. **The catalog audit that followed found the defect had already shipped**: `tensorhub/wan22-ti2v-5b`'s `prod`+`latest` head carries a **1,409,400,600 B bf16** `AutoencoderKLWan` against upstream's **2,818,777,808 B** fp32 (196 tensors, all BF16 by header) — a whole-tree fp32→bf16 cast whose transformer is likewise exactly half of upstream. Reported for its owner to re-clone rather than silently re-cast; the two ie#649 intermediates carrying the same downcast are untagged and superseded. + +## 0.108.0 (2026-08-11) — **the execution axis is REPORTED, not derived** — plus the rig/probe pin folds. Tagged `v0.108.0` at `821090c3` and published to PyPI 2026-08-11 18:09Z; it does NOT carry pgw#1133 (see 0.109.0) + +- **ie#655: the execution axis of `metrics.lane` is REPORTED, not derived — and it stops erring in the flattering direction.** pgw#1104 made the WEIGHTS half of the lane id follow what `setup()` actually did; the `+compiled`/`+eager` half stayed a second, independent derivation, and it over-claimed. Measured on wan-2.2's first sm90 pod (`sbzo69ff5t0l44`, H100 80GB): the worker declined its own mint (`self_mint_skipped reason=insufficient_vram headroom=37.68GiB needed~=72.54GiB`), said `eager` three times in its own boot rows, served eager — and reported `fp8-w8a8-dynamic+compiled` on both billed requests. The cause is the lane table's PLANNING coercion (`_with_supported_execution`, now `_planned_execution`): `fp8-w8a8-dynamic` is marked compiled-only because eager w8a8 is UNMEASURED, not because it cannot happen, and running that preference over an OBSERVED eager posture rewrote the fact on the key that carries pricing, quant verdicts, serving floors and cell identity. + + The lane's execution axis is now `ServedIdentity.serving_mode` — the same object, at the same instant, that `metrics.serving_mode` is stamped from — so the two cannot disagree by construction rather than by check. `_served_execution_lane` splits into `_served_execution_body` (bindings ∪ applied reports ∪ a declared `handles=` instruction, most-quantized wins) and one composition at the terminal, where a per-request eager fallback that happened DURING the handler is finally knowable; the dispatch-time stamp survives only as `ctx.lane`'s forecast. A hub lane instruction now owns the BODY and never the execution axis: what the hub asked for is not evidence of what ran. New `observed_execution_lane()` reports the posture it is handed and coerces nothing — the reportable set is deliberately WIDER than `known_execution_lanes()`, which enumerates the lanes the platform may CHOOSE. + + Revert-turns-red: `tests/test_execution_axis_ie655.py` drives a serve-time-quantized endpoint through the real gRPC terminal path and asserts `+eager` on a JobMetrics whose `serving_mode` is `eager`; it reads `+compiled` on the pre-fix tree. pgw#1104's own `test_a_serve_time_recipe_moves_the_reported_lane` was asserting the over-claim (`fp8-w8a8-dynamic+compiled` on a rig that compiles nothing) and now asserts the honest string. + +- **pgw#1123 (follow-up): the fleet's probe image is repinned to the wheel that + fixed it.** `examples/micro-diffusion` was pinned at `gen-worker==0.97.0` — a + wheel whose `models/structure_only` imports `accelerate`, which this family + deliberately does not ship. The SDK fix landed in `858a7bcb`, but the BUILT + image kept deriving no boot key, issuing no + `POST /v1/worker/cells/resolve` and self-minting forever, so the AOT + reuse-circle proof would have measured the same silence a third time at real + pod cost. Pin moved to `0.106.0` and the lock re-resolved against the + published wheel (`sha256:bd1e4558…`). No `accelerate` line was added to the + image: `pipeline.py` already uses the SDK's `models.meta_init` seam, and + declaring the package here would have fixed one image and left the class in + place for every other family. + +- **pgw#1127: cozy-local can reach the AOT cell sink, and the boot asks THIS MACHINE before it asks the hub.** DESIGN-RULINGS §4.28 says untrusted hardware mints for ITSELF — *"local cell, local repo-CAS, reused across its own boots — never uploaded, never requested"* — and pgw#1096 built exactly that store, ck1-keyed and consulted local-first in `fleet_cells._arming_policy`. Two defects kept it out of reach. **(1)** `cli/run.py` still armed through `local_cells.enable_compiled`, the JIT path, so `_arming_policy` was never entered from `cozy serve` and cozy-local got compile-once-run-forever on JIT only — on the recipe pgw#1086 wave 1 deletes. It now arms through a new `local_serve.py`: `fleet_cells.enable_compiled(publisher=None)`, and on a miss it DRIVES the ordinary delegated mint, whose cell `adopt_delegated_mint` stores locally before any publish could be attempted. The obligation ends at a new `fleet_cells.keep_self_mint_local` rather than at `publish_self_mint`, whose sinkless branch is a fleet WIRING ALARM that would make the one machine §4.28 is about indistinguishable from a broken pod. `local_cells` now has zero readers anywhere in the tree, which is what unblocks that deletion. **(2)** `_boot_adopt` returned `no_hub` BEFORE deriving the key, reasoning that *"deriving a key nobody will answer is pure boot latency"* — false on exactly these machines, because the derived ck1 key IS the local store's own address. The sequence is now derive → local `lookup(key)` → hub `resolve(key)`; `no_hub` is deleted and split into `no_cell_source` (nobody at all, so the derive really is skipped) and `local_miss_no_hub`, joined by `local_hit` and `local_graph_witness_mismatch`, all four in the pgw#1116 typed vocabulary. A local hit is handed to the arming brain as an ADDRESS (`boot_local_key`) and not as an `_ArmOrder` — a self-minted cell has no hub receipt, so the ordered path would refuse it — making the boot-derived key a SECOND lookup route into the same CAS the arm-token memo addresses, with `_arm_exported_cell` the one gate at the end of both. That is what makes an arm-token scheme bump cost a TRACE instead of a MINT: `sweep_superseded_memos` deletes the shortcut and leaves the cells under their own keys, and the boot now re-finds them and rewrites the memo from the proven arm. Both properties are fenced structurally rather than by convention — an AST fence refusing any `CellPublisher`, publish identifier or transport import on the local serve entry, and a `socket.connect` fence proving a boot with a populated store and an unreachable hub makes ZERO network attempts. + +- **pgw#1128: a virtual tensor is not resident VRAM, and its data pointer is never read.** `memory._sum_tensor_bytes` walked a pgw#1080 structure-only component's FAKE parameters as if they held storage, and got three answers wrong at once: it booked their declared bytes as CUDA-RESIDENT, so `select_auto_mode`'s pgw#1025 net requirement fell to zero and a 40 GB virtual tree read as fitting a 24 GB card on a fully resident rung; it deduped the whole tree into its first tensor, because every FakeTensor answers `data_ptr()` with `0`; and it made that call at all, which torch has deprecated (*"will error"*) behind callers whose bare `except` would have turned every placement estimate into a silent `0.0`. A fake tensor now contributes zero RESIDENT bytes, is keyed by object identity rather than by a storage it does not have, and still counts toward the REQUIREMENT — the shape and dtype it declares are what a real load, or the mint child's `materialize_random`, goes on to allocate. Nothing was mis-booked in production today only because no structure-only pipeline reaches the residency registry; the mint child, which composes structure-only and does place, was already choosing its rung off the wrong number. + ## 0.106.0 (2026-08-11) — **a split serving pod knows who it is, a boot-trace child stops fighting for the card, and the boot key stops depending on a package nothing declared** - Export declarations register on INTENT, and `_Thunk` is gone (pgw#1107). With diff --git a/changelog.d/ie655.md b/changelog.d/ie655.md deleted file mode 100644 index c8af14fd..00000000 --- a/changelog.d/ie655.md +++ /dev/null @@ -1,5 +0,0 @@ -- **ie#655: the execution axis of `metrics.lane` is REPORTED, not derived — and it stops erring in the flattering direction.** pgw#1104 made the WEIGHTS half of the lane id follow what `setup()` actually did; the `+compiled`/`+eager` half stayed a second, independent derivation, and it over-claimed. Measured on wan-2.2's first sm90 pod (`sbzo69ff5t0l44`, H100 80GB): the worker declined its own mint (`self_mint_skipped reason=insufficient_vram headroom=37.68GiB needed~=72.54GiB`), said `eager` three times in its own boot rows, served eager — and reported `fp8-w8a8-dynamic+compiled` on both billed requests. The cause is the lane table's PLANNING coercion (`_with_supported_execution`, now `_planned_execution`): `fp8-w8a8-dynamic` is marked compiled-only because eager w8a8 is UNMEASURED, not because it cannot happen, and running that preference over an OBSERVED eager posture rewrote the fact on the key that carries pricing, quant verdicts, serving floors and cell identity. - - The lane's execution axis is now `ServedIdentity.serving_mode` — the same object, at the same instant, that `metrics.serving_mode` is stamped from — so the two cannot disagree by construction rather than by check. `_served_execution_lane` splits into `_served_execution_body` (bindings ∪ applied reports ∪ a declared `handles=` instruction, most-quantized wins) and one composition at the terminal, where a per-request eager fallback that happened DURING the handler is finally knowable; the dispatch-time stamp survives only as `ctx.lane`'s forecast. A hub lane instruction now owns the BODY and never the execution axis: what the hub asked for is not evidence of what ran. New `observed_execution_lane()` reports the posture it is handed and coerces nothing — the reportable set is deliberately WIDER than `known_execution_lanes()`, which enumerates the lanes the platform may CHOOSE. - - Revert-turns-red: `tests/test_execution_axis_ie655.py` drives a serve-time-quantized endpoint through the real gRPC terminal path and asserts `+eager` on a JobMetrics whose `serving_mode` is `eager`; it reads `+compiled` on the pre-fix tree. pgw#1104's own `test_a_serve_time_recipe_moves_the_reported_lane` was asserting the over-claim (`fp8-w8a8-dynamic+compiled` on a rig that compiles nothing) and now asserts the honest string. diff --git a/changelog.d/pgw1123.md b/changelog.d/pgw1123.md deleted file mode 100644 index 86a48a40..00000000 --- a/changelog.d/pgw1123.md +++ /dev/null @@ -1,12 +0,0 @@ -- **pgw#1123 (follow-up): the fleet's probe image is repinned to the wheel that - fixed it.** `examples/micro-diffusion` was pinned at `gen-worker==0.97.0` — a - wheel whose `models/structure_only` imports `accelerate`, which this family - deliberately does not ship. The SDK fix landed in `858a7bcb`, but the BUILT - image kept deriving no boot key, issuing no - `POST /v1/worker/cells/resolve` and self-minting forever, so the AOT - reuse-circle proof would have measured the same silence a third time at real - pod cost. Pin moved to `0.106.0` and the lock re-resolved against the - published wheel (`sha256:bd1e4558…`). No `accelerate` line was added to the - image: `pipeline.py` already uses the SDK's `models.meta_init` seam, and - declaring the package here would have fixed one image and left the class in - place for every other family. diff --git a/changelog.d/pgw1127.md b/changelog.d/pgw1127.md deleted file mode 100644 index c4650df7..00000000 --- a/changelog.d/pgw1127.md +++ /dev/null @@ -1 +0,0 @@ -- **pgw#1127: cozy-local can reach the AOT cell sink, and the boot asks THIS MACHINE before it asks the hub.** DESIGN-RULINGS §4.28 says untrusted hardware mints for ITSELF — *"local cell, local repo-CAS, reused across its own boots — never uploaded, never requested"* — and pgw#1096 built exactly that store, ck1-keyed and consulted local-first in `fleet_cells._arming_policy`. Two defects kept it out of reach. **(1)** `cli/run.py` still armed through `local_cells.enable_compiled`, the JIT path, so `_arming_policy` was never entered from `cozy serve` and cozy-local got compile-once-run-forever on JIT only — on the recipe pgw#1086 wave 1 deletes. It now arms through a new `local_serve.py`: `fleet_cells.enable_compiled(publisher=None)`, and on a miss it DRIVES the ordinary delegated mint, whose cell `adopt_delegated_mint` stores locally before any publish could be attempted. The obligation ends at a new `fleet_cells.keep_self_mint_local` rather than at `publish_self_mint`, whose sinkless branch is a fleet WIRING ALARM that would make the one machine §4.28 is about indistinguishable from a broken pod. `local_cells` now has zero readers anywhere in the tree, which is what unblocks that deletion. **(2)** `_boot_adopt` returned `no_hub` BEFORE deriving the key, reasoning that *"deriving a key nobody will answer is pure boot latency"* — false on exactly these machines, because the derived ck1 key IS the local store's own address. The sequence is now derive → local `lookup(key)` → hub `resolve(key)`; `no_hub` is deleted and split into `no_cell_source` (nobody at all, so the derive really is skipped) and `local_miss_no_hub`, joined by `local_hit` and `local_graph_witness_mismatch`, all four in the pgw#1116 typed vocabulary. A local hit is handed to the arming brain as an ADDRESS (`boot_local_key`) and not as an `_ArmOrder` — a self-minted cell has no hub receipt, so the ordered path would refuse it — making the boot-derived key a SECOND lookup route into the same CAS the arm-token memo addresses, with `_arm_exported_cell` the one gate at the end of both. That is what makes an arm-token scheme bump cost a TRACE instead of a MINT: `sweep_superseded_memos` deletes the shortcut and leaves the cells under their own keys, and the boot now re-finds them and rewrites the memo from the proven arm. Both properties are fenced structurally rather than by convention — an AST fence refusing any `CellPublisher`, publish identifier or transport import on the local serve entry, and a `socket.connect` fence proving a boot with a populated store and an unreachable hub makes ZERO network attempts. diff --git a/changelog.d/pgw1128.md b/changelog.d/pgw1128.md deleted file mode 100644 index 3545546b..00000000 --- a/changelog.d/pgw1128.md +++ /dev/null @@ -1 +0,0 @@ -- **pgw#1128: a virtual tensor is not resident VRAM, and its data pointer is never read.** `memory._sum_tensor_bytes` walked a pgw#1080 structure-only component's FAKE parameters as if they held storage, and got three answers wrong at once: it booked their declared bytes as CUDA-RESIDENT, so `select_auto_mode`'s pgw#1025 net requirement fell to zero and a 40 GB virtual tree read as fitting a 24 GB card on a fully resident rung; it deduped the whole tree into its first tensor, because every FakeTensor answers `data_ptr()` with `0`; and it made that call at all, which torch has deprecated (*"will error"*) behind callers whose bare `except` would have turned every placement estimate into a silent `0.0`. A fake tensor now contributes zero RESIDENT bytes, is keyed by object identity rather than by a storage it does not have, and still counts toward the REQUIREMENT — the shape and dtype it declares are what a real load, or the mint child's `materialize_random`, goes on to allocate. Nothing was mis-booked in production today only because no structure-only pipeline reaches the residency registry; the mint child, which composes structure-only and does place, was already choosing its rung off the wrong number. diff --git a/changelog.d/pgw1133.md b/changelog.d/pgw1133.md deleted file mode 100644 index ab778833..00000000 --- a/changelog.d/pgw1133.md +++ /dev/null @@ -1 +0,0 @@ -- **pgw#1133: a dtype cast is tree-wide, a precision pin is per-component — and only the LOAD half knew it.** `families.facts` states `AutoencoderKLWan -> fp32` (*"the Wan VAE is numerically fragile: bf16 latents degrade decoded frames visibly"*) and `models/loading.py` honours it on every materialize. `convert/clone.py`'s cast did not consult it at all — `quantize_components` is reached only when `is_quant`, so a plain `dtype: "bf16"` clone applied to **every** weight group in the tree. Live, on the master stack: ie#649 leg A published `vae/diffusion_pytorch_model.safetensors` at **253,806,966 B** against the **507,591,892 B** fp32 upstream, valid and classified and complete, and a serving pod would have upcast the truncation back into fp32 with nothing anywhere saying so. New `convert/dtype_pins.py` is the producer half of that one fact: it reads the TREE'S OWN `model_index.json` classes and asks `families.facts` — never a second table. A tree-wide NARROWING cast **skips** the pinned component (passthrough at source precision) and reports it in `attr_dtype_pinned_components`, because "publish a bf16 flavor of this model" has no per-component spelling that could satisfy both the request and the pin, and refusing would leave the operator with ie#649's third pod leg as the only path to the same tree; a cast that WIDENS is a no-op and is not touched. An **explicit** instruction naming a pinned component as a quant target is refused instead, typed and by name (`ComponentDtypePinError`), because that one has a repair. Two publish gates close it behind the cast: `run_clone` and `publish_flavors` both refuse a tree carrying a pinned component narrower than its pin (`ComponentDtypePinViolation`) — the clone arm compares against the SOURCE, so an upstream that ships the component narrow is still mirrorable and only OUR truncation fails. Both publish `metadata.component_dtypes`, so per-component precision is a queryable checkpoint fact instead of a byte count somebody has to notice. **The catalog audit that followed found the defect had already shipped**: `tensorhub/wan22-ti2v-5b`'s `prod`+`latest` head carries a **1,409,400,600 B bf16** `AutoencoderKLWan` against upstream's **2,818,777,808 B** fp32 (196 tensors, all BF16 by header) — a whole-tree fp32→bf16 cast whose transformer is likewise exactly half of upstream. Reported for its owner to re-clone rather than silently re-cast; the two ie#649 intermediates carrying the same downcast are untagged and superseded. diff --git a/pyproject.toml b/pyproject.toml index 745a3ae1..679b97f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "gen-worker" -version = "0.108.0" +version = "0.109.0" description = "A library used to build custom functions in Cozy Creator's serverless function platform." readme = "README.md" license = "MIT" From cc646757dd6b615484fcf8bf760a285bb1bebfb1 Mon Sep 17 00:00:00 2001 From: Paul Fidika Date: Tue, 11 Aug 2026 12:15:47 -0600 Subject: [PATCH 2/2] ie#656: relock uv.lock for 0.109.0 (the lock records the project's own version) --- uv.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uv.lock b/uv.lock index ddaa9d02..afceeebc 100644 --- a/uv.lock +++ b/uv.lock @@ -592,7 +592,7 @@ wheels = [ [[package]] name = "gen-worker" -version = "0.108.0" +version = "0.109.0" source = { editable = "." } dependencies = [ { name = "blake3" },