Skip to content

📦 WP-154 — chore(deps): fuse 0.12 becomes the pinned engine

Engineering log · Phase 14 — Augmentation upstreaming to fuse, v0.7.0

🔗 Depends on WP-153c · Needed by WP-154c, WP-154b

⬅️ WP-153c · Roadmap · WP-154c ➡️

WP-154 — every delta traced, and the frozen tree could not absorb it again

R21 advances from fedde0c1 to a5a276a, and the two breaks WP-153c predicted both arrived exactly as described. The import break is the pleasant kind: tests/fixtures/synthetic.py imported animal_shapes from fuse_augmentations.data.animals, upstream's restructure removed it, and collection fails immediately rather than at some later assertion. The replacement is tuple(AnimalShape)[:KEYPOINTS_ANIMAL_COUNT], and its equivalence is read from upstream's own source at the old pin rather than assumed from the name: animal_shapes(count) was tuple(AnimalShape)[:count] with a range check, so the selection is identical and the range check is the only thing lost — on a constant of 2 against a 12-member enum. The other three imports from that package all still resolve, checked one at a time rather than inferred from the module importing. AnimalShape declaration order still opens on duck and elephant, which is what makes the constant's own comment still true; had the restructure reordered the enum, the keypoints fixture would have silently changed categories with no golden anywhere to notice.

The trace is a two-commit partition, and it is bit-exact. Sixteen values moved across the two generator-derived goldens, and the discipline the row owes is matching each to a named upstream change rather than merely observing that they moved. Only two of the fifteen commits between the pins touch src/fuse_augmentations/data/ at all — 964fd07 (registry, SVG assets, Fill type) and abbf1f2 (upright OBB, triangle, docs split) — so the generator was installed at four commits in turn (fedde0c1, 964fd07, abbf1f2, a5a276a) and both producers run at each, the method WP-146 established. The partition came back clean. fedde0c1 reproduces all 22 stored values exactly, which is what certifies the harness and the import edit as behaviour-neutral before anything is attributed. 964fd07 moves nothing at all, despite being the commit that removed animal_shapes and rebuilt the animal family around the packaged SVG zoo — a restructure that changed how the assets are stored and not what they are. Every one of the sixteen moved values moves at abbf1f2, and nothing moves after it: the entire augmentation-engine half of the diff, eleven commits of letterbox, keep-mask, rotated-box and keypoint-swap work, is fixture-neutral, as a change to the transform stack rather than the generator should be.

The values do not merely move; they return. abbf1f2 makes PrimitiveShape.TRIANGLE equilateral again, undoing the obtuse-scalene redesign 0a0cc640 introduced and WP-132 absorbed, and it re-derives polygon_to_obb in the shape's own upright frame instead of by minimum-area calipers. The strongest evidence that this is the whole cause is that all sixteen values land bit-exactly on the figures this repository itself froze before 0a0cc640 — 93 detection annotations, 964 segmentation points, 66380.64 box-area sum, 44 oriented annotations, 176 oriented segmentation points, and the ten data_pipeline_metrics values including image_std_sum at 1.0084 and bbox_area_sum at 32923.115, every one of them recoverable from the goldens/frozen/0.2/ snapshot WP-132 removed. WP-132's log recorded obb_num_annotations going 44 to 61 and image_std_sum falling 35.5% when the triangle became obtuse-scalene; both walk back to the digit. A trace that lands on a number the project already wrote down is a different quality of evidence from one that merely sounds plausible, and it leaves zero untraced deltas — so nothing here is a regression being frozen over.

The gate went red on four files for a reason no work in this row could fix. Every hook passes, 2534 tests pass, and 36 of 40 goldens pass. The four that fail are fixture_checksums.json and data_checksums.json under goldens/frozen/0.5/ and goldens/frozen/0.6/, and they fail for a reason no work in this row can fix: their producers render images through an external package, so once that package changes they can never satisfy "current code must still satisfy every value a past release pinned". This is not a new discovery. WP-132 hit the identical wall with the identical partition — every pure-code frozen golden green, only the two generator-derived ones red — took the question to the principal rather than resolving it in the row that raised it, and the decision was that those two "were never really freezable; they were a category error in what got snapshotted, not a regression". They were removed from the frozen tree and the live copies re-frozen. The row therefore stopped at the same place, under escalation trigger 4, rather than editing release history on a precedent it had not been given. The principal authorized the same remedy: the four files are removed here — recoverable in history, and the live copies of both metrics were already re-frozen correctly in this row — leaving 36 of 36 goldens green and the frozen-golden regression still meaning what it means for every metric it can actually test.

What is worth naming is why the wall came back. WP-132's removal was correct and did not survive, because make freeze-goldens copies whatever live goldens exist into the new release directory with no notion that two of them are generator-derived. WP-140 froze them into 0.5 and WP-153 into 0.6, each re-committing the category error the principal had already ruled on, and neither could have noticed: the freeze is a copy, and a copy of a green golden is green until the generator moves. So the remedy the principal authorized once needs to be applied to two more directories, and the mechanism needs to stop reintroducing them, so WP-154c is opened to stop the mechanism reintroducing them rather than to remove them a third time — without it 0.7 freezes them again and WP-159 meets this same wall. The general shape is WP-153b's own lesson in a new place — what the gate reads is safe, and what it does not read drifts silently. Here the gate does read the frozen tree; what nothing reads is the question of which metrics belong in it.