GitLab Poller Integration
File: assistant/gitlab_poller.go (114 lines), assistant/heartbeat.go (Loop 15)
The GitLab integration uses a polling architecture rather than webhooks to detect code changes and trigger the Gilfoyle agent for security analysis.
Architecture Overview
flowchart LR
A[heartbeat.go<br/>Loop 15] -->|5 min interval| B[PollGitLabForChanges]
B -->|GET /api/v4/events| C[GitLab API<br/>gitlab.dlan]
C -->|JSON events| D{New Event?}
D -->|Yes| E[Queue for Batch Analysis]
D -->|No| F[Continue polling]
E -->|accumulate 24h window| G[Nightly Ritual]
G -->|TaskType: gitlab_push_notice| H[Gilfoyle Session]
GitLab Push Batching (commit 2d21c25c)
The poller now implements 24-hour batch analysis to avoid triggering Gilfoyle for every individual push. This reduces noise and allows Gilfoyle to perform a consolidated security audit.
Key Components
| Function | Purpose |
|---|---|
PollGitLabForChanges() |
Queries GitLab API for new push events |
loadGitLabState() |
Loads last event ID and pending summaries from state file |
saveGitLabState() |
Persists state to logs/gitlab_poller_state.json |
WasThereActivityInLast24Hours() |
Checks for recent activity (used by nightly ritual) |
State Tracking
{
"last_event_id": 12345,
"last_change_time": "2026-04-12T10:30:00Z",
"last_analysis_time": "2026-04-12T03:00:00Z",
"pending_summaries": ["push summary 1", "push summary 2"]
}
| Field | Purpose |
|---|---|
LastEventID |
Compared against new events to detect changes |
LastChangeTime |
Timestamp of most recent push (for 24h activity check) |
LastAnalysisTime |
When the last batch analysis was performed (cooldown tracking) |
PendingSummaries |
Queued push notifications waiting for batch analysis |
3. Heartbeat Loop 15 (heartbeat.go:461-525)
| Feature | Interval | Purpose |
|---|---|---|
| Push Detection | 5 minutes (day) | Polls for new commits |
| Adaptive Polling | 1 hour (night 20:00-08:00) | Reduces API load during quiet hours |
| Nightly Security Ritual | 03:00 daily | If activity in last 24h, Gilfoyle + SkriptKiddie audit |
Trigger Flow
On Push Detection
PollGitLabForChanges()queries/api/v4/events?action=pushed&per_page=1- If
eventID > state.LastEventID:- Updates state file
- Constructs summary:
"New push detected in Project ID X by user: "message" - Triggers Gilfoyle with
TaskType: "gitlab_push_notice"
Nightly Security Ritual (03:00)
- Checks
WasThereActivityInLast24Hours() - If true, triggers Gilfoyle with prompt:
SYSTEM TASK: Nightly Security Ritual. Code changes were detected in the last 24 hours. Coordinate with SkriptKiddie to perform a joint security audit. Identify new dependencies or modified logic and check for known vulnerabilities (CVEs) or exploit PoCs.
Configuration
| Constant | Value | Location |
|---|---|---|
GitLabAPIURL |
http://gitlab.dlan/api/v4 |
gitlab_poller.go:13 |
GitLabToken |
API token for authentication | gitlab_poller.go:14 |
GitLabStateFile |
assistant/logs/gitlab_poller_state.json |
gitlab_poller.go:15 |
Gilfoyle Agent Tools
The Gilfoyle agent has access to a dedicated GitLab monitoring tool:
| File | Purpose |
|---|---|
prompts/tools/gilfoyle/gitlab_monitor.sh |
Bash wrapper for GitLab API queries |
prompts/tools/gilfoyle/gitlab_monitor.md |
Tool definition and parameters |
Available Operations
list_projects— Projects user has access toget_project— Project details by IDlist_commits— Recent commits for a projectget_commit— Commit details with difflist_pipelines— CI/CD pipeline statushealth_check— GitLab instance health
Troubleshooting
GitLab Not Triggering
Symptom: No Gilfoyle sessions for push events.
Checks:
- State file exists? Look for
assistant/logs/gitlab_poller_state.json- If missing, first push will create it
- GitLab reachable? Test:
curl http://gitlab.dlan/api/v4/version - API token valid? Check
GitLabTokenconstant - Heartbeat running? Check logs for
[GITLAB_MONITOR]prefix
No State File
If gitlab_poller_state.json is missing:
- First poll will initialize with current event ID
- No push detected until a NEW event occurs after initialization
- This is expected behavior on fresh deployments
Why Polling Instead of Webhooks?
| Aspect | Polling | Webhooks |
|---|---|---|
| Complexity | Simple HTTP GET | Requires endpoint + signature validation |
| Reliability | Self-healing on restart | Can miss events if endpoint down |
| Firewall | Outbound only | Requires inbound port exposure |
| State | Persistent via file | Stateless (push-based) |
The polling approach was chosen for simplicity and reliability in a home-lab environment where GitLab is on an internal network.
See also: Heartbeat & Triggers, Nightly Security Audit