<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kukuri.git, branch main</title>
<subtitle>kukuri: Kotlin Multiplatform app (desktop / wasm / native / Android) for the orgflow UI</subtitle>
<link rel='alternate' type='text/html' href='https://openpgpkey.dangofactory.net/cgit/cgit.cgi/kukuri.git/'/>
<entry>
<title>UI: the pie labels were a quarter-turn out from their own wedges</title>
<updated>2026-10-05T14:58:26+00:00</updated>
<author>
<name>Charlie Root</name>
<email>root@dangofactory.local</email>
</author>
<published>2026-10-05T14:58:26+00:00</published>
<link rel='alternate' type='text/html' href='https://openpgpkey.dangofactory.net/cgit/cgit.cgi/kukuri.git/commit/?id=e0465ad93dd2d2123a7cd6eb1bf497d0a6b47535'/>
<id>e0465ad93dd2d2123a7cd6eb1bf497d0a6b47535</id>
<content type='text'>
Three attempts at this and the cause was never the offset arithmetic. Measured
on build 86, the label mean angles were 45.9 / 130.3 / 209.1 / 319.9 degrees while
the wedge centres are 0 / 90 / 180 / 270. A constant ~45 degree error in all four
quadrants is not a magnitude problem, it is an origin problem.

The wedges are drawn at angles[i], which distributeAngles() fills starting from 0
and stepping clockwise, so item 0 sits at drawAngle 0 -- to the RIGHT, because
canvas angles run from 3 o'clock. The label loop was computing
`i * (360.0/n) - 90.0`, which assumes the first wedge is at the top. So the labels
were anchored a quarter turn away from the wedges, which is exactly one
separator, and no value of the constant would have fixed it.

The labels now take the wedge angles as a parameter and use angles[i] directly,
so a label and its wedge cannot disagree again -- including for a menu whose item
count is not 4 or which pins an item with an explicit `angle`.

Also worth recording: the two earlier attempts were tuning a constant while the
constant itself was wrong, and the measurements (19 px in the top quadrant, then
"all four on the boundaries") were consistent with an origin bug the whole time.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Three attempts at this and the cause was never the offset arithmetic. Measured
on build 86, the label mean angles were 45.9 / 130.3 / 209.1 / 319.9 degrees while
the wedge centres are 0 / 90 / 180 / 270. A constant ~45 degree error in all four
quadrants is not a magnitude problem, it is an origin problem.

The wedges are drawn at angles[i], which distributeAngles() fills starting from 0
and stepping clockwise, so item 0 sits at drawAngle 0 -- to the RIGHT, because
canvas angles run from 3 o'clock. The label loop was computing
`i * (360.0/n) - 90.0`, which assumes the first wedge is at the top. So the labels
were anchored a quarter turn away from the wedges, which is exactly one
separator, and no value of the constant would have fixed it.

The labels now take the wedge angles as a parameter and use angles[i] directly,
so a label and its wedge cannot disagree again -- including for a menu whose item
count is not 4 or which pins an item with an explicit `angle`.

Also worth recording: the two earlier attempts were tuning a constant while the
constant itself was wrong, and the measurements (19 px in the top quadrant, then
"all four on the boundaries") were consistent with an origin bug the whole time.
</pre>
</div>
</content>
</entry>
<entry>
<title>build: metaspace was the limit, not heap or wasm-opt's -Oz</title>
<updated>2026-10-05T14:14:07+00:00</updated>
<author>
<name>Charlie Root</name>
<email>root@dangofactory.local</email>
</author>
<published>2026-10-05T14:14:07+00:00</published>
<link rel='alternate' type='text/html' href='https://openpgpkey.dangofactory.net/cgit/cgit.cgi/kukuri.git/commit/?id=d4c6c11df0cf60dd956fe0d84f2edc97ffc8381d'/>
<id>d4c6c11df0cf60dd956fe0d84f2edc97ffc8381d</id>
<content type='text'>
build 84 died in bundle-web with "Gradle build daemon disappeared unexpectedly",
same as builds 76 and 77. The daemon log is what finally settled it:

  Starting 8th build in daemon [uptime: 3m45s, performance: 99%, GC rate: 0.00/s,
                                 heap usage: 0% of 2 GiB, non-heap usage: 28% of 512 MiB]
  ...
  ValidateIrAfterLowering

Heap usage was zero. The host was 91% idle. wasm-opt was still at -Oz. None of
those were the cause: the daemon had served eight builds and by the eighth its
class metadata had filled a 512 MiB metaspace, and it died while wasm-opt's Kotlin
lowering loaded more IR classes. So this is non-heap exhaustion, and the fix is
non-heap capacity.

  -XX:MaxMetaspaceSize 512m -&gt; 1g
  org.gradle.daemon=false          one JVM per build, so metadata cannot pile up

Verified by reproducing the CI sequence -- clean the wasm outputs, the build
cache and the configuration cache exactly as clean-wasm-output does, then run
bundleWeb: BUILD SUCCESSFUL in 12m, no signal 9. That is the same sequence that
just failed in CI.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
build 84 died in bundle-web with "Gradle build daemon disappeared unexpectedly",
same as builds 76 and 77. The daemon log is what finally settled it:

  Starting 8th build in daemon [uptime: 3m45s, performance: 99%, GC rate: 0.00/s,
                                 heap usage: 0% of 2 GiB, non-heap usage: 28% of 512 MiB]
  ...
  ValidateIrAfterLowering

Heap usage was zero. The host was 91% idle. wasm-opt was still at -Oz. None of
those were the cause: the daemon had served eight builds and by the eighth its
class metadata had filled a 512 MiB metaspace, and it died while wasm-opt's Kotlin
lowering loaded more IR classes. So this is non-heap exhaustion, and the fix is
non-heap capacity.

  -XX:MaxMetaspaceSize 512m -&gt; 1g
  org.gradle.daemon=false          one JVM per build, so metadata cannot pile up

Verified by reproducing the CI sequence -- clean the wasm outputs, the build
cache and the configuration cache exactly as clean-wasm-output does, then run
bundleWeb: BUILD SUCCESSFUL in 12m, no signal 9. That is the same sequence that
just failed in CI.
</pre>
</div>
</content>
</entry>
<entry>
<title>build: drop to --max-workers=1; -Oz was never the problem</title>
<updated>2026-10-05T13:23:42+00:00</updated>
<author>
<name>Charlie Root</name>
<email>root@dangofactory.local</email>
</author>
<published>2026-10-05T13:23:42+00:00</published>
<link rel='alternate' type='text/html' href='https://openpgpkey.dangofactory.net/cgit/cgit.cgi/kukuri.git/commit/?id=8b197b25293024be3df541ea292164558505e783'/>
<id>8b197b25293024be3df541ea292164558505e783</id>
<content type='text'>
build 83's assemble ended with "command finished with signal 9". I had assumed
that was wasm-opt's -Oz pass list and tried to change it to -O2, which broke the
detekt gate instead (detekt parses build.gradle.kts as Kotlin source, and the
`optimizations { wasm-opt { ... } }` accessor does not resolve there -- 9
"Unresolved reference" errors). That DSL block is gone again in 4f00e13.

With the block removed, wasm-opt still runs at -Oz and both of the steps that
were dying now pass on this host:

  ./gradlew --max-workers=1 assemble   BUILD SUCCESSFUL in 7m38s
  ./gradlew --max-workers=1 bundleWeb  BUILD SUCCESSFUL in 3m11s

with no signal 9. So the killer was concurrency, not the optimizer level: several
JVMs (Gradle, the Kotlin daemon, wasm-opt) resident at once is what overran the
11.9 GB. The budgets are lowered to match (Gradle 3g -&gt; 2g, Kotlin 2g -&gt; 1.5g)
and --max-workers=1 is applied to assemble, bundles and bundle-web so only one
compile is resident at a time. The wall clock goes up, which is the trade that has
to be made for a bundle that exists.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
build 83's assemble ended with "command finished with signal 9". I had assumed
that was wasm-opt's -Oz pass list and tried to change it to -O2, which broke the
detekt gate instead (detekt parses build.gradle.kts as Kotlin source, and the
`optimizations { wasm-opt { ... } }` accessor does not resolve there -- 9
"Unresolved reference" errors). That DSL block is gone again in 4f00e13.

With the block removed, wasm-opt still runs at -Oz and both of the steps that
were dying now pass on this host:

  ./gradlew --max-workers=1 assemble   BUILD SUCCESSFUL in 7m38s
  ./gradlew --max-workers=1 bundleWeb  BUILD SUCCESSFUL in 3m11s

with no signal 9. So the killer was concurrency, not the optimizer level: several
JVMs (Gradle, the Kotlin daemon, wasm-opt) resident at once is what overran the
11.9 GB. The budgets are lowered to match (Gradle 3g -&gt; 2g, Kotlin 2g -&gt; 1.5g)
and --max-workers=1 is applied to assemble, bundles and bundle-web so only one
compile is resident at a time. The wall clock goes up, which is the trade that has
to be made for a bundle that exists.
</pre>
</div>
</content>
</entry>
<entry>
<title>build: drop the wasm-opt DSL block that detekt cannot parse</title>
<updated>2026-10-05T12:57:29+00:00</updated>
<author>
<name>Charlie Root</name>
<email>root@dangofactory.local</email>
</author>
<published>2026-10-05T12:57:29+00:00</published>
<link rel='alternate' type='text/html' href='https://openpgpkey.dangofactory.net/cgit/cgit.cgi/kukuri.git/commit/?id=4f00e13607ad4137fec4ce54f1ebeca03889e099'/>
<id>4f00e13607ad4137fec4ce54f1ebeca03889e099</id>
<content type='text'>
The -O2 block I added to silence the OOM killer broke the detekt gate instead.
build 82 failed at detekt-gate, and running detekt by hand showed why: it parses
build.gradle.kts as Kotlin source, and the Kotlin DSL's optimizations { wasm-opt
{ ... } } is a lazy accessor with no resolvable type, so detekt reported 9
'Unresolved reference' errors on wasm-opt, optimizationLevel and pass.

So the file is back to the plain
and detekt passes again (verified: detekt and compileKotlinWasmJs both
BUILD SUCCESSFUL).

The OOM problem is therefore NOT fixed by this commit. wasm-opt still runs at
-Oz and bundleWeb can still be killed by signal 9. The fix has to be expressed in
a way detekt can parse, which means the argument list for the optimizer task
rather than the target DSL. That is the next change, and it needs to be verified
against both detekt and bundleWeb in one go, because each one alone will not tell
you whether it worked.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The -O2 block I added to silence the OOM killer broke the detekt gate instead.
build 82 failed at detekt-gate, and running detekt by hand showed why: it parses
build.gradle.kts as Kotlin source, and the Kotlin DSL's optimizations { wasm-opt
{ ... } } is a lazy accessor with no resolvable type, so detekt reported 9
'Unresolved reference' errors on wasm-opt, optimizationLevel and pass.

So the file is back to the plain
and detekt passes again (verified: detekt and compileKotlinWasmJs both
BUILD SUCCESSFUL).

The OOM problem is therefore NOT fixed by this commit. wasm-opt still runs at
-Oz and bundleWeb can still be killed by signal 9. The fix has to be expressed in
a way detekt can parse, which means the argument list for the optimizer task
rather than the target DSL. That is the next change, and it needs to be verified
against both detekt and bundleWeb in one go, because each one alone will not tell
you whether it worked.
</pre>
</div>
</content>
</entry>
<entry>
<title>build: wasm-opt -Oz -&gt; -O2; the optimizer was OOM-killed</title>
<updated>2026-10-05T12:33:08+00:00</updated>
<author>
<name>Charlie Root</name>
<email>root@dangofactory.local</email>
</author>
<published>2026-10-05T12:33:08+00:00</published>
<link rel='alternate' type='text/html' href='https://openpgpkey.dangofactory.net/cgit/cgit.cgi/kukuri.git/commit/?id=24ab3fc0b9fa9c5079186605f34c71f1dcf11584'/>
<id>24ab3fc0b9fa9c5079186605f34c71f1dcf11584</id>
<content type='text'>
build 81's bundle-web ended with 'process killed by signal 9' during
compileProductionExecutableKotlinWasmJsOptimize, i.e. the OOM killer took
wasm-opt on this 11.9 GB host. wasm-opt exposes no memory cap, so the only lever
is how much work it is asked to do.

At -Oz Kotlin's default pass list runs --gufa plus repeated -O3 --type-merging.
That combination is the memory peak. -O2 keeps most of the size win and does not
pull in gufa. The pass list is now written out explicitly so it cannot silently
drift back to the -Oz defaults.

This trades a little wasm size for the web bundle actually shipping at all, which
is the right way round: an unbuilt bundle helps nobody.

Also fixes the CI fleet-wide daemon pressure by leaving the --max-workers=2
restriction from the previous commit in place.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
build 81's bundle-web ended with 'process killed by signal 9' during
compileProductionExecutableKotlinWasmJsOptimize, i.e. the OOM killer took
wasm-opt on this 11.9 GB host. wasm-opt exposes no memory cap, so the only lever
is how much work it is asked to do.

At -Oz Kotlin's default pass list runs --gufa plus repeated -O3 --type-merging.
That combination is the memory peak. -O2 keeps most of the size win and does not
pull in gufa. The pass list is now written out explicitly so it cannot silently
drift back to the -Oz defaults.

This trades a little wasm size for the web bundle actually shipping at all, which
is the right way round: an unbuilt bundle helps nobody.

Also fixes the CI fleet-wide daemon pressure by leaving the --max-workers=2
restriction from the previous commit in place.
</pre>
</div>
</content>
</entry>
<entry>
<title>UI: place the pie labels by absolute polar coordinates</title>
<updated>2026-10-05T12:04:37+00:00</updated>
<author>
<name>Charlie Root</name>
<email>root@dangofactory.local</email>
</author>
<published>2026-10-05T12:04:37+00:00</published>
<link rel='alternate' type='text/html' href='https://openpgpkey.dangofactory.net/cgit/cgit.cgi/kukuri.git/commit/?id=43bcab0d3af73559c7004e33cc291a95d8522b96'/>
<id>43bcab0d3af73559c7004e33cc291a95d8522b96</id>
<content type='text'>
Third attempt at the label placement, and the previous one did not work. Measured
about the true disc centre (135.0, 725.5, a 200x200 disc) the label means sat at
152 / 201 / 300 degrees: still 15-24 degrees from a separator and 21-62 degrees
from a wedge centre.

Why 90 dp did not fix it: Modifier.offset is applied AFTER placement, so it adds
to wherever the parent's placement rules already decided. With
Box(Modifier.fillMaxSize(), contentAlignment = Center) the parent was deciding,
and a polar offset added on top of that is not a polar position -- the parent's
rules win and the angle comes out wrong.

This time the parent stops deciding. BoxWithConstraints gives the real
constraint size, and each label box is positioned at
(centre + cos/sin * 67dp - halfBox) with nothing else touching placement. Box
is 84 dp so it fits inside a 45 degree wedge at r=67 (arc length there is about
53 dp), and the box's centre, not its corner, is placed on the bisector.

Verified by measurement on the next build rather than assumed: the label mean
angle per quadrant must come out near 0/90/180/270 rather than 45/135/225/315.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Third attempt at the label placement, and the previous one did not work. Measured
about the true disc centre (135.0, 725.5, a 200x200 disc) the label means sat at
152 / 201 / 300 degrees: still 15-24 degrees from a separator and 21-62 degrees
from a wedge centre.

Why 90 dp did not fix it: Modifier.offset is applied AFTER placement, so it adds
to wherever the parent's placement rules already decided. With
Box(Modifier.fillMaxSize(), contentAlignment = Center) the parent was deciding,
and a polar offset added on top of that is not a polar position -- the parent's
rules win and the angle comes out wrong.

This time the parent stops deciding. BoxWithConstraints gives the real
constraint size, and each label box is positioned at
(centre + cos/sin * 67dp - halfBox) with nothing else touching placement. Box
is 84 dp so it fits inside a 45 degree wedge at r=67 (arc length there is about
53 dp), and the box's centre, not its corner, is placed on the bisector.

Verified by measurement on the next build rather than assumed: the label mean
angle per quadrant must come out near 0/90/180/270 rather than 45/135/225/315.
</pre>
</div>
</content>
</entry>
<entry>
<title>UI: stop the pie labels from riding the quadrant boundaries</title>
<updated>2026-10-05T11:19:36+00:00</updated>
<author>
<name>Charlie Root</name>
<email>root@dangofactory.local</email>
</author>
<published>2026-10-05T11:19:36+00:00</published>
<link rel='alternate' type='text/html' href='https://openpgpkey.dangofactory.net/cgit/cgit.cgi/kukuri.git/commit/?id=fa6352a2e84a17651234fee639d0f560877fd23f'/>
<id>fa6352a2e84a17651234fee639d0f560877fd23f</id>
<content type='text'>
The previous commit fixed the missing top label but left the placement wrong in
a subtler way, and the measurement caught it: taking the circular mean of the
white ink in each quadrant gave 60 / 128 / 207 / 325 degrees. The wedge bisectors
are 0 / 90 / 180 / 270 and the separators are 45 / 135 / 225 / 315, so every
label sat 27-60 degrees off its wedge centre and within 7-18 degrees of a
separator.

Cause: each label lived in a Box sized labelRadius * 2 = 134 dp. That is two
thirds of the whole 200 dp disc, so it does not fit inside a 45 degree wedge.
Compose redistributed the overflow by placing the child about 45 degrees away
from where the offset asked, which is exactly the boundary-hugging result.

Fix: size the measuring box at 90 dp so it fits the wedge arc, and compute the
top-left so the box's CENTRE lands on the bisector at 67 dp rather than letting
the box corner land there. Radial distance is unchanged.

Hub stays at 22% and the separators stay 3 px; the review only complained the
overall structure still read weakly because of this placement.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The previous commit fixed the missing top label but left the placement wrong in
a subtler way, and the measurement caught it: taking the circular mean of the
white ink in each quadrant gave 60 / 128 / 207 / 325 degrees. The wedge bisectors
are 0 / 90 / 180 / 270 and the separators are 45 / 135 / 225 / 315, so every
label sat 27-60 degrees off its wedge centre and within 7-18 degrees of a
separator.

Cause: each label lived in a Box sized labelRadius * 2 = 134 dp. That is two
thirds of the whole 200 dp disc, so it does not fit inside a 45 degree wedge.
Compose redistributed the overflow by placing the child about 45 degrees away
from where the offset asked, which is exactly the boundary-hugging result.

Fix: size the measuring box at 90 dp so it fits the wedge arc, and compute the
top-left so the box's CENTRE lands on the bisector at 67 dp rather than letting
the box corner land there. Radial distance is unchanged.

Hub stays at 22% and the separators stay 3 px; the review only complained the
overall structure still read weakly because of this placement.
</pre>
</div>
</content>
</entry>
<entry>
<title>build: cap Gradle parallelism; the daemon was being OOM-killed, not wedged</title>
<updated>2026-10-05T10:27:20+00:00</updated>
<author>
<name>Charlie Root</name>
<email>root@dangofactory.local</email>
</author>
<published>2026-10-05T10:27:20+00:00</published>
<link rel='alternate' type='text/html' href='https://openpgpkey.dangofactory.net/cgit/cgit.cgi/kukuri.git/commit/?id=19113d280955e0ffd4fd14eef7cdac1347a30f84'/>
<id>19113d280955e0ffd4fd14eef7cdac1347a30f84</id>
<content type='text'>
builds 76 and 77 both died in assemble with 'Gradle build daemon disappeared
unexpectedly'. I had guessed --no-daemon would help; it did not, it just moved
the whole build into the client JVM and that died the same way. The useful
evidence was ./gradlew --status reporting every daemon as 'STOPPED (by user or
operating system)' while vmstat showed 91% of 11.9 GB idle, and the build log
complaining that 9 stopped daemons could not be reused.

What actually fixes it is the worker count. assemble with --max-workers=2
completed in 5m33s from a clean daemon registry. So:

  org.gradle.parallel=false          project-level parallelism off
  org.gradle.jvmargs -Xmx1536m -&gt; 3g (holds Kotlin now that it is in-process)
  kotlin.daemon.jvmargs 4096m -&gt; 2g
  kotlin.compiler.execution.strategy=in-process   one fewer 4 GB JVM
  registry.maximum-size=1, idletimeout 2 min    the pool stops accumulating
  assemble step passes --max-workers=2 explicitly

bundle-web drops --no-daemon again; with the pool bounded, a normal reused daemon
is correct and faster for a ~1 min task.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
builds 76 and 77 both died in assemble with 'Gradle build daemon disappeared
unexpectedly'. I had guessed --no-daemon would help; it did not, it just moved
the whole build into the client JVM and that died the same way. The useful
evidence was ./gradlew --status reporting every daemon as 'STOPPED (by user or
operating system)' while vmstat showed 91% of 11.9 GB idle, and the build log
complaining that 9 stopped daemons could not be reused.

What actually fixes it is the worker count. assemble with --max-workers=2
completed in 5m33s from a clean daemon registry. So:

  org.gradle.parallel=false          project-level parallelism off
  org.gradle.jvmargs -Xmx1536m -&gt; 3g (holds Kotlin now that it is in-process)
  kotlin.daemon.jvmargs 4096m -&gt; 2g
  kotlin.compiler.execution.strategy=in-process   one fewer 4 GB JVM
  registry.maximum-size=1, idletimeout 2 min    the pool stops accumulating
  assemble step passes --max-workers=2 explicitly

bundle-web drops --no-daemon again; with the pool bounded, a normal reused daemon
is correct and faster for a ~1 min task.
</pre>
</div>
</content>
</entry>
<entry>
<title>UI: fix the pie's top label falling outside the disc</title>
<updated>2026-10-05T09:10:58+00:00</updated>
<author>
<name>Charlie Root</name>
<email>root@dangofactory.local</email>
</author>
<published>2026-10-05T09:10:58+00:00</published>
<link rel='alternate' type='text/html' href='https://openpgpkey.dangofactory.net/cgit/cgit.cgi/kukuri.git/commit/?id=996db6abbfd929d746444409ce77d22d4aa07827'/>
<id>996db6abbfd929d746444409ce77d22d4aa07827</id>
<content type='text'>
Pro reviewed the rebuilt menu and read the image rather than the numbers: three
quadrants had labels, the top one had none. My own pixel count agreed --
19 px of white ink in the top quadrant against 421-519 px in the others.

Cause: the label loop computed a polar offset relative to the CENTRE but applied
it with Modifier.offset inside Box(Modifier.fillMaxSize()), whose origin is the
TOP-LEFT. So every label was displaced by half a radius too little, and the top
one at y = -67 dp landed outside the disc entirely. The three that appeared to
work were only roughly right.

Fix: centre the outer Box (contentAlignment = Center) so the origin is the disc
centre, and pass the polar displacement as a relative offset. Pro's -90 deg
convention was already right -- item 0 at the top, proceeding clockwise -- and is
kept; only the origin was wrong.

Pro's other read on the rebuild: the 3 px separator reads well at this size and
does not flare, and the 22% hub is better balanced than 26%. Both kept.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Pro reviewed the rebuilt menu and read the image rather than the numbers: three
quadrants had labels, the top one had none. My own pixel count agreed --
19 px of white ink in the top quadrant against 421-519 px in the others.

Cause: the label loop computed a polar offset relative to the CENTRE but applied
it with Modifier.offset inside Box(Modifier.fillMaxSize()), whose origin is the
TOP-LEFT. So every label was displaced by half a radius too little, and the top
one at y = -67 dp landed outside the disc entirely. The three that appeared to
work were only roughly right.

Fix: centre the outer Box (contentAlignment = Center) so the origin is the disc
centre, and pass the polar displacement as a relative offset. Pro's -90 deg
convention was already right -- item 0 at the top, proceeding clockwise -- and is
kept; only the origin was wrong.

Pro's other read on the rebuild: the 3 px separator reads well at this size and
does not flare, and the 22% hub is better balanced than 26%. Both kept.
</pre>
</div>
</content>
</entry>
<entry>
<title>ci: run bundleWeb with --no-daemon</title>
<updated>2026-10-05T08:27:52+00:00</updated>
<author>
<name>Charlie Root</name>
<email>root@dangofactory.local</email>
</author>
<published>2026-10-05T08:27:52+00:00</published>
<link rel='alternate' type='text/html' href='https://openpgpkey.dangofactory.net/cgit/cgit.cgi/kukuri.git/commit/?id=6d22a9e78ed3490b0009ae1ae08683a0edb53fa7'/>
<id>6d22a9e78ed3490b0009ae1ae08683a0edb53fa7</id>
<content type='text'>
build 73 failed in bundle-web. Re-running the task by hand reproduced the
message 'Starting a Gradle Daemon, 7 busy and 1 stopped Daemons could not be
used', and ./gradlew --status showed a pool that had accumulated across the
repeated forced builds. The invocation lost that race and died; a later run with
'--stop' followed by --no-daemon completed the same task in 1m12s and produced
the zip.

--no-daemon gives the build its own JVM and tears it down afterwards, so a
wedged or crashed previous build cannot poison the next one. That matters more
than the lost daemon reuse, because bundleWeb is only ~1 min here.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
build 73 failed in bundle-web. Re-running the task by hand reproduced the
message 'Starting a Gradle Daemon, 7 busy and 1 stopped Daemons could not be
used', and ./gradlew --status showed a pool that had accumulated across the
repeated forced builds. The invocation lost that race and died; a later run with
'--stop' followed by --no-daemon completed the same task in 1m12s and produced
the zip.

--no-daemon gives the build its own JVM and tears it down afterwards, so a
wedged or crashed previous build cannot poison the next one. That matters more
than the lost daemon reuse, because bundleWeb is only ~1 min here.
</pre>
</div>
</content>
</entry>
</feed>
