# Hook Health Alert

> Periodic hook health check with Slack alerting when error rates exceed thresholds

- Skill: `omninode-ai/hook-health-alert` (Agent Skill)
- Install (CLI): `npx skillmds@latest add omninode-ai/hook-health-alert`
- Raw SKILL.md: https://api.skillmd.com/api/skills/omninode-ai/hook-health-alert/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: OmniNode-ai (https://skillmd.com/u/omninode-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/omninode-ai/hook-health-alert

---


# Hook Health Alert

## Fast Path — Node Dispatch

Dispatches to `node_platform_diagnostics` for the HOOK_HEALTH dimension:

```bash
onex run node_platform_diagnostics -- --dimensions=HOOK_HEALTH
```

With dry-run (reads cached artifacts, no live HTTP):

```bash
onex run node_platform_diagnostics -- --dimensions=HOOK_HEALTH --dry-run
```

Returns `ModelDiagnosticsResult` with `HOOK_HEALTH` dimension status (PASS/WARN/FAIL),
error rate, actionable items.

---

## Purpose

Periodic check of hook error rates. Queries the omnidash API for hook health
summary, evaluates against thresholds, and fires Slack alerts when tier 1
(interpreter) or tier 2 (degraded) errors exceed the configured threshold.

Designed as a skill-based interim solution. Will migrate to an ONEX effect node
(consuming `onex.evt.omniclaude.hook-health-error.v1` directly) when the
runtime node system is operational.

## Execution

1. Query `GET /api/hook-health/summary?window={window}m` from omnidash
   (pending: omnidash endpoint not yet implemented; uses local `hook_health_probe` until then)
2. Evaluate:
   - Tier 1 (interpreter) errors > 0: CRITICAL alert (always)
   - Tier 2 (degraded) errors > threshold: WARNING alert
   - Tier 3 (intentional): dashboard only, no alert
   - **Alert-channel liveness:** `probe_hook_health()` folds in
     `omniclaude.hooks.alert_channel.probe_alert_channel()`. A configured
     channel that does not deliver sets `alert_channel_status == "dead"`, makes
     hook health unhealthy, and is reported on the durable failure log plus a
     local (osascript / notify-send) notification — never through the dead
     channel itself. Result is cached ~1h, so the check costs one round trip per
     hour regardless of session count. Three states, not two: `live`, `dead`,
     `not_configured`.
3. If alert needed and not --dry-run:
   - Post to Slack via `SLACK_BOT_TOKEN` / `SLACK_CHANNEL_ID` — the sole
     channel (the incoming webhook is retired; no fallback)
   - Rate limit: one alert per stable alert identity per 30 minutes
   - Alert identity = `{hook_name}:{error_tier}:{error_category}`
   - Message format matches existing blocked_notifier.py Block Kit style
4. Log result to `.onex_state/hook-health/last-check.json`

## Alert Format

```
:red_circle: Hook Health CRITICAL
Interpreter errors detected (N in last 5m)

Hook: pre_tool_use_authorization_shim
Category: import_error
Message: ImportError: cannot import name 'UTC'...
Python: 3.9.6 (expected 3.12+)

Action: Rebuild plugin venv -- `cd plugins/onex/lib && uv sync`
```

## Scheduling

```
/hook-health-alert --schedule 5m
```

This creates a CronCreate job that runs the check every 5 minutes.

