# github_webhooks/ — Inbound GitHub Event Receiver

See @../../CLAUDE.md for project-wide patterns.

## Architecture
Dispatcher pattern: `routes.py` receives webhooks, `dispatcher.py` routes to registered handlers. This is **inbound** (GitHub → peon), unlike `webhooks/` which is outbound (peon → external).

## Webhook Authentication
- If `GITHUB_WEBHOOK_SECRET` is set: HMAC-SHA256 signature in `X-Hub-Signature-256` is **required** (no fallback)
- Falls back to API key auth only if no webhook secret configured

## Event Handlers
- **pr_handler**: Links task.pr_url when PR branch matches task branch. Parses issue refs from PR title/body (`fixes #N`, `closes #N`, `#N`)
- **pr_risk**: Calculates risk score from lines changed, files count, and critical path hits (migrations, auth, CI, Docker). Applies GitHub label + posts risk comment
- **auto_merge**: Re-evaluates merge eligibility when feature tasks complete
- **ci_failure_handler**: Handles CI check failures
- **merge_conflict_handler**: Detects and handles merge conflicts
- **pr_review_handler / pr_reviewer**: PR review workflow

## Handler Registration
Handlers register at import time via the dispatcher. `routes.py` imports handler modules to trigger registration — if you add a new handler, import it in routes.py.

## Gotchas
- Webhook handlers use `get_pool()` from `peon_mcp.db` for direct asyncpg pool access (NOT via FastAPI dependency)
- Task linking only updates `task.pr_url` if currently empty — won't overwrite existing PR URL
- PR files fetch uses `gh api` CLI — requires gh CLI installed and authenticated on the server
- Risk score thresholds: 0=low, 1+=medium, 2+=high, 4+=critical
- Critical path patterns are regex on file paths (case-insensitive)
- Unhandled events are logged at INFO, not ERROR — no exception raised

## DB Table
`github_webhook_events`: delivery_id, event_type, action, status (dispatched/no_handler) — append-only audit trail
