159 lines
4.0 KiB
Markdown
159 lines
4.0 KiB
Markdown
# gh-monitor — Design Doc
|
|
|
|
**Status:** Pending Andrew's review
|
|
**Repo:** coding-with-hans-heinemann/hans-tools
|
|
**Author:** Hans Heinemann
|
|
|
|
---
|
|
|
|
## What It Does
|
|
|
|
Polls the GitHub API for activity on watched repositories and fires OpenClaw
|
|
system events to wake Hans when action is needed. Hans can then read the PR,
|
|
respond to comments, push fixes, or request changes — all without a public
|
|
webhook endpoint.
|
|
|
|
---
|
|
|
|
## Scope
|
|
|
|
Initial scope: PRs only. Issues, CI, and deployments out of scope for v1.
|
|
|
|
Events monitored:
|
|
- New review submitted (approved, changes requested, commented)
|
|
- New PR review comment posted
|
|
- New PR issue comment posted
|
|
- PR merged or closed
|
|
|
|
Events NOT monitored in v1:
|
|
- CI/check status
|
|
- Issue activity
|
|
- Dependabot alerts
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
```
|
|
cron (every 5 min)
|
|
└── gh-monitor/poll.py
|
|
├── reads config/watched.yaml (repos + filter rules)
|
|
├── reads state/last_seen.json (per-repo event cursor)
|
|
├── calls GitHub API via gh CLI (no extra credentials)
|
|
├── diffs against last_seen
|
|
├── for each new event:
|
|
│ └── fires openclaw system event (text summary)
|
|
└── writes updated last_seen.json
|
|
```
|
|
|
|
Hans receives OpenClaw system event → session wakes → Hans reads + acts.
|
|
|
|
---
|
|
|
|
## Config — watched.yaml
|
|
|
|
```yaml
|
|
repos:
|
|
- owner: coding-with-hans-heinemann
|
|
repo: the-agency
|
|
notify_on:
|
|
- review_submitted
|
|
- review_comment
|
|
- issue_comment
|
|
- pr_closed
|
|
```
|
|
|
|
Multiple repos supported. Per-repo filter rules.
|
|
|
|
---
|
|
|
|
## State — last_seen.json
|
|
|
|
Tracks the timestamp of the last processed event per repo. On each poll,
|
|
only events newer than this cursor are processed. Prevents duplicate alerts.
|
|
|
|
```json
|
|
{
|
|
"coding-with-hans-heinemann/the-agency": {
|
|
"last_event_at": "2026-03-15T17:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
On first run (no state file), cursor is set to now — no backfill of old events.
|
|
|
|
---
|
|
|
|
## Notification Format
|
|
|
|
OpenClaw system event text:
|
|
|
|
```
|
|
[gh-monitor] PR #1 "feat: Phase 2" — Andrew left a review comment:
|
|
"The escalation retry logic looks good but can you add a test for the blocked case?"
|
|
https://github.com/coding-with-hans-heinemann/the-agency/pull/1#discussion_r12345
|
|
```
|
|
|
|
One event per notification. If multiple events arrive in one poll cycle, they
|
|
fire as separate system events in sequence.
|
|
|
|
---
|
|
|
|
## GitHub API Access
|
|
|
|
Uses `gh` CLI (already installed, already authenticated as hansheinemann).
|
|
No new credentials needed. All API calls go through `gh api`.
|
|
|
|
Endpoints used:
|
|
- `GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews`
|
|
- `GET /repos/{owner}/{repo}/pulls/{pull_number}/comments`
|
|
- `GET /repos/{owner}/{repo}/issues/{pull_number}/comments`
|
|
- `GET /repos/{owner}/{repo}/pulls` (list open PRs)
|
|
|
|
Rate limit: 5,000 requests/hour for authenticated requests. At 5-min poll
|
|
intervals across a handful of repos, this is nowhere near the limit.
|
|
|
|
---
|
|
|
|
## Cron Schedule
|
|
|
|
Every 5 minutes via OpenClaw cron:
|
|
```
|
|
{ "kind": "every", "everyMs": 300000 }
|
|
```
|
|
|
|
Payload: systemEvent → injects wake text into main session.
|
|
|
|
Can be paused/resumed via OpenClaw cron management without touching the code.
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
- GitHub API errors: log to `state/errors.log`, skip that repo for this cycle
|
|
- Malformed API response: log and skip
|
|
- Missing state file: create fresh with cursor = now
|
|
- `gh` CLI not found: exit with error message
|
|
|
|
Errors do NOT fire system events (avoid alert fatigue from transient API blips).
|
|
If errors persist for >3 consecutive cycles, fire one alert to Hans.
|
|
|
|
---
|
|
|
|
## Security
|
|
|
|
- No webhook endpoint — nothing exposed to the internet
|
|
- No secrets stored in the repo — `gh` CLI handles auth via its own keychain
|
|
- State files excluded from git via .gitignore
|
|
- Read-only GitHub API access needed (no write scopes required for polling)
|
|
|
|
---
|
|
|
|
## Out of Scope (v1)
|
|
|
|
- Filtering by PR author
|
|
- Filtering by comment author
|
|
- Digest mode (batch multiple events into one notification)
|
|
- Slack/email delivery (OpenClaw system event only)
|
|
- CI/check status monitoring
|