Verification pool sessions share one executor, violating the "separate sessions" invariant
Severity: High
File: src/cain_agent/multi_agent/orchestration.py:91-93
build_orchestration creates multiple ExecutorVerificationSession instances but they all wrap the same validation_executor object:
sessions = tuple(
ExecutorVerificationSession(f"verify-{index}", validation_executor)
for index in range(session_count)
)
The architecture requires independent verification sessions for majority-vote integrity (FindingsPipeline.__init__ explicitly rejects pool sessions that share the discovery executor). Yet all three verification sessions share a single SDKExecutor, meaning they share the same hooks, allowed_tools, and — critically — the same underlying Claude Agent SDK session when resume_session_id is set. The pool then runs asyncio.run() per call inside ThreadPoolExecutor threads, but all threads drive the same executor state.
Why it matters
If one verification thread mutates executor state (e.g., appending a hook, advancing a session), the other threads observe the mutation. A failure in one session could corrupt the shared state for all three, turning an independent majority vote into a correlated single-point result — undermining the anti-self-certification design.
Verification pool sessions share one executor, violating the "separate sessions" invariant
Severity: High
File:
src/cain_agent/multi_agent/orchestration.py:91-93build_orchestrationcreates multipleExecutorVerificationSessioninstances but they all wrap the samevalidation_executorobject:The architecture requires independent verification sessions for majority-vote integrity (
FindingsPipeline.__init__explicitly rejects pool sessions that share the discovery executor). Yet all three verification sessions share a singleSDKExecutor, meaning they share the samehooks,allowed_tools, and — critically — the same underlying Claude Agent SDK session whenresume_session_idis set. The pool then runsasyncio.run()per call insideThreadPoolExecutorthreads, but all threads drive the same executor state.Why it matters
If one verification thread mutates executor state (e.g., appending a hook, advancing a session), the other threads observe the mutation. A failure in one session could corrupt the shared state for all three, turning an independent majority vote into a correlated single-point result — undermining the anti-self-certification design.