Add a typed lifecycle hook system inspired by OpenClaw, designed for
PicoClaw's ultra-lightweight philosophy. Provides 8 interception points
around the agent loop for observability, content filtering, and guardrails.
Two execution patterns:
- Void hooks (concurrent): message_received, after_tool_call,
llm_input, llm_output, session_start, session_end
- Modifying hooks (sequential by priority, with cancel):
message_sending, before_tool_call
Key design choices:
- Zero-cost when unused: all triggers check len==0 and return immediately
- Copy-on-write registration: insertSorted allocates new backing array
so concurrent readers never race with writers
- Panic recovery in all handler dispatch paths
- sendOutbound wrapper returns cancel status to callers
- MessageTool callback rewired via SetHooks for content filtering
15 tests covering execution, priority ordering, cancel semantics,
concurrency (barrier-based), panic recovery, and error swallowing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>