The hook system — register handlers for lifecycle events, fire them in-process, or drive them from config
Failure modes
| Symptom | Cause | Fix | Severity |
|---|---|---|---|
handler() got an unexpected keyword argument |
handler written as def handler(context) |
context is unpacked as kwargs — use def handler(**context) |
high |
RuntimeWarning: coroutine 'fire' was never awaited |
fire/execute called without await |
use fire_sync, or await the async ones |
high |
| Hook never fires | wrong HookEvent, or a matcher excludes the context |
check the event; inspect get_matching_hooks(event, context) |
medium |
ValidationError building a HookDefinition |
timeout outside 1–300, or missing command |
supply a valid command and timeout |
medium |
Risk areas
- Handlers take kwargs.
def handler(**context), notdef handler(context). fireandexecuteare async;fire_syncis sync.- Priority + matcher decide what runs. A
matchercan exclude a handler even for the right event.
Diagnosis order
- Did it fire?
registry.get_matching_hooks(event, context). - Handler signature —
**context? - Async-not-awaited? Use
fire_syncorawait. - For config hooks,
HookConfig.get_hooks_for_event(event).