Feathering had two defects: the mask used max(original, blur), and a
blurred step edge sits at ~50% on the boundary, so the mask jumped
255->127 in one pixel - the visible seam line - and the output image was
never blended at all, ending in a hard cut against the fill. The mask
ramp is now pinned to full strength exactly at the edge (double the blur
and clip, then max with the original for thin slivers), and the visible
output fades into the fill color across the same ramp, so outpaints
blend smoothly in both the image and the mask.
The rotation knob now anchors to the outermost top-right corner of
source-union-output, so it stays visually attached when padding grows
the canvas instead of floating where the source corner used to be.
Save & close is now filled with the AusBoss accent; Reset all is styled
as a destructive red button.
22 Python + 9 JS tests pass, including new asserts that the mask ramp
holds >=200 on the first kept column (was ~127) and that the image
visibly blends into the fill. Live-browser verified: knob tracks the
outermost corner under 140/90px padding, buttons computed styles match.
Review fixes verified against live ComfyUI 0.28.0:
- rotatedSize now reproduces Pillow's expand=True output exactly (transpose
fast path at axis angles, corner extents elsewhere). The previous formula
was 1px short on 34 of 78 sampled size/angle combos, so editor-predicted
output dimensions disagreed with queued results at most free angles.
Verified 0 mismatches across 6776 combinations and end-to-end on the
server (predicted 848x496 == queued image and mask at 77.7 degrees).
- decode_video_frame seeks to the nearest keyframe and decodes forward
instead of scanning from frame 0, with the sequential scan kept as the
fallback for files without usable timestamps. Scrubbing long videos no
longer decodes the entire prefix per preview request.
- Preview routes no longer serve arbitrary local paths to any HTTP client:
local-path previews outside ComfyUI's input/output/temp folders now
require AUSBOSS_TRANSFORM_LOCAL_PREVIEW=1, checked before touching the
filesystem so denied requests cannot probe path existence. Queued
workflows are unaffected.
- Editor: metadata is cached per source instead of refetched every scrub
tick, timeline seeks fetch only the frame with a 70ms trailing debounce,
AbortError from superseded requests no longer paints the error state,
and switching source mode before picking a file no longer resets the
transform.
- Tests: 13 -> 18 Python (seek vs sequential ground truth, time-mode seek,
out-of-range clamp, preview gate), 8 -> 9 JS (Pillow-verified rotated-size
fixtures including the odd/even transpose edge).