Repository navigation
Reload a daemon still running as launchd Adaptive instead of deferring forever #1351
Copy link
Copy link
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
kcap 1.3.0-beta.6, macOS 26.6, 24 cores / 64 GB, 11 hosted agents.
Symptom
The desktop app stays responsive, but typing into and redrawing a hosted agent's terminal gets slow whenever the agents work, and worse the more agents there are. With the agents idle it is fine.
Cause
The daemon is still loaded as ProcessType=Adaptive:
launchctl print gui/501/io.kurrent.kcap.daemon.alexeyshowsspawn type = adaptive (6), jetsam priority 40.ps -M <daemon pid>shows PRI 4 on every thread. All 12 children (11claude, 1codex) run at PRI 4, and so do theVBCSCompiler(7.3 GB and 4.4 GB) andcscprocesses their builds spawn. The app's main thread runs at 46; a Claude started from a terminal at 31.- The agents' parallel builds pushed the machine into swap: 23 GB in the compressor, 13 of 14 GB swap used, load 129 with 59% CPU idle. The background band is throttled on CPU and I/O, so the daemon and the agents on the keystroke path wait on page-ins while the foreground app does not.
Ruled out: the app keeps one workspace alive (a hidden agent has no attach, chat poll or PR poll), PTY reads run on dedicated threads (#1024), both sinks are non-blocking, and the cloud mirror's desyncs today were all reconnects.
Why the migration in #1269 does not reach this host
- The deferral has no end.
RefreshUnitreloads only after the daemon accepts an idle-only restart. A host that always has agents running never idles, so the plist stays Adaptive for good, and nothing inkcap daemon statusor the app says so. - The upgrade is a byte-exact match.
UpgradeProcessTypelooks for the writer's single line<key>ProcessType</key><string>Adaptive</string>. The plist on this machine is in Apple's canonical layout (tab-indented, one element per line, keys sorted), which is what anything that went throughplutil,PlistBuddyordefaultsends up as. The upgrade returns null,DeclaresStandardProcessTypeis false, and the refresh reports Unchanged. - There is no in-process escape.
taskpolicy -B -p <pid>exits 0 and changes nothing, on the daemon or on a child. The background state is derived from the spawn type and inherited as derived state, so the daemon cannot lift it at startup. Only a launchd reload applies the new type. kcap daemon restartdoes not apply it either. KeepAlive relaunches from the definition launchd cached at load.
Proposal
kcap daemon status,kcap doctorand the desktop app's daemon row report when the loaded job runs as Adaptive (LaunchdUnit.LoadedAsAdaptivealready reads it) and say that a reload is needed.kcap daemon restartand the app's restart action, when the loaded spawn type is Adaptive or the plist on disk differs from the loaded definition, run the bootout-while-exiting + bootstrap sequence from [AI-3419] Run the macOS daemon as a Standard launchd process #1269 instead of letting KeepAlive relaunch the cached definition.--when-idledoes the same once idle.- The migration parses the plist and rewrites
ProcessTypewhatever its layout, instead of matching one line. - The reload ends every hosted agent, and uncommitted work in their worktrees is deleted with them, so the command must say so and refuse while agents run unless forced.
Workaround used here: edit the plist to Standard by hand, then launchctl bootout and bootstrap the job once the agents are done.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
linear-code commentedon Oct 7, 2026
AI-3551
Merge main into daemon-adaptive-reload (#1351)
Skip the rollback when the label is loaded in the band after a bootst…
Charge no lock wait to the forced refresh and refuse it off launchd (#…
Check the null spawn type through the JSON element helper (#1351)
Gate the reload, order status reads and name an unloaded label (#1351)
Note the rollback, budget, gate and unloaded-label rules in the spec (#…
Check the reload consent against the attach generation after the gate (…