Symptom

Kraken nightly scan (issue #804) flagged LambdaProcessor as a potential propagation-context gap. Investigation confirmed: a lambda node invoked via an observer chain (or via RESET) allocated a fresh epoch instead of inheriting the parent’s, and suppressPublish=true was silently lost, allowing the lambda result to fan out to observers when it should not.

Root cause

LambdaProcessor.process() delegated async work with a bare scope.launch {} rather than scope.launchProcessing(nodeManager, node). The PropagationContextElement installed by ServerNodeManager.invoke() (which pins propagationContextTL on the coroutine’s thread for the duration of the processor run) is not inherited by sibling coroutines launched from the injected application scope. The inner LambdaPythonExecutor.start() eventually calls nodeManager.succeeded()publish(), which reads propagationContextTL.get() directly. With context lost, publish() called nextEpoch() for a fresh epoch (breaking D7 cycle-dedupe) and used DEFAULT_HOP_TTL (breaking D11 hop-count), and the suppressPublish=true guard in update() was never seen (breaking D6 terminal-RESET semantics).

This is the same class of bug as #699 (fixed in PR #700), which introduced launchProcessing for ServerComputeProcessor, ServerCalculationProcessor, ServerLLMProcessor, ServerSMTPProcessor, and ServerTaskListProcessor. LambdaProcessor was not in that sweep because it delegates to a LambdaExecutor abstraction and the context loss was one call level deeper than a direct scope.launch in process().

Fix

Prevention