📦 WP-153b — docs: fuse 0.12 validated against the Phase 14 rows¶
Engineering log · Phase 13 — Contributor admission, augmentation guard and keypoint parity, v0.6.0
WP-153b — the phase is unblocked, and three of its rows described upstream wrongly¶
fuse 0.12 landed every capability Phase 14 waits on: FA-1 through FA-5, FA-7 and FA-8, with FA-6 and FA-9 declined exactly as the plan agreed. The phase is unblocked. Validating it against the rows that consume it turned up more than a green light, which is the reason to validate before implementing rather than during.
Two capabilities arrived better than they were specified. FA-7 imposes no canonical form on a rotated box — no w >= h swap, no angle range — and takes canonicalize= as a caller callback instead, on the reasoning that the long-edge convention belongs with the assigner, loss and evaluation kernel that share it. That is A22's argument, reached independently upstream, and it is what keeps WP-157's design intact. FA-8 decides when to permute keypoint pairs off the sign of the composed matrix's determinant rather than off whether a flip appears in the pipeline, and applies it on every routing path including the two that never build a warp grid. Two mirrors compose back to a rotation that must not swap, and a rotation past 90 degrees looks like a flip while being none; the local unconditional swap gets both wrong, so this is a capability that arrives stronger than the code it replaces.
Three rows named upstream mechanisms that do not exist. WP-154 planned to pin align_corners=False in the frozen suite, "which fuse currently does not" use. 0.12 declined to add the flag at all and measured the equivalence instead: it samples with align_corners=True against the normalization sandwich derived for that same flag, so the convention cancels and the pixel-space map is the one an align_corners=False implementation produces for the same matrix, verified against an independently constructed reference to atol=1e-5. There is nothing left to pin, and the residual that does survive is a different quantity — the composition centre, ((W-1)/2, (H-1)/2) upstream against (W/2, H/2) here. WP-156 attributed geometric fusion to clip_policy="final"; clip_policy decides when a fused colour chain clamps and shares nothing with geometry, a confusion upstream anticipated well enough to warn against by name in its own docstring. Fusion is adjacency-driven, so a colour operation between two geometric ones splits the run and return_matrix then reports the last segment alone, silently — which makes that row's tier-C single-segment invariant more load-bearing than when it was written, not less. WP-157 planned to delete rotated_aug.py; upstream refuses to clip a rotated box on the grounds that the clipped shape is a polygon and not a rotated box, so clip_rboxes_to_canvas has nowhere to go, and check_rotated_pairing validates a local Targets invariant that was never a resampling concern. The module shrinks and does not vanish.
What a green gate would not have caught. None of the three errors is detectable by any check this repository runs. They are prose in a scope cell, describing a repository the gate never reads, and each would have surfaced as an implementing agent reaching for a parameter that is not there — the same failure mode as WP-139's golden that was never written and WP-146's register that named the wrong commit. The pattern is consistent enough to name: what the gate reads is safe, and what it does not read drifts silently.
Three decisions the measurement forced, taken by the principal. The first is the pin. fuse has no tags, local or remote, and PyPI's latest is 0.10.0.dev0, so 0.12 exists as a pushed bump commit rather than a release; the phase proceeds on a commit pin, and v0.12.0 is tagged from that same commit once the roll-out here is clean. That inverts ADR-005's step order and is deliberate — this project is fuse's first real consumer, so the tag follows the integration that proves it, which is the reciprocal battle-test contract rather than an exception to it. The second is the letterbox. The geometry matches exactly, verified in both directions on integer arithmetic, but the pixels do not: this project resizes with an antialiased bilinear interpolate, upstream runs one grid_sample with antialias off by default and a Gaussian mipmap prefilter when on, so any downscale differs and Letterbox is the inference preprocessor for six evaluation and prediction call sites. The delegation proceeds, with the eval delta measured first and re-frozen in a row of its own; keeping the local resize would have kept a second implementation of the package's whole subject, which is what the migration exists to stop. The third is the mirror axis: upstream reflects about (width - 1) / 2 and this project about width / 2, so every mirrored centre moves a pixel. Upstream's axis is adopted and the convention change recorded, on the reasoning that one convention across image and coordinate transport is worth a re-freeze and two conventions inside one pipeline are worth nothing.
What this row deliberately does not do. No DoD moves and no row splits — WP-153c does both. WP-154 needs splitting — the pin bump moves the synthetic fixtures, because upstream redesigned the triangle from obtuse-scalene to equilateral and replaced the minimum-area OBB derivation with an upright-frame one, and triangle is 25 of 90 detseg and 17 of 61 obb annotations against goldens whose tolerance is zero — so a re-freeze rides with that bump and must not ride with a swap. WP-155 and WP-157 need their DoDs rewritten to match the two decisions above. All of that is a row edit rather than a correction, and it follows rather than accompanies the correction of what was simply wrong.