v2.0.0-preview.4
·
13 commits
to main
since this release
日本語のリリースノートはこちらです。
What's Changed
Windows
macOS
Linux
New Features
- Added Ctrl+Shift+P command palette for quickly searching and executing commands
- Added history view with jump-to-step for navigating the undo history
- Added 2D transform handles on the preview for directly manipulating position, scale, and rotation
- Added keyboard shortcuts for nudging timeline elements, duplicating clips (Ctrl+D / Alt+drag), and seeking to the next/previous keyframe
- Added a Go-to-timecode dialog for precise playhead positioning in the player
- Added onion-skin overlay to the preview player
- Moved player settings to a dedicated Preview Settings tool tab
- Added an "Add Adjustment Layer" menu entry to the editor
- Implemented resolution-independent rendering pipeline — effects and filters now scale correctly at any output resolution (breaking change)
- Added audio effects:
- Compressor
- Limiter (brick-wall peak limiter)
- Added Flatpak packaging for Linux distribution
- Expanded telemetry sensitive-data redaction
Improvements & Refactoring
- Refactored Timeline editing to route through a dedicated editor services layer, improving plugin extensibility (breaking change)
- Removed many deprecated and dead API surfaces, including the legacy encoder pipeline, obsolete
ISamplestructs, deadConfigurationsurface,BcTabView/BcTabItemcontrols, unused byte-LUT chain,ICanvas/INode/GraphicsException, andProjectService/EditorService/ExtensionProvidersingletons — all breaking changes - Made
IFrameProvider/ISampleProviderimplementIDisposablefor reliable resource cleanup (breaking change) - Removed MediaFoundation DXVA2/audio dead paths and no-op settings (breaking change)
- Removed the in-process FFmpeg path; collapsed the FFmpegOutOfProcess configuration axis (breaking change)
- Relocated IPC frame/sample providers to the MIT-licensed
Beutl.FFmpegIpcproject - Multiple performance improvements:
- Pooled per-sample speed buffers in SpeedNode
- Reused onion-skin snapshot bitmap during compositing
- Made FFmpeg codec property editors async and cached
- Shared FFmpegOptionsCache across editor instances to reduce IPC round-trips
- Reused the retained buffer for same-frame re-requests in IpcFrameProvider
- Upgraded ReactiveUI.Avalonia and Dock.Avalonia packages
Bug Fixes
- File compatibility: Fixed deserialization of legacy 1.x element files missing the
$typediscriminator - Editor:
- Fixed index out-of-range error when dragging gradient color stops
- Fixed output profiles being overwritten on restore failure
- Fixed corrupt config files causing crashes (JSON errors now caught gracefully)
- Fixed scene failing to open when the view state config was corrupt
- Fixed partial relocation failures not being reported during project export
- Fixed history mutation not pausing playback; scene settings are now applied correctly after pause
- Player / Preview:
- Fixed transform-handle overlay blocking the UI during playback
- Fixed onion-skin config being read off the UI thread
- Audio:
- Fixed audio resampler not being disposed during FFmpeg encoding cleanup
- Fixed
UseGlobalClockand parent-relative time not being respected in audio animations - Fixed silent audio buffer sample count alignment
- Fixed limiter deque overflow during audio release
- Fixed integer overflow in audio/media sample-index conversions
- Fixed waveform thumbnail sample math overflow
- Multiple audio buffer leak fixes across audio graph nodes
- FFmpeg / Video:
- Fixed FFmpeg install dialog not appearing when worker libraries were missing
- Fixed FFmpeg worker not respecting
BEUTL_HOMEwhen locating libraries - Fixed IpcFrameProvider returning the wrong frame on non-sequential requests
- Multiple IpcFrameProvider/IpcSampleProvider reliability fixes (leak guards, size validation, prefetch, EOF clamping)
- Fixed encode cancellation not being surfaced as
OperationCanceledException - Fixed FFmpeg seek returning -22 Invalid argument when seeking past EOF
- Engine / Rendering:
- Fixed multiple
FormattedTextresource leaks and use-after-dispose bugs - Fixed integer overflow in Animator interpolation
- Fixed video thumbnail count against degenerate frame sizes
- Fixed double-dispose in rasterize paths when an operation throws on Dispose
- Fixed SKColorFilter leak in ParticleRenderNode
- Fixed multiple
- MediaFoundation (Windows):
- Fixed resource cleanup and initialization failure handling across MFReader and MFDecoder
- Fixed frame buffer size overflow
- Fixed video-only files not opening correctly in AudioVideo mode
- Stability:
- Fixed NotificationService crash and UI thread starvation
- Fixed
TimeRange.IsEmptyreturning wrong result for zero-duration ranges - Fixed thread-safety race in the shutdown/wait path
- Fixed encoder extension matching to be case-insensitive
- Fixed keyframe animations being skipped when parent offset was unresolvable
- Rolled back project state when persistence fails
- Rolled back failed extension loads in the API layer
- Hardened
Counter<T>against reorder and AddRef TOCTOU races - Hardened IpcConnection cancellation handling in the multiplexed path
Changelog
- ci: add scheduled code review workflow posting to Projects v2 by @yuto-trd in #1766
- build(deps): bump actions/checkout from 4 to 6 by @dependabot[bot] in #1769
- feat: Expand telemetry sensitive-data redaction by @yuto-trd in #1770
- fix: deserialize 1.x Element files missing $type discriminator by @yuto-trd in #1771
- fix: dispose audio resampler in FFmpeg encoding cleanup by @yuto-trd in #1772
- feat: Add Ctrl+Shift+P command palette for searchable commands by @yuto-trd in #1776
- test: Expand unit-test coverage across Core, Engine, Utilities by @yuto-trd in #1778
- test: Expand unit-test coverage across Core, Graphics, Utilities by @yuto-trd in #1783
- fix(command-palette): address remaining PR #1776 review comments by @yuto-trd in #1779
- feat: add history view with jump-to-step by @yuto-trd in #1780
- fix: dispose SKColorFilter in ParticleRenderNode by @yuto-trd in #1788
- fix: surface FFmpeg install dialog when worker libraries are missing by @yuto-trd in #1786
- feat: add Flatpak packaging for Linux distribution by @yuto-trd in #1784
- feat: route FFmpegWorker logs to host logger by @yuto-trd in #1787
- fix: prevent NotificationService crash and UI thread starvation by @yuto-trd in #1789
- build(deps): bump actions/cache from 4 to 5 by @dependabot[bot] in #1790
- fix: exclude AVFoundation extension from Linux/Windows builds by @yuto-trd in #1795
- Bump Microsoft.Extensions.ObjectPool from 10.0.7 to 10.0.8 by @dependabot[bot] in #1805
- Bump Microsoft.Extensions.DependencyInjection and Microsoft.Extensions.Logging by @dependabot[bot] in #1803
- Bump Microsoft.Extensions.Logging.Console from 10.0.7 to 10.0.8 by @dependabot[bot] in #1804
- Bump Microsoft.Extensions.FileSystemGlobbing from 10.0.7 to 10.0.8 by @dependabot[bot] in #1802
- Bump Microsoft.Extensions.DependencyModel from 10.0.7 to 10.0.8 by @dependabot[bot] in #1801
- Bump System.CommandLine from 2.0.7 to 2.0.8 by @dependabot[bot] in #1816
- Bump NuGet.Protocol and NuGet.Resolver by @dependabot[bot] in #1814
- Bump Microsoft.Extensions.TimeProvider.Testing from 10.5.0 to 10.6.0 by @dependabot[bot] in #1811
- Bump NuGet.ProjectModel from 7.3.1 to 7.6.0 by @dependabot[bot] in #1812
- Bump System.Management from 10.0.7 to 10.0.8 by @dependabot[bot] in #1817
- fix: avoid ObjectDisposedException on PlayerViewModel dispose by @yuto-trd in #1798
- fix: prevent index out-of-range when dragging gradient stops by @yuto-trd in #1799
- fix: protect output profiles from overwrite on restore failure by @yuto-trd in #1809
- fix: catch JsonException in JsonRestore for corrupt config files (#1807) by @yuto-trd in #1810
- feat: add debug-only main window capture to MP4 by @yuto-trd in #1796
- fix: respect UseGlobalClock and parent local time in audio animations by @yuto-trd in #1818
- ci: register published release assets to beutl-reflect-release API by @yuto-trd in #1819
- fix: correct TimeRange.IsEmpty for zero duration by @yuto-trd in #1820
- fix: align silent audio buffer sample count with ceiling by @yuto-trd in #1821
- fix: prevent crash from async void in EditorHostViewModel by @yuto-trd in #1822
- fix: harden Counter against reorder and AddRef TOCTOU races by @yuto-trd in #1823
- feat: Add keyboard nudge shortcuts for timeline elements by @yuto-trd in #1824
- fix: keep scene openable when view state config is corrupt by @yuto-trd in #1825
- fix: harden cancellation handling in IpcConnection multiplexed path by @yuto-trd in #1826
- fix: surface partial relocation failures during project export by @yuto-trd in #1827
- docs: expand PR template with guidance and Test plan section by @yuto-trd in #1833
- feat: add clip duplication via Ctrl+D and Alt+drag by @yuto-trd in #1828
- feat: add 2D transform handles for direct preview manipulation by @yuto-trd in #1782
- fix: avoid overflow in integer Animator interpolation by @yuto-trd in #1830
- feat: Add goto timecode for player playhead seeking by @yuto-trd in #1829
- build(deps): bump actions/github-script from 7 to 9 by @dependabot[bot] in #1835
- chore: scaffold AI-native development workflow by @yuto-trd in #1837
- feat: Add next/previous key frame seek commands by @yuto-trd in #1831
- chore: expand AI workflow scaffolding (per-module anchors, pre-PR skill, statusline, etc.) by @yuto-trd in #1839
- feat: add Spec-Kit git extension hooks by @yuto-trd in #1840
- Bump NUnit from 4.6.0 to 4.6.1 by @dependabot[bot] in #1842
- chore: install .NET SDK in Claude Code on the web sessions by @yuto-trd in #1844
- fix: localize 3D camera mode tooltips in PlayerView by @yuto-trd in #1847
- fix: ensure all FFmpeg native resources are disposed when one Dispose throws by @yuto-trd in #1848
- fix: close TOCTOU race in FFmpegInstallNotifier throttle by @yuto-trd in #1849
- build(deps): bump dotnet/nbgv from 0.5.1 to 0.5.2 by @dependabot[bot] in #1846
- Bump coverlet.collector from 10.0.0 to 10.0.1 by @dependabot[bot] in #1836
- feat: Add onion skin overlay to the preview player by @yuto-trd in #1861
- docs: improve contributor onboarding and add SECURITY/CODEOWNERS by @yuto-trd in #1860
- Bump HarfBuzzSharp.NativeAssets.Linux from 8.3.1.3 to 8.3.1.5 by @dependabot[bot] in #1853
- Bump SkiaSharp.NativeAssets.Linux from 3.119.2 to 3.119.4 by @dependabot[bot] in #1856
- Bump Microsoft.NET.Test.Sdk from 18.5.1 to 18.6.0 by @dependabot[bot] in #1859
- Bump Avalonia and Avalonia.Diagnostics by @dependabot[bot] in #1858
- Bump HarfBuzzSharp, SkiaSharp and SkiaSharp.HarfBuzz by @dependabot[bot] in #1855
- Bump Avalonia.Themes.Fluent from 11.3.13 to 11.3.17 by @dependabot[bot] in #1866
- Bump Avalonia.Desktop from 11.3.13 to 11.3.17 by @dependabot[bot] in #1865
- refactor!: route Timeline editing through Beutl.Editor.Services by @yuto-trd in #1845
- Upgrade package versions for ReactiveUI.Avalonia and Dock.Avalonia by @yuto-trd in #1869
- fix: harden Dispatcher timer wait and resource disposal by @yuto-trd in #1870
- docs: document follow-up task capture in AGENTS.md by @yuto-trd in #1871
- perf(engine): pool per-sample speed buffer in SpeedNode.ProcessAnimatedSpeed by @yuto-trd in #1872
- docs(ai-workflow): add beutl-ai-review-task skill by @yuto-trd in #1873
- feat: migrate player settings to a Preview Settings tool tab by @yuto-trd in #1875
- refactor(engine): consolidate Delay parameter constants into DelayParameters by @yuto-trd in #1876
- refactor(engine): unify DelayNode/GainNode animation guard to Animation != null by @yuto-trd in #1877
- feat: Add audio Compressor effect by @yuto-trd in #1724
- fix(core): roll back project state when persist fails by @yuto-trd in #1878
- docs: shorten recently added code comments by @yuto-trd in #1879
- Bump Microsoft.Extensions.DependencyModel from 10.0.8 to 10.0.9 by @dependabot[bot] in #1882
- Bump Microsoft.Extensions.FileSystemGlobbing from 10.0.8 to 10.0.9 by @dependabot[bot] in #1883
- Bump Microsoft.Extensions.DependencyInjection and Microsoft.Extensions.Logging by @dependabot[bot] in #1884
- Bump Microsoft.Extensions.Logging.Console from 10.0.8 to 10.0.9 by @dependabot[bot] in #1885
- Bump OpenTelemetry and OpenTelemetry.Exporter.Console by @dependabot[bot] in #1891
- Bump Microsoft.Windows.CsWin32 from 0.3.275 to 0.3.287 by @dependabot[bot] in #1889
- Bump Microsoft.Extensions.ObjectPool from 10.0.8 to 10.0.9 by @dependabot[bot] in #1887
- Bump Microsoft.Extensions.TimeProvider.Testing from 10.6.0 to 10.7.0 by @dependabot[bot] in #1888
- fix: Phase 0 verified-bug fixes from refactoring audit by @yuto-trd in #1892
- fix(engine): dispose consumed AudioBuffer in audio graph nodes by @yuto-trd in #1893
- chore: remove tests/KeySplineEditor leftover prototype app by @yuto-trd in #1895
- chore: remove unused PackageReferences and dead PackageVersion pins by @yuto-trd in #1896
- refactor!: remove unused BcTabView/BcTabItem control cluster from Beutl.Controls by @yuto-trd in #1898
- refactor: remove dead observable/endpoint machinery and the no-op startup guard by @yuto-trd in #1899
- refactor!: remove three unused ISample structs by @yuto-trd in #1906
- refactor!: drop dead Beutl.Core/Configuration surface by @yuto-trd in #1901
- refactor!: remove dead FFmpegIpc protocol surface (QueryDefaultCodec, EncodeProgress, Handshake) by @yuto-trd in #1908
- refactor!: remove legacy encoder pipeline and obsolete Page/Layer extensions by @yuto-trd in #1905
- refactor!: collapse cross-type TypeConverter matrices to string-only converters by @yuto-trd in #1907
- refactor!: drop assorted dead Engine surface by @yuto-trd in #1904
- refactor: remove unreachable legacy (non-ring-buffer) ReadVideo path from FFmpegWorker by @yuto-trd in #1900
- refactor!: remove [Obsolete] byte-LUT chain by @yuto-trd in #1902
- fix(encoding): surface encode cancellation as OperationCanceledException by @yuto-trd in #1894
- fix: prevent IpcFrameProvider from returning wrong frame on non-sequential requests by @yuto-trd in #1912
- fix(threading): make _running volatile and cover the Shutdown/Wait race by @yuto-trd in #1911
- docs: multi-agent audit playbook + refactoring-plan Phase 1/3 corrections by @yuto-trd in #1913
- feat: add 'Add Adjustment Layer' menu (refactor ElementDescription to EngineObjectFactory) by @yuto-trd in #1880
- fix(extensibility): compare encoder extensions case-insensitively in IsSupported by @yuto-trd in #1918
- refactor: drop unreachable NotoSansJP UI weights, stale AVF dylibs, and orphan icon by @yuto-trd in #1897
- refactor: remove in-process FFmpeg path, collapse FFmpegOutOfProcess axis, relocate GPL sources by @yuto-trd in #1909
- refactor!: remove dead StringHash and BaseUriHelper helpers by @yuto-trd in #1920
- refactor!: make GainNode.Gain a required non-null property by @yuto-trd in #1921
- fix(engine): dispose child AudioBuffer consumed by SpeedProcessor.Read by @yuto-trd in #1919
- refactor: strip dead null-guards from DelayNode body by @yuto-trd in #1923
- refactor: remove stale InternalsVisibleTo for deleted Beutl.PackageTools CLI by @yuto-trd in #1922
- fix(test): gamma-encode linear HDR pixels to sRGB in Graphics3DTests debug PNGs by @yuto-trd in #1924
- refactor(core): extract fragile legacy type-name literals into LegacyTypeNames constants by @yuto-trd in #1925
- refactor: remove unused ReactiveUI.Avalonia references from WaitingDialog and PackageTools.UI by @yuto-trd in #1927
- fix(worker): respect BEUTL_HOME when locating FFmpeg libraries by @yuto-trd in #1929
- fix(worker): stop prefetch before disposing ReaderState in DecodingHandler.Dispose by @yuto-trd in #1928
- fix: skip keyframe animations with unresolvable parent offset by @yuto-trd in #1926
- refactor(editor): extract keyframe-seek logic to KeyFrameNavigationHelper and add tests by @yuto-trd in #1930
- Bump OpenTelemetry.Exporter.OpenTelemetryProtocol from 1.15.3 to 1.16.0 by @dependabot[bot] in #1915
- Bump Microsoft.Windows.CsWin32 from 0.3.287 to 0.3.296 by @dependabot[bot] in #1914
- Bump System.CommandLine from 2.0.8 to 2.0.9 by @dependabot[bot] in #1917
- feat!: resolution-independent rendering pipeline (003) by @yuto-trd in #1886
- test(editor): cover KeyFrameNavigationHelper NodeGraph member path by @yuto-trd in #1932
- fix(hooks): pin and checksum-verify dotnet-install.sh before executing by @yuto-trd in #1933
- refactor!: remove dead public graphics surface (ICanvas, INode, GraphicsException, FpsText/DrawFps) by @yuto-trd in #1903
- Bump System.Management from 10.0.8 to 10.0.9 by @dependabot[bot] in #1941
- test(rendering): cover FR-036 escape hatch through FilterEffect.Resource.Push by @yuto-trd in #1943
- refactor(ffmpeg-ipc): relocate IPC frame/sample providers to MIT Beutl.FFmpegIpc + add seek/cancel tests by @yuto-trd in #1934
- fix(editor): read onion-skin config on the UI thread in PlayerViewModel.OnSceneEdited by @yuto-trd in #1935
- fix(app): replace window-capture stop busy-spin with a single-flight async gate by @yuto-trd in #1931
- fix!: address 003 resolution-independent rendering review follow-ups by @yuto-trd in #1937
- test: deflake Counter ParallelTryAddRefRace race-window guard by @yuto-trd in #1947
- perf(engine): hoist loop-invariant rowFill out of AudioSpectrogramDrawable cell loop by @yuto-trd in #1939
- perf(ffmpeg): make the three codec property editors async + cached by @yuto-trd in #1936
- feat: Add audio Limiter (brick-wall peak limiter) effect by @yuto-trd in #1725
- perf(player): reuse one snapshot bitmap for onion-skin compositing by @yuto-trd in #1944
- Bump Microsoft.Windows.CsWin32 from 0.3.296 to 0.3.298 by @dependabot[bot] in #1945
- Bump Refit from 10.2.0 to 11.2.0 by @dependabot[bot] in #1946
- chore(deps): bump actions/checkout from 6 to 7 by @dependabot[bot] in #1948
- fix(engine): sanitize degenerate maxWorkingScale on public surface by @yuto-trd in #1942
- fix(player): stop transform-handle overlay from blocking the UI during playback by @yuto-trd in #1949
- refactor!: remove MediaFoundation DXVA2/audio dead paths and no-op settings by @yuto-trd in #1910
- refactor!: remove RenderNodeCache LastAccessedTime by @yuto-trd in #1951
- fix: guard limiter deque overflow in release by @yuto-trd in #1953
- fix(player): dispose CancellationTokenSource in BufferedPlayer.WaitRender/WaitTimer by @yuto-trd in #1950
- fix(audio): dispose output buffer on failure across all audio nodes by @yuto-trd in #1952
- fix(engine): avoid double-dispose in RasterizeAndConcat and RasterizeAt when an op throws on Dispose by @yuto-trd in #1954
- cleanup(player): remove dead DrawFrame() by @yuto-trd in #1959
- build: drop blanket dual-TFM default, hoist MSBuild blocks, unify coverlet (Phase 2) by @yuto-trd in #1955
- fix(engine): guard audio/media sample-index conversions against Int32 overflow by @yuto-trd in #1960
- test: consolidate Beutl.UnitTests scaffolding, modernize assertions, unblock Editor.Components (Phase 2) by @yuto-trd in #1956
- fix: bound dotnet session-start hook operations by @yuto-trd in #1962
- fix(engine): guard waveform thumbnail sample math overflow by @yuto-trd in #1965
- chore: add hook that flags newly added comments for review by @yuto-trd in #1971
- docs: document shader uniform migration by @yuto-trd in #1963
- refactor(editor): extract encoder settings JSON handling by @yuto-trd in #1969
- docs: fix Graphics3D NUnit test routing across guidance docs by @yuto-trd in #1968
- perf(ffmpeg): share FFmpegOptionsCache across editor instances to dedupe worker IPC by @yuto-trd in #1961
- test(nodegraph): cover NodeGraphFilterEffectRenderNode scale forwarding by @yuto-trd in #1967
- refactor: move interactive previewers/sample out of tests/, invert ArtifactProvider opt-in (Phase 2) by @yuto-trd in #1957
- test(engine): cover SpeedIntegrator long-timeline sample index by @yuto-trd in #1980
- fix(mediafoundation): compile sideload timestamp utilities by @yuto-trd in #1972
- fix(engine): preserve rasterize cleanup exceptions by @yuto-trd in #1970
- fix(editor): pause playback before history mutations by @yuto-trd in #1966
- test: make Beutl.Graphics3DTests and SourceGeneratorTest real NUnit suites (Phase 2) by @yuto-trd in #1958
- fix(engine): guard op-dispose loops against leaking remaining ops on throw by @yuto-trd in #1973
- fix(editor): apply latest scene settings after pause by @yuto-trd in #1977
- fix(engine): deterministically dispose FormattedText Skia handles by @yuto-trd in #1974
- fix(ffmpeg): avoid -22 Invalid argument on seek past EOF by @yuto-trd in #1985
- fix(engine): guard video thumbnail count against degenerate frame size by @yuto-trd in #1978
- fix(player): prevent BufferedPlayer timer dispose hang by @yuto-trd in #1981
- Bump Microsoft.NET.Test.Sdk from 18.6.0 to 18.7.0 by @dependabot[bot] in #1986
- fix(mediafoundation): guard frame buffer size overflow by @yuto-trd in #1976
- fix(mediafoundation): dispose MFReader resources on init failure by @yuto-trd in #1964
- fix(api): roll back failed extension loads by @yuto-trd in #1979
- fix(mediafoundation): dispose MFDecoder on init failure by @yuto-trd in #1987
- fix(ci): select x64 debian release asset by @yuto-trd in #1975
- test(rendering): assert LayerRenderNode emits Unbounded EffectiveScale by @yuto-trd in #1989
- test(rendering): cover non-origin DestRect and ImageBrush fill density by @yuto-trd in #1993
- fix(mediafoundation): open video-only files in AudioVideo mode by @yuto-trd in #1991
- docs: Harden branch naming and auto-register follow-ups in AI-review skill by @yuto-trd in #1996
- docs: Forbid deferring tasks instead of capturing follow-ups by @yuto-trd in #2001
- fix(engine): dispose truncated FormattedText glyph resources on shrink by @yuto-trd in #1990
- refactor(ffmpeg): extract codec-editor query/apply decisions for unit tests by @yuto-trd in #1994
- fix(engine): rebuild cached glyph geometry path on FormattedText slot reuse by @yuto-trd in #1995
- perf(ffmpeg-ipc): reuse retained buffer for same-frame re-requests in IpcFrameProvider by @yuto-trd in #1988
- fix(engine): preserve rasterize output and exceptions when RenderTarget disposal throws by @yuto-trd in #1992
- fix(engine): throw ObjectDisposedException from FormattedText measuring members after Dispose by @yuto-trd in #1999
- fix(editor): harden HistoryMutationPlaybackGuard.Dispose and SceneSettings Apply feedback by @yuto-trd in #2002
- build(deps): bump actions/cache from 5 to 6 by @dependabot[bot] in #2003
- fix(ffmpeg-ipc): harden IpcFrameProvider/IpcSampleProvider (leak guard, size validation, prefetch, EOF clamp) by @yuto-trd in #2012
- refactor!: make IFrameProvider/ISampleProvider IDisposable and guard IPC providers post-dispose by @yuto-trd in #2013
- refactor(ffmpeg): extract seek/prefetch decisions as pure predicates + tests by @yuto-trd in #2014
- test(ffmpeg-ipc): fix Windows hang in IpcConnection multiplexed tests (drain outbound request) by @yuto-trd in #2016
- docs: clarify Nuke-only publish for the FFmpeg worker; mark matrix collapse done by @yuto-trd in #2015
- fix(engine): dispose uncommitted scaled text handles in FormattedText.GetScaledTextCache by @yuto-trd in #2000
- refactor!: remove ProjectService/EditorService/ExtensionProvider singletons by @yuto-trd in #1982
- test: introduce headless E2E test suites (domain, controls, shell) by @yuto-trd in #2017
- feat: add /beutl-loop autonomous board loop (loop engineering) by @yuto-trd in #2018
Full Changelog: v2.0.0-preview.3...v2.0.0-preview.4