After landing separate-crud-from-invocation §10 (commit c58f90e16), the
desktop app stopped discovering the LAN krill server. Beacons appeared
fine from the server’s side (wlan0 joined to 239.255.0.69, UDP 45317
bound) but the desktop kernel never joined the multicast group — the
desktop’s beacon listener simply never started.
Symptom-wise: the server appeared nowhere in the desktop’s swarm, even
though both were on the same /24. The same regression silently
disabled stored-host auto-reconnect on app launch.
The client bootstrap is structured as:
1
2
3
4
5
6
7
App.kt LaunchedEffect
→ nodeManager.execute(client)
→ ClientNodeManager.execute() stamps the local Client node's state
→ DefaultNodeObserver collector calls collectedNode.type.emit(node)
→ KrillApp.Client.emit → ClientClientProcessor.post(node)
→ if state matches the arm, call process(node)
→ start beacon discovery, auto-reconnect stored servers, init LocalSwarmHost
Phase 4 §10 changed ClientNodeManager.execute() so the optimistic local
state stamp goes to NodeState.PROCESSING (the new universal-invocation
pulse) instead of NodeState.EXECUTED (the legacy structural-push
stamp). The author updated UniversalAppNodeProcessor.post to handle
both — its comment specifically calls out “UAP renders both
identically so no UX regression”.
But two other consumers of the same emit chain were missed:
ClientClientProcessor.post — only handled NodeState.EXECUTED.ClientServerProcessor.post — same.With the stamp now PROCESSING, both fell through to their else -> {}
arm. process(node) was never invoked, so
beaconSupervisor.startBeaconProcess() and the stored-host loop never
ran. The kernel never got a joinGroup(239.255.0.69, eno1) call.
Group NodeState.PROCESSING with NodeState.EXECUTED in both
processors’ post() arms, exactly the way UniversalAppNodeProcessor
already does. Two-file, schema-compatible change.
ClientNodeManager.execute() (or any emit-driving function)
changes the state it stamps, audit every processor.post
implementation that observes a single state value. Search:
grep -rn 'NodeState\.\(EXECUTED\|PROCESSING\)' shared/.../krillapp.
The §10 audit only checked state = NodeState.EXECUTED call sites,
not the consumer when arms.clientProcessor.process(client)
directly, the same way the server runs CrudLifecycleTask from
ServerBoss instead of through KrillApp.emit. That’s the Phase 4
architectural alignment; tracked as a follow-up.ClientClientProcessor.post(NodeState.PROCESSING) → calls
beaconSupervisor.startBeaconProcess() would be valuable.