Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
419 commits
Select commit Hold shift + click to select a range
7279b62
fix(jlink): drop jdk.jlink from includeAllModules runtime images (#673)
kdroidFilter Sep 17, 2026
dae095c
Merge pull request #682 from NucleusFramework/fix/673-drop-jdk-jlink
kdroidFilter Sep 17, 2026
a4bcb69
fix(fs-watcher): shared native watcher, macOS renames (#570, #571)
kdroidFilter Sep 17, 2026
c3c3699
fix(fs-watcher): hand the canonical root to inotify as well
kdroidFilter Sep 17, 2026
948f22e
Merge pull request #683 from NucleusFramework/fix/570-571-fswatcher-s…
kdroidFilter Sep 17, 2026
e8c2034
feat(window): maximizable flag, off by default for satellite windows
kdroidFilter Sep 17, 2026
0d56452
test(application): thread maximizable through the recording window hosts
kdroidFilter Sep 17, 2026
ac3b0d8
Merge pull request #684 from NucleusFramework/feat/window-maximizable
kdroidFilter Sep 18, 2026
23dd930
Merge origin/main into nucleus-2.6
kdroidFilter Sep 18, 2026
14f8fd0
feat(core-runtime): configurable native library cache directory (#303)
kdroidFilter Sep 18, 2026
617dc63
Merge pull request #686 from NucleusFramework/feat/native-cache-dir
kdroidFilter Sep 18, 2026
5e0dd35
fix: marshal native callbacks to the host UI thread, not the AWT EDT
kdroidFilter Sep 18, 2026
6c77844
feat(pkg): Developer ID PKG with install scripts (#249)
kdroidFilter Sep 18, 2026
0972034
build: derive apiValidation exclusions from the project tree
kdroidFilter Sep 18, 2026
e9fd7d5
Merge pull request #688 from NucleusFramework/feat/249-developer-id-pkg
kdroidFilter Sep 18, 2026
e9c384c
style: fix the two outstanding ktlint violations
kdroidFilter Sep 18, 2026
7281be0
fix(notification-common): marshal macOS notification callbacks to the…
kdroidFilter Sep 18, 2026
a34eb67
fix(tao/linux): paint at the drawable's real size, not a predicted on…
kdroidFilter Sep 18, 2026
20b7a0f
Merge pull request #687 from NucleusFramework/fix/ui-thread-marshal
kdroidFilter Sep 18, 2026
fddc7ee
fix(tao/linux): pin when the pending resize lands in the buffer (#444)
kdroidFilter Sep 18, 2026
f8c86b7
test(444): dump the frames whose drawable was reallocated mid-frame
kdroidFilter Sep 18, 2026
b5cde6d
review(444): correct two comments that generalised a local observation
kdroidFilter Sep 18, 2026
f23476f
Merge pull request #689 from NucleusFramework/fix/444-wayland-drawabl…
kdroidFilter Sep 18, 2026
b21ceaf
fix(tao/macos): keep the input-source indicator off a caret that is gone
kdroidFilter Sep 19, 2026
38bd8b7
test(tao/macos): lock the caret rect's lifetime in the headful suite
kdroidFilter Sep 19, 2026
7a248b9
Merge pull request #690 from NucleusFramework/fix/macos-input-source-…
kdroidFilter Sep 19, 2026
2c7ea41
fix(tao/macos): keep hover alive through AppKit's phantom mouseExited
kdroidFilter Sep 19, 2026
b9e8b1c
test(tao): fix the three #569 popup cases red on the macOS runner
kdroidFilter Sep 19, 2026
5f9dd26
test(tao): land a robot press on its target, not where the pointer was
kdroidFilter Sep 19, 2026
3654fd0
fix(tao/linux): commit the resize frame with GTK's geometry, not afte…
kdroidFilter Sep 19, 2026
a1a19f9
fix(tao/macos): give the parent the release of the press a popup forw…
kdroidFilter Sep 19, 2026
e315620
test(tao): film the dialog animation, not the compositor's timing
kdroidFilter Sep 19, 2026
594a0bb
Merge pull request #691 from NucleusFramework/fix/444-wayland-resize-…
kdroidFilter Sep 19, 2026
2685723
fix(tao/linux): keep the toplevel's frame callbacks flowing when maxi…
kdroidFilter Sep 19, 2026
0136488
ci: publish unverified dev builds from a `-dev-` tag
kdroidFilter Sep 20, 2026
c9e258c
Merge branch 'main' into nucleus-2.6
kdroidFilter Sep 22, 2026
9c8fff6
fix(tao/macos): step AppKit's own frame animations too (#576)
kdroidFilter Sep 22, 2026
dd6fc45
Merge pull request #693 from NucleusFramework/fix/tao-macos-edge-zoom…
kdroidFilter Sep 22, 2026
184bfe0
feat(plugin): strip JRE fonts from the runtime image by default
kdroidFilter Sep 22, 2026
a84a0fc
Merge pull request #694 from NucleusFramework/feat/strip-jre-fonts
kdroidFilter Sep 22, 2026
174d45b
feat(tao): customizable tab previews, pane extent limits, RTL drop fixes
kdroidFilter Sep 22, 2026
43c081f
Merge pull request #695 from NucleusFramework/feat/tab-preview-custom…
kdroidFilter Sep 22, 2026
d2f89d3
chore(plugin): default GraalVM innovation channel to 25i4 (GraalVM 25…
kdroidFilter Sep 22, 2026
7d2b849
Merge pull request #698 from NucleusFramework/chore/graalvm-25i4
kdroidFilter Sep 22, 2026
ff38b93
fix(tao): add cancellable system quit handling
anthonyhfm Sep 22, 2026
a4801d8
fix(tao): match Electron's macOS quit semantics
kdroidFilter Sep 23, 2026
e12ad9e
Merge pull request #696 from anthonyhfm/main
kdroidFilter Sep 23, 2026
06ddbd7
test(tao): align DockLandingRectTest with the #695 split-side preview
kdroidFilter Sep 23, 2026
144bffc
Merge pull request #700 from NucleusFramework/fix/dock-landing-rect-test
kdroidFilter Sep 23, 2026
395465c
Merge branch 'main' into nucleus-2.6
kdroidFilter Sep 23, 2026
0c7f064
ci: run every Linux job on ubuntu-22.04
kdroidFilter Sep 23, 2026
7871455
Merge pull request #702 from NucleusFramework/ci/ubuntu-22.04-everywh…
kdroidFilter Sep 23, 2026
32081b0
Merge branch 'main' into nucleus-2.6
kdroidFilter Sep 23, 2026
dffd786
test(application): skip the live theme e2e without an XDG portal
kdroidFilter Sep 23, 2026
d61f892
fix(tao/linux): resolve the toplevel draw callback on its interface (…
kdroidFilter Sep 23, 2026
0ea29b0
Merge pull request #704 from NucleusFramework/fix/tao-linux-toplevel-…
kdroidFilter Sep 23, 2026
7aa9ed7
Merge pull request #703 from NucleusFramework/fix/theme-e2e-requires-…
kdroidFilter Sep 23, 2026
5d3936e
perf(tao): stop re-running layout callbacks on unrelated placements (…
kdroidFilter Sep 23, 2026
c097413
feat(tao): consume ANGLE as a Maven dependency, built for D3D11 only
kdroidFilter Sep 23, 2026
dae3bf3
ci: track dependencies with Dependabot
kdroidFilter Sep 23, 2026
fae2b60
Merge pull request #707 from NucleusFramework/feat/angle-prebuilt-nat…
kdroidFilter Sep 23, 2026
71b304d
Merge pull request #705 from NucleusFramework/perf/tao-on-layout-rect…
kdroidFilter Sep 23, 2026
5c27575
build: stop native tasks from rebuilding every run
kdroidFilter Sep 23, 2026
76f8f78
build: update to Gradle 9.8.0-rc-3
kdroidFilter Sep 23, 2026
1261873
build: let the build use up to 80% of the machine's RAM
kdroidFilter Sep 23, 2026
b886db0
fix(graalvm): allow --gc=G1 on Windows and macOS from GraalVM 25.4
kdroidFilter Sep 23, 2026
dfe9fbf
Merge pull request #708 from NucleusFramework/fix/graalvm-g1-windows-…
kdroidFilter Sep 23, 2026
f354e4e
feat(plugin): provision Node.js instead of requiring it, bump electro…
kdroidFilter Sep 23, 2026
9c667dd
ci(universal-macos): run the pinned electron-builder on a provisioned…
kdroidFilter Sep 23, 2026
139f265
feat(tao): report a stalled event loop instead of freezing silently (…
kdroidFilter Sep 24, 2026
d2166c8
style: ktlint-format three build scripts that fail preMerge on nucleu…
kdroidFilter Sep 24, 2026
c437f0c
perf(tao): park the watchdog while no window is registered
kdroidFilter Sep 24, 2026
7b2cd33
Merge pull request #709 from NucleusFramework/feat/node-auto-download
kdroidFilter Sep 24, 2026
662f4dc
fix(plugin): serialize toolchain provisioning across parallel tasks
kdroidFilter Sep 24, 2026
1d7b4df
feat(tao): let an app declare an expected stall to the watchdog
kdroidFilter Sep 24, 2026
da7fe54
perf(tao): keep the watchdog's debugger check off the startup path
kdroidFilter Sep 24, 2026
b3b926d
fix(tao): harden the watchdog against the review's findings
kdroidFilter Sep 24, 2026
70b9469
fix(tao): keep the watchdog alive under blocking listeners, GC and re…
kdroidFilter Sep 24, 2026
b363579
fix(tao): make the watchdog survive its own reporting path
kdroidFilter Sep 24, 2026
f9d9531
fix(tao): make the watchdog's restart and teardown race-free
kdroidFilter Sep 24, 2026
56e215f
Merge pull request #711 from NucleusFramework/fix/toolchain-install-lock
kdroidFilter Sep 24, 2026
2fc98e3
test(tao): concurrency monkey for the watchdog, and the bug it found
kdroidFilter Sep 24, 2026
e88db99
fix(tao): two watchdog leaks the concurrency monkey found
kdroidFilter Sep 24, 2026
b828d66
test(tao): watchdog monkey against a real window
kdroidFilter Sep 24, 2026
2713589
test(tao): watchdog monkey against an animating app, and a flake it e…
kdroidFilter Sep 24, 2026
8c145e8
feat(plugin): ship Nucleus JNI libraries next to the app instead of i…
kdroidFilter Sep 24, 2026
6cf29e4
test(tao): diagnose a frame stall, and stop demanding instant thread …
kdroidFilter Sep 24, 2026
59142ae
fix(tao): re-issue a redraw the OS never answered, instead of latchin…
kdroidFilter Sep 24, 2026
75b66eb
fix(plugin): only move the Nucleus modules' own JNI libraries out of …
kdroidFilter Sep 24, 2026
b6f1211
test(tao): tell a late recovery apart from a lost one
kdroidFilter Sep 24, 2026
6f3120a
fix(tao): never park the watchdog on an open episode
kdroidFilter Sep 24, 2026
96861c6
fix(tao): guard every log on the watchdog's own paths, not just the r…
kdroidFilter Sep 24, 2026
d3b21af
style(tao): wrap the smoke task's forwarded-property list the way ktl…
kdroidFilter Sep 24, 2026
63b7b51
style(tao): forward each smoke property by name, no multiline expression
kdroidFilter Sep 24, 2026
d61e025
Merge pull request #710 from NucleusFramework/feat/event-loop-watchdo…
kdroidFilter Sep 24, 2026
14ff2ab
fix(tao): dispatch recognized trackpad pinch as Compose Scale events …
kdroidFilter Sep 7, 2026
fa4ea46
test(tao): register the #660 scale tests and cover Ctrl+wheel headful
kdroidFilter Sep 23, 2026
cfe2020
fix(tao/macos): keep pinch and rotate from overlapping; e2e the AppKi…
kdroidFilter Sep 24, 2026
67ff413
fix(tao/macos): synthetic rotation contacts never coexist with a mous…
kdroidFilter Sep 24, 2026
45c6ecd
fix(window/macos): the trackpad rotation's contacts never start a win…
kdroidFilter Sep 24, 2026
0fee010
test(tao): the night gesture monkey tells a person at the machine fro…
kdroidFilter Sep 24, 2026
53637d8
test(tao): the title-bar rotation case measures the rotation only (#660)
kdroidFilter Sep 24, 2026
1efc875
fix(tao/linux): GDK pinch and rotation never overlap; e2e the GDK ges…
kdroidFilter Sep 24, 2026
8ac3fee
fix(tao): flush the display connections after the Linux event loop re…
kdroidFilter Sep 24, 2026
c142d20
Merge pull request #714 from NucleusFramework/fix/exit-process-on-exi…
kdroidFilter Sep 24, 2026
7dffa6d
Merge pull request #712 from NucleusFramework/feat/bundle-nucleus-nat…
kdroidFilter Sep 24, 2026
71c9604
Merge pull request #662 from NucleusFramework/fix/660-tao-trackpad-sc…
kdroidFilter Sep 24, 2026
c62f33e
ci(publish-plugin): set up JDK 21 before Gradle
kdroidFilter Sep 24, 2026
572b6d4
fix(optimization): enable idle GC in GraalVM native images
kdroidFilter Sep 24, 2026
cf4029d
Merge pull request #715 from NucleusFramework/fix/native-image-idle-gc
kdroidFilter Sep 24, 2026
73a36a7
fix(application): disable Compose system theme polling
kdroidFilter Sep 24, 2026
dda6bae
Merge pull request #716 from NucleusFramework/fix/disable-compose-the…
kdroidFilter Sep 24, 2026
a925930
fix(application): disable single instance by default in dev runs
kdroidFilter Sep 24, 2026
098b8f7
Merge pull request #717 from NucleusFramework/fix/dev-single-instance…
kdroidFilter Sep 24, 2026
810674c
feat(application): auto-initialize FileKit with the app id
kdroidFilter Sep 25, 2026
8520410
fix(plugin): refresh package.json and delete read-only app images
kdroidFilter Sep 25, 2026
d7347aa
fix(plugin): remove the appId data dir on NSIS uninstall
kdroidFilter Sep 25, 2026
68c4b77
feat(application): let apps opt out of FileKit auto-initialization
kdroidFilter Sep 25, 2026
0af4712
Merge pull request #718 from NucleusFramework/feat/filekit-auto-init
kdroidFilter Sep 25, 2026
f344491
feat(updater): hot update for Windows NSIS installs
kdroidFilter Sep 25, 2026
79c7644
fix(global-hotkey): deliver hotkey callbacks on the host UI thread
kdroidFilter Sep 25, 2026
70b4119
Merge pull request #721 from NucleusFramework/fix/global-hotkey-ui-th…
kdroidFilter Sep 25, 2026
6aee0db
feat(application): parent FileKit dialogs to a Nucleus window
kdroidFilter Sep 25, 2026
0b3c3a4
build: bump FileKit to 0.16.0
kdroidFilter Sep 25, 2026
730739e
Merge remote-tracking branch 'origin/nucleus-2.6' into feat/windows-h…
kdroidFilter Sep 25, 2026
d8c3e1a
docs(application): explain why macOS FileKit dialogs stay unparented
kdroidFilter Sep 25, 2026
332543e
Merge pull request #722 from NucleusFramework/feat/filekit-dialog-parent
kdroidFilter Sep 25, 2026
0c5c92d
Merge pull request #720 from NucleusFramework/feat/windows-hot-update
kdroidFilter Sep 25, 2026
e8053ea
build: bump dependencies
kdroidFilter Sep 25, 2026
4a44140
Merge pull request #723 from NucleusFramework/chore/bump-dependencies
kdroidFilter Sep 25, 2026
aa11325
test(plugin): match fpm script paths as YAML-escaped on Windows
kdroidFilter Sep 25, 2026
6924d50
feat(updater): test updates without publishing a release
kdroidFilter Sep 25, 2026
a2b37e4
feat(share): add a Kotlin Multiplatform native share sheet module
kdroidFilter Sep 25, 2026
55e093d
feat(share): add the web targets on the Web Share API
kdroidFilter Sep 25, 2026
c784a88
feat(tao): forward back/forward mouse buttons to Compose
skyecodes Sep 25, 2026
766af43
fix(plugin): keep the Gradle classpath order in packaged launchers
kdroidFilter Sep 25, 2026
ed00a44
fix(examples): package the JDK 25 demos with a JDK 25 runtime
kdroidFilter Sep 25, 2026
899a883
Merge pull request #728 from skyecodes/feature/navigation_mouse_buttons
kdroidFilter Sep 25, 2026
567b518
Merge pull request #729 from NucleusFramework/fix/packaged-classpath-…
kdroidFilter Sep 25, 2026
1e67978
Merge pull request #725 from NucleusFramework/feat/updater-dev-testing
kdroidFilter Sep 25, 2026
c00db60
fix(tabs): a tear-off never reuses a restored group id
kdroidFilter Sep 27, 2026
c2ad083
feat(tabs): titleBar slot on TabWindows
kdroidFilter Sep 27, 2026
e1458d7
ci: register the new tab test in the battery, refresh stale API dumps
kdroidFilter Sep 27, 2026
1325e6f
Merge pull request #731 from NucleusFramework/fix/tab-windows-for-zayit
kdroidFilter Sep 27, 2026
f9ff958
feat(tabs): export the parts TabWindows is built from
kdroidFilter Sep 27, 2026
9d7dcd0
fix(tabs): tabSlot ignores a tab that has just left its group
kdroidFilter Sep 27, 2026
ea19b06
feat(tabs): TabGripCursor, the pointer icon of a tab grip
kdroidFilter Sep 27, 2026
25e5f87
Merge pull request #732 from NucleusFramework/feat/app-owned-tab-windows
kdroidFilter Sep 27, 2026
698ec53
feat(satellite): controlButtonsDirection on Satellite
kdroidFilter Sep 27, 2026
cbf41bb
fix(macos): a window created maximized restores to its floating size
kdroidFilter Sep 27, 2026
7fc3092
Merge pull request #733 from NucleusFramework/fix/satellite-control-b…
kdroidFilter Sep 27, 2026
9f21ab7
feat(tabs): linked workspaces take each other's tab drags
kdroidFilter Sep 27, 2026
a6beb66
Merge pull request #734 from NucleusFramework/feat/linked-tab-workspaces
kdroidFilter Sep 27, 2026
cba6f9b
fix(graalvm/macos): make AWT font creation work in native bundles
kdroidFilter Sep 27, 2026
d697406
Merge pull request #735 from NucleusFramework/fix/graalvm-createfont-…
kdroidFilter Sep 27, 2026
f9d6704
fix(tao/macos): deliver Control-click as a secondary click (#736)
kdroidFilter Sep 28, 2026
2579df2
Merge pull request #737 from NucleusFramework/fix/macos-control-click…
kdroidFilter Sep 28, 2026
842f0c3
build: update Gradle wrapper to 9.8.0
kdroidFilter Sep 29, 2026
0e005a7
fix(tao): reject an unplaceable outer position instead of aborting in…
kdroidFilter Sep 30, 2026
c1cbf29
Merge pull request #738 from NucleusFramework/fix/tao-reject-unplacea…
kdroidFilter Sep 30, 2026
87b4713
test(application): bound and reap the theme E2E portal probe
sproctor Oct 1, 2026
5b9cd13
test(launcher-linux): skip the native D-Bus tests when the session bu…
sproctor Oct 1, 2026
0a1ab8d
fix(tao/linux): call XInitThreads before GTK opens its X display
sproctor Sep 30, 2026
984b372
ci(graalvm): run the native test pyramid on setup-nucleus's Xvfb
sproctor Sep 30, 2026
ebc1115
test(tao): disable the flaky scroll symmetry test and record why it f…
sproctor Sep 30, 2026
067db50
ci(graalvm): install x11-utils for the Xvfb check
sproctor Sep 30, 2026
b385867
ci(graalvm): arm the macOS scroll injector for the native headful run
sproctor Oct 1, 2026
30fbb65
test(tao): skip the #576 animated-height headful case on Linux
sproctor Oct 1, 2026
9cc5040
test(tao): link the ignored scroll-symmetry test to CMP-10875
sproctor Oct 1, 2026
53e67aa
test(tao): keep @Ignore'd tests out of the native battery
sproctor Oct 1, 2026
1570c9b
fix(launcher-linux): never lose a GMainLoop quit issued before the lo…
sproctor Oct 1, 2026
e029b4c
fix(launcher-linux): spell the NUL char literal as '\0'
sproctor Oct 1, 2026
d149c1e
fix(updater): reject manifest file names that escape the staging dire…
sproctor Sep 30, 2026
b332e05
test(tao): register OuterPositionTest in the native battery
sproctor Oct 1, 2026
6849b7e
fix(share): pair saved files by name and never time out a Linux porta…
kdroidFilter Oct 4, 2026
49c7759
Merge pull request #744 from sproctor/fix/theme-e2e-requires-portal
kdroidFilter Oct 4, 2026
b1c9be2
fix(share): report a missing Linux handler for mixed payloads, keep A…
kdroidFilter Oct 4, 2026
a6f4b4c
fix(tao): one TaoGpuRenderContext instance per surface
kdroidFilter Oct 4, 2026
77be904
Merge pull request #752 from NucleusFramework/fix/gpu-render-context-…
kdroidFilter Oct 4, 2026
d97cd2b
Merge pull request #727 from NucleusFramework/feat/share-sheet
kdroidFilter Oct 4, 2026
8e1daf3
fix(plugin): accept SemVer pre-release versions on Windows and macOS
sproctor Sep 30, 2026
82358d1
fix(plugin): resolve every packaged version through packageVersionFor
sproctor Oct 4, 2026
9c194ee
test(tao): skip the #576 zoom present-lag case on Linux
sproctor Oct 4, 2026
958df80
fix(tao): keep a drag ghost placeable when the pointer leaves every d…
sproctor Oct 5, 2026
6b0c65f
test(tao): measure the dialog scrim ramp at a fixed point of the fade…
sproctor Oct 5, 2026
1829b55
test(tao): stop the #569 placement cases assuming one large display
sproctor Oct 5, 2026
39ffb7e
fix(tao): settle a wrap-content window even when the scene re-measure…
sproctor Oct 5, 2026
e8563e7
test(tao): give the headful suite room to finish on macOS
sproctor Oct 5, 2026
a7c5f97
Merge pull request #255 from sproctor/feat/jpackage-version
kdroidFilter Oct 5, 2026
bc68b4e
Merge pull request #760 from sproctor/ci/remove-headful-watchdog
kdroidFilter Oct 5, 2026
6aa6e8a
Merge pull request #759 from sproctor/fix/569-tab-motion-offscreen
kdroidFilter Oct 5, 2026
e160365
Merge pull request #758 from sproctor/fix/576-zoom-linux-skip
kdroidFilter Oct 5, 2026
f87b1ef
Merge pull request #740 from sproctor/fix/manifest-path-traversal
kdroidFilter Oct 5, 2026
3dbb1d9
fix(tao): pace clean frames on Windows to the display refresh
kdroidFilter Oct 5, 2026
8e14f66
Merge pull request #761 from NucleusFramework/fix/windows-clean-frame…
kdroidFilter Oct 5, 2026
b5c8609
fix(tao/linux): stop GDK's placeholder origin from moving windows to …
sproctor Oct 5, 2026
3fdb6b7
test(tao): make the dialog-film and overlapping-drag headful cases de…
sproctor Oct 5, 2026
f75c8b6
test(tao): compare dialog films by longest hold, and keep the hide wa…
sproctor Oct 5, 2026
c0eec73
Merge pull request #762 from sproctor/fix/headful-ci-failures
kdroidFilter Oct 5, 2026
f291061
fix(plugin/windows): sign the app image binaries, not only the installer
kdroidFilter Oct 5, 2026
6642c3f
fix(plugin/windows): sign bundled DLLs by default when signing is ena…
kdroidFilter Oct 5, 2026
5baa078
fix(tao): present Windows frames through a flip-model swapchain
kdroidFilter Oct 5, 2026
8493211
fix(plugin/windows): sign JAR libraries before AOT training, decode W…
kdroidFilter Oct 5, 2026
01bb7f3
fix(tao): keep ANGLE's blt present by default, flip chain opt-in
kdroidFilter Oct 5, 2026
6577bc8
fix(plugin/aot): keep the AOT cache valid once installed, keep GraalV…
kdroidFilter Oct 5, 2026
70b6745
fix(plugin/windows): sign JAR libraries before the sandboxed AOT trai…
kdroidFilter Oct 5, 2026
e967e14
fix(plugin/aot): skip JAR signing on dev runs, always define the NSIS…
kdroidFilter Oct 5, 2026
de07823
fix(plugin/nsis): only warn on a real customInstall declaration, reat…
kdroidFilter Oct 5, 2026
46d9e9f
fix(plugin/aot): retrain when the Windows signing settings change
kdroidFilter Oct 5, 2026
0bbe2f6
fix(plugin/windows): keep the PFX password out of Gradle's --info log
kdroidFilter Oct 5, 2026
f8848aa
fix(tao): mirror Windows frames through DirectComposition while a win…
kdroidFilter Oct 5, 2026
e1dfe53
Merge pull request #764 from NucleusFramework/fix/windows-offscreen-p…
kdroidFilter Oct 5, 2026
309db5b
Merge pull request #763 from NucleusFramework/feat/sign-bundled-dlls-748
kdroidFilter Oct 5, 2026
21d818f
ci: update every GitHub Action to its latest version
sproctor Oct 5, 2026
62fb4b3
Merge pull request #767 from sproctor/ci/update-actions
kdroidFilter Oct 5, 2026
2029e9c
fix(tao/macos): fall back to the arrow when a cursor cannot be loaded…
kdroidFilter Oct 5, 2026
24e00fd
fix(tao/macos): one cursor table, no private NSCursor factory where i…
kdroidFilter Oct 5, 2026
d8c485d
fix(tao/macos): set the cursor outside the WINDOWS lock (#746)
kdroidFilter Oct 5, 2026
2e49b02
feat(tao): partial redraw on Linux — repaint and present only the dam…
kdroidFilter Oct 4, 2026
48cccbd
feat(tao): partial redraw on drivers without a buffer age (X11)
kdroidFilter Oct 4, 2026
80abeb4
fix(tao): partial redraw review — idle-hold drain, period drift, pres…
kdroidFilter Oct 4, 2026
c0d4bde
fix(tao): partial redraw review — OS redraws, idle check, frame key t…
kdroidFilter Oct 4, 2026
36c2311
fix(tao): partial redraw — no retained graphics layers, nothing insta…
kdroidFilter Oct 4, 2026
a89a916
feat(tao): partial redraw on macOS — repaint only what each drawable …
kdroidFilter Oct 4, 2026
b4ff86d
feat(tao): macOS partial redraw — repaint in full past 80 % of the dr…
kdroidFilter Oct 5, 2026
c82d1fe
feat(tao): partial redraw on Windows — repaint only the damage, prese…
kdroidFilter Oct 5, 2026
0df6109
feat(tao): repaint in full past 80 % on Windows too, one shared thres…
kdroidFilter Oct 5, 2026
756424d
feat(tao): partial redraw is opt-in through nucleusOptimization { par…
kdroidFilter Oct 5, 2026
a52fb9d
feat(tao): partial redraw tint flashes like Android's "show GPU view …
kdroidFilter Oct 5, 2026
a95340e
feat(plugin): debug { } DSL for the run task, with recomposition coun…
kdroidFilter Oct 5, 2026
d631dd0
fix(tao): re-arm a purged drawable instead of repainting it in full f…
kdroidFilter Oct 5, 2026
f9c98ab
test(examples): partial redraw torture scene with a settle oracle (#755)
kdroidFilter Oct 5, 2026
fc92267
fix(tao): measure the present period from 2 ms, up to 1.5x the curren…
kdroidFilter Oct 5, 2026
9e03ca0
fix(tao): keep running a minimized window's coroutines (#755)
kdroidFilter Oct 5, 2026
2329dc9
fix(tao): apply the snapshot before the damage walk, and tell the ora…
kdroidFilter Oct 5, 2026
2c96490
fix(tao): a writer re-publishing an unchanged clear colour keeps its …
kdroidFilter Oct 5, 2026
6369b15
fix(tao): resize ANGLE's swap chain before drawing the first frame at…
kdroidFilter Oct 5, 2026
204e77e
fix(tao/macos): a blocking frame never leaves its drawable marked cle…
kdroidFilter Oct 5, 2026
3a58031
fix(tao): partial redraw verify dump creates its directory and never …
kdroidFilter Oct 5, 2026
e209360
Merge pull request #756 from NucleusFramework/feat/partial-redraw-755
kdroidFilter Oct 5, 2026
83cc7ea
feat(linux): opt-in glibc malloc arena cap (#757)
kdroidFilter Oct 5, 2026
063d7f2
Merge pull request #769 from NucleusFramework/fix/malloc-arena-cap-757
kdroidFilter Oct 5, 2026
770dc21
Merge pull request #768 from NucleusFramework/fix/tao-cursor-icon-746
kdroidFilter Oct 5, 2026
3f6f7db
fix(tao): a main-dispatcher dispatch no longer renders a frame (#754)
kdroidFilter Oct 5, 2026
099eefd
Merge pull request #770 from NucleusFramework/fix/main-dispatch-frame…
kdroidFilter Oct 5, 2026
3988122
fix(updater): ignore SemVer build metadata when parsing versions
palmoni5 Oct 5, 2026
6ca2bed
Merge pull request #771 from palmoni5/fix/updater-semver-build-metadata
kdroidFilter Oct 6, 2026
35a24a5
fix(updater): limit GenericProvider's http exception to real loopback…
sproctor Sep 30, 2026
9020033
Merge pull request #742 from sproctor/fix/generic-provider-loopback
kdroidFilter Oct 6, 2026
8217243
chore(skills): tag-dev cuts 3.0.0 dev tags
kdroidFilter Oct 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
65 changes: 65 additions & 0 deletions .claude/skills/tag-dev/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
name: tag-dev
description: Create and push a timestamped dev tag for Nucleus 3.0 in the format v3.0.0-dev-YYYYMMDDHHMM, publishing runtime modules to Maven Central and the plugin to the Gradle Plugin Portal without running preMerge. Use when the user asks to "publish a dev build", "cut a dev", "tag dev", "publier une version dev", or similar on this project.
---

# Tag dev — Nucleus 3.0

Creates a timestamped dev tag on the current HEAD and pushes it to `origin`. The tag publishes
**unverified** artifacts: `.github/workflows/publish-maven.yaml` and `publish-plugin.yaml` skip
`preMerge` for dev tags, and the desktop / GraalVM release workflows ignore them entirely.

## Format

`v3.0.0-dev-YYYYMMDDHHMM` — e.g. `v3.0.0-dev-202609200830` for Sep 20 2026, 08:30 UTC.

Timestamp components come from `date -u +%Y%m%d%H%M` (UTC, no separators, 12 chars).

The published Maven version is the tag without the leading `v` (`3.0.0-dev-202609200830`), which
orders below `3.0.0` for Gradle and Maven, so a dev build can never shadow the real release.

## Procedure

1. **Verify the branch is on the 3.0 line** — `nucleus-2.6` (the 3.0 release is cut from it),
`nucleus-3.0` if it exists, or a feature branch cut from either. A dev tag on `main` or on the
2.5 line would publish a `3.0.0-dev-*` version from the wrong code; abort and say so.
2. **Verify the working tree is clean** — `git status --porcelain` empty. If dirty, ask the user
whether to commit first or abort. Never tag a dirty tree: the tag is what CI builds.
3. **Verify HEAD is pushed** — `git fetch origin` then check the commit exists on the remote
(`git branch -r --contains HEAD`). A tag on an unpushed commit makes CI check out a commit
nobody else has; push the branch first (ask before pushing).
4. **Generate the timestamp** with `date -u +%Y%m%d%H%M`.
5. **Check the tag doesn't already exist** — `git tag -l v3.0.0-dev-<ts>`. If it does, use the
next minute; Maven Central versions are immutable, a retag would publish nothing.
6. **Create an annotated tag**:
```bash
git tag -a "v3.0.0-dev-<ts>" -m "v3.0.0-dev-<ts>"
```
Annotated (not lightweight) because the published history uses annotated tags.
7. **Push the tag**:
```bash
git push origin "v3.0.0-dev-<ts>"
```
8. **Report** the tag name, the commit SHA, the resulting Maven version, and the coordinates a
consumer needs, e.g.:
```kotlin
implementation("dev.nucleusframework:nucleus.decorated-window-tao:3.0.0-dev-<ts>")
```
Mention that Central takes ~15 minutes to expose the version after the workflow goes green.

## Hard rules

- Never tag `main` or the 2.5 line with this format.
- Never cut a `2.6.0-dev-*` tag anymore: the next release is 3.0.0.
- Never overwrite or force-push a tag — the version is already on Central and cannot be replaced.
- Never add `Co-Authored-By` or AI attribution to the tag message (per the project's CLAUDE.md).
- Tag message body is just the tag name itself — matches the existing convention.
- The tag must stay `v<major>.<minor>.<patch>-dev-<id>`: `.github/actions/release-tag-info`
rejects anything else, because every publish task derives its version by stripping
`refs/tags/v` from `GITHUB_REF`.

## When NOT to use this skill

- Stable releases (`v3.0.0`) — those go through the full `preMerge` gate and cut GitHub releases.
- Alpha/beta/rc prereleases — see the `tag-alpha` skill and `.github/actions/validate-release-ref`.
- Backporting onto an old commit — this skill always tags `HEAD`.
24 changes: 24 additions & 0 deletions .github/actions/build-macos-universal/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ inputs:
description: 'Path to runtime embedded.provisionprofile for sandboxed app runtime'
required: false
default: ''
electron-builder-toolchain-dir:
description: 'Directory holding the package.json / package-lock.json of the pinned electron-builder toolchain embedded in the Nucleus plugin'
required: false
default: 'plugin-build/plugin/src/main/resources/nucleus/electron-builder'
node-version:
description: 'Node.js line to provision (a major like 22, or a pinned x.y.z). Keep in sync with the nativeDistributions { nodejs { version } } default.'
required: false
default: '22'

outputs:
zip:
Expand Down Expand Up @@ -102,6 +110,22 @@ runs:
echo "==> No sandboxed ZIPs found (App Store PKG will use electron-builder fallback)"
fi

# Same cache entry as setup-nucleus: the provisioning script uses the
# plugin's install layout, so a Node.js downloaded by either is reused.
- name: Cache Node.js toolchain
uses: actions/cache@v6
with:
path: ~/.gradle/nucleus/nodejs
key: nodejs-toolchain-${{ runner.os }}-${{ runner.arch }}-${{ inputs.node-version }}

- name: Provision Node.js and electron-builder
shell: bash
env:
NODE_LINE: ${{ inputs.node-version }}
TOOLCHAIN_DIR: ${{ inputs.electron-builder-toolchain-dir }}
TOOL_DIR: ${{ runner.temp }}/electron-builder-tool
run: bash "${{ github.action_path }}/provision-electron-builder.sh"

- name: Build universal binary
id: build
shell: bash
Expand Down
5 changes: 3 additions & 2 deletions .github/actions/build-macos-universal/build-universal.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
set -euo pipefail

# ── Required env vars ─────────────────────────────────────────────────────
: "${ARM64_ZIP:?}" "${X64_ZIP:?}" "${OUTPUT_DIR:?}"
: "${ARM64_ZIP:?}" "${X64_ZIP:?}" "${OUTPUT_DIR:?}" "${NODE_BIN:?}" "${ELECTRON_BUILDER_CLI:?}"

# ── Optional env vars (default to empty) ──────────────────────────────────
SIGNING_IDENTITY="${SIGNING_IDENTITY:-}"
Expand Down Expand Up @@ -499,8 +499,9 @@ run_electron_builder() {
codesign --force --deep --sign - "$app_copy"
fi

# Provisioned by provision-electron-builder.sh from the plugin's lock file.
CSC_IDENTITY_AUTO_DISCOVERY=false \
npx --yes electron-builder \
"$NODE_BIN" "$ELECTRON_BUILDER_CLI" \
--prepackaged "$app_copy" \
--config "$eb_dir/electron-builder.yml" \
--config.electronVersion=33.0.0 \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env bash
# Provisions the same Node.js and the same pinned electron-builder toolchain the Nucleus plugin
# uses, for the universal repack — which runs electron-builder outside the plugin.
#
# - Node.js: the newest release of $NODE_LINE from nodejs.org, verified against the release's
# SHASUMS256.txt, installed with the plugin's layout (NodeToolchainProvisioner):
# <install-base>/node-<line>-darwin-<arch>/<archive top dir>/ plus a `.nucleus-provisioned`
# marker naming that top dir. A cache restored from a plugin run is therefore reused as is.
# - electron-builder: `npm ci --ignore-scripts` against the lock file embedded in the plugin, so
# every transitive package is checked against its recorded integrity hash (no `npx --yes`).
#
# Writes NODE_BIN and ELECTRON_BUILDER_CLI to $GITHUB_ENV.
set -euo pipefail

: "${NODE_LINE:?}" "${TOOLCHAIN_DIR:?}" "${TOOL_DIR:?}"
# The plugin's default cache location (<gradle-user-home>/nucleus/nodejs).
NODE_INSTALL_BASE="${NODE_INSTALL_BASE:-$HOME/.gradle/nucleus/nodejs}"

case "$(uname -m)" in
arm64 | aarch64) arch="arm64" ;;
x86_64) arch="x64" ;;
*) echo "::error::Unsupported architecture $(uname -m)" >&2; exit 1 ;;
esac

install_dir="$NODE_INSTALL_BASE/node-$NODE_LINE-darwin-$arch"
marker="$install_dir/.nucleus-provisioned"

if [[ -f "$marker" && -x "$install_dir/$(cat "$marker")/bin/node" ]]; then
node_home="$install_dir/$(cat "$marker")"
echo "==> Reusing Node.js at $node_home"
else
dist="https://nodejs.org/dist"
# Same rule as the plugin: a pinned x.y.z as is, otherwise the newest release of that major.
if [[ "$NODE_LINE" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
version="v${NODE_LINE#v}"
else
version="$(curl -fsSL "$dist/index.json" |
jq -r --arg major "$NODE_LINE" \
'[.[] | select(.version | startswith("v" + $major + "."))]
| sort_by(.version | ltrimstr("v") | split(".") | map(tonumber)) | last | .version')"
fi
if [[ -z "$version" || "$version" == "null" ]]; then
echo "::error::No Node.js release matches '$NODE_LINE'" >&2
exit 1
fi

archive="node-$version-darwin-$arch.tar.gz"
work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT

echo "==> Downloading Node.js $version from $dist/$version/$archive"
curl -fsSL -o "$work/$archive" "$dist/$version/$archive"
curl -fsSL -o "$work/SHASUMS256.txt" "$dist/$version/SHASUMS256.txt"
(cd "$work" && grep " $archive\$" SHASUMS256.txt | shasum -a 256 -c -)

tar -xzf "$work/$archive" -C "$work"
top_dir="node-$version-darwin-$arch"
rm -rf "$install_dir"
mkdir -p "$install_dir"
mv "$work/$top_dir" "$install_dir/"
echo "$top_dir" > "$marker"
node_home="$install_dir/$top_dir"
echo "==> Node.js $version installed to $node_home"
fi

node_bin="$node_home/bin/node"
# npm's launcher resolves `node` through PATH.
export PATH="$node_home/bin:$PATH"

echo "==> Provisioning electron-builder from the plugin's lock file (npm ci --ignore-scripts)"
rm -rf "$TOOL_DIR"
mkdir -p "$TOOL_DIR"
cp "$TOOLCHAIN_DIR/package.json" "$TOOLCHAIN_DIR/package-lock.json" "$TOOL_DIR/"
(cd "$TOOL_DIR" && npm ci --ignore-scripts --no-audit --no-fund --no-progress --loglevel=error)

cli="$TOOL_DIR/node_modules/electron-builder/cli.js"
if [[ ! -f "$cli" ]]; then
echo "::error::electron-builder CLI missing at $cli after npm ci" >&2
exit 1
fi
echo "==> electron-builder $("$node_bin" "$cli" --version)"

{
echo "NODE_BIN=$node_bin"
echo "ELECTRON_BUILDER_CLI=$cli"
} >> "$GITHUB_ENV"
64 changes: 64 additions & 0 deletions .github/actions/release-tag-info/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Release tag info
description: Classifies the pushed tag into a release channel and derives the version the build will publish

outputs:
version:
description: Maven version the publish tasks will derive from the tag (tag name without the leading `v`)
value: ${{ steps.classify.outputs.version }}
channel:
description: '`dev` for a `v<version>-dev-<id>` tag, `release` for anything else'
value: ${{ steps.classify.outputs.channel }}
is-dev:
description: '`true` when the tag is a dev tag (publish without running preMerge)'
value: ${{ steps.classify.outputs.is-dev }}

runs:
using: composite
steps:
- name: Classify tag
id: classify
shell: bash
run: |
set -euo pipefail

if [[ "${GITHUB_REF_TYPE:-}" != "tag" ]]; then
echo "::error::release-tag-info only runs on tag refs (got '${GITHUB_REF_TYPE:-none}')."
exit 1
fi

tag="${GITHUB_REF_NAME}"

# Every publish task derives its version with `GITHUB_REF.removePrefix("refs/tags/v")`,
# so a tag that is not `v<semver>` would publish a version literally named
# `refs/tags/<tag>`. Fail here rather than on Maven Central, where it is permanent.
if [[ ! "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?$ ]]; then
echo "::error::Tag '$tag' is not a publishable version tag (expected v<major>.<minor>.<patch>[-qualifier])."
exit 1
fi

version="${tag#v}"

# Dev channel: `v2.6.0-dev-202609200830`. Cut from any branch, published without
# preMerge — the usual Kotlin-ecosystem `-dev-` build.
if [[ "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-dev([.-][0-9A-Za-z]+)*$ ]]; then
channel=dev
is_dev=true
else
channel=release
is_dev=false
fi

echo "Tag '$tag' → version '$version', channel '$channel'."
{
echo "version=$version"
echo "channel=$channel"
echo "is-dev=$is_dev"
} >> "$GITHUB_OUTPUT"

{
echo "### Publishing \`$version\` (\`$channel\` channel)"
if [[ "$is_dev" == "true" ]]; then
echo ""
echo "Dev tag: \`preMerge\` is skipped."
fi
} >> "$GITHUB_STEP_SUMMARY"
38 changes: 20 additions & 18 deletions .github/actions/setup-nucleus/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,25 @@ inputs:
required: false
default: 'false'
setup-gradle:
description: 'Setup Gradle via gradle/actions/setup-gradle@v5'
description: 'Setup Gradle via gradle/actions/setup-gradle@v6 (open-source basic cache provider)'
required: false
default: 'true'
graalvm:
description: 'Prepare a GraalVM native-image build: native build tools (Xcode/MSVC) and toolchain cache. The GraalVM JDK itself is auto-downloaded by the Nucleus plugin.'
required: false
default: 'false'
graalvm-version:
description: 'GraalVM toolchain version, used only as a cache-key component. Keep in sync with the graalvm { toolchain { } } DSL (e.g. 25i3, 25).'
description: 'GraalVM toolchain version, used only as a cache-key component. Keep in sync with the graalvm { toolchain { } } DSL (e.g. 25i4, 25).'
required: false
default: '25i3'
default: '25i4'
graalvm-distribution:
description: 'GraalVM distribution, used only as a cache-key component. Keep in sync with graalvm { toolchain { distribution } } (community or oracle). Changing it must not restore a cache holding the other distribution.'
required: false
default: 'community'
setup-node:
description: 'Setup Node.js'
required: false
default: 'true'
node-version:
description: 'Node.js version'
description: 'Node.js line the Nucleus plugin provisions, used only as a cache-key component. Keep in sync with the nativeDistributions { nodejs { version } } DSL.'
required: false
default: '24'
default: '22'

outputs:
java-home:
Expand All @@ -62,10 +58,9 @@ runs:
# Temurin, matching the rest of the workflows. jpackage bundles this JDK into
# the distributed app. In GraalVM mode the native image is built entirely by
# the plugin-provisioned GraalVM, so the Gradle JDK contributes nothing to
# that output. decorated-window-jbr needs no JBR here — the JBR API comes
# from the org.jetbrains.runtime:jbr-api Maven artifact.
# that output.
- name: Set up JDK
uses: actions/setup-java@v4
uses: actions/setup-java@v6
with:
distribution: ${{ runner.os == 'Windows' && 'microsoft' || 'temurin' }}
java-version: ${{ inputs.java-version }}
Expand Down Expand Up @@ -94,7 +89,7 @@ runs:
# a cache still holding the other build.
- name: Cache GraalVM toolchain
if: inputs.graalvm == 'true'
uses: actions/cache@v4
uses: actions/cache@v6
with:
path: ~/.gradle/nucleus/graalvm
key: graalvm-toolchain-${{ runner.os }}-${{ runner.arch }}-${{ inputs.graalvm-distribution }}-${{ inputs.graalvm-version }}
Expand Down Expand Up @@ -152,11 +147,18 @@ runs:
# ── Gradle ──────────────────────────────────────────────────────────
- name: Setup Gradle
if: inputs.setup-gradle == 'true'
uses: gradle/actions/setup-gradle@v5
uses: gradle/actions/setup-gradle@v6
with:
# Open-source cache on GitHub Actions cache; v6's default provider is proprietary.
cache-provider: basic

# ── Node.js ─────────────────────────────────────────────────────────
- name: Setup Node.js
if: inputs.setup-node == 'true'
uses: actions/setup-node@v6
# No actions/setup-node: the Nucleus plugin downloads the Node.js it runs
# electron-builder with and caches it under ~/.gradle/nucleus/nodejs, so CI
# packages with the same toolchain a developer machine does. Only the cache
# is CI's business.
- name: Cache Node.js toolchain
uses: actions/cache@v6
with:
node-version: ${{ inputs.node-version }}
path: ~/.gradle/nucleus/nodejs
key: nodejs-toolchain-${{ runner.os }}-${{ runner.arch }}-${{ inputs.node-version }}
Loading
Loading