Commit Graph

6 Commits

Author SHA1 Message Date
Christian Stewart 302148523f fix(hub): wake owners when supervised processes exit
Publish terminal daemon completions to the session that started the
process so idle agents can resume without polling hub status.

Persist every unacknowledged generation with a stable completion ID and
immutable snapshot. Replay the collection after reconnect or broker
recovery, and clear each event only after the owning client acknowledges
it.

Signed-off-by: Christian Stewart <christian@aperture.us>
2026-08-03 01:31:39 -07:00
can1357 04fad069aa Merge PR #6853: fix(launch): treat restarting daemon as settled in broker #settle (@roboomp) 2026-07-28 10:59:35 +02:00
can1357 30512418c1 test(launch): restore kernel comm after in-process broker test
startDaemonBrokerFromEnvironment now sets the kernel-visible name via
prctl, so restoring only process.title left the test runner's
/proc/self/comm as "omp daemon brok" for the rest of the Linux run.
2026-07-28 10:58:59 +02:00
roboomp a0f353c561 fix(launch): rechecked daemon state after output read
A recovered detached daemon has no in-memory process handle, so two
concurrent refreshes can both enter settle for the same dead pid. The
initial guard runs before detached output is read; both continuations
could therefore pass it and then double-settle the generation.

Recheck generation and settled states after the awaited output read,
and cover concurrent refreshes against a recovered daemon. Without the
post-read guard the regression test observes restartCount 2 instead of
1.

Fixes #6852
2026-07-28 04:16:24 +00:00
roboomp 9d6eac0cb8 fix(launch): treat restarting daemon as settled in broker #settle
A detached restart:"always" daemon that exits quickly parks in the
`restarting` state with process/pid cleared and a restartTimer armed.
Every subsequent op ran #refreshDetached, which only skips terminal
states, so it fell through to a re-entrant #settle. #settle's guard
only checked generation and terminalState, so re-entry proceeded:
restartCount++ and record.restartTimer was overwritten without clearing
the previously armed timer, orphaning it.

Consequences: stop cleared only the last timer, so an orphaned timer
later fired #launch (resetting stopRequested) and resurrected the
daemon; and restartCount phantom-inflated on every list/logs poll.

Add `restarting` to #settle's entry guard: it is a settled state
(child exited, relaunch timer pending) and no legitimate caller settles
while in it. Closes both the timer leak and the count inflation.

Fixes #6852
2026-07-28 04:04:52 +00:00
can1357 d16a251777 chore: reorg tests 2026-07-27 16:43:53 +02:00