AgentPool now maintains a per-agent Semaphore(1) that serializes
concurrent run() calls targeting the same Agent. This prevents
shared-state races on Agent.state (status, messages, tokenUsage)
when multiple independent tasks are assigned to the same agent.
Lock acquisition order: per-agent lock first, then pool semaphore,
so queued tasks don't waste pool slots while waiting.
Add lightweight onTrace callback to OrchestratorConfig that emits
structured span events (llm_call, tool_call, task, agent) with timing,
token usage, and runId correlation. Zero overhead when not subscribed.
Closes#18