# rig-conductor event types — full schema

> All events accepted by `POST /api/events` on the rig-conductor cluster-internal API.
> Source of truth: `dashecorp/rig-conductor/src/ConductorE.Core/UseCases/SubmitEvent.cs` (MapToEvent switch).
> This file is compiled from `facts/events.yaml` in rig-docs.

## `ISSUE_APPROVED`

Issue is ready for dispatch.

**Fields:** `{ Repo, IssueNumber, Title, Body, Priority, Milestone?, DependsOn[] }`

## `ISSUE_ASSIGNED`

Dispatch picked an agent.

**Fields:** `{ Repo, IssueNumber, AgentId, Attempt }`

## `ISSUE_UNASSIGNED`

Agent released (timeout, explicit release, escalation).

**Fields:** `{ Repo, IssueNumber, AgentId, Reason }`

## `WORK_STARTED`

Agent began coding.

**Fields:** `{ Repo, IssueNumber, AgentId, Branch }`

## `BRANCH_CREATED`

Feature branch pushed.

**Fields:** `{ Repo, IssueNumber, AgentId, Branch }`

## `PR_CREATED`

PR opened from agent branch.

**Fields:** `{ Repo, IssueNumber, AgentId, PrNumber, PrUrl, Branch }`

## `CI_PASSED`

Per-PR CI green.

**Fields:** `{ Repo, IssueNumber, PrNumber }`

## `CI_FAILED`

Per-PR CI red.

**Fields:** `{ Repo, IssueNumber, PrNumber, FailedChecks[], Logs? }`

## `REVIEW_ASSIGNED`

Review-E or human picked up the PR.

**Fields:** `{ Repo, IssueNumber, PrNumber, AgentId }`

## `REVIEW_PASSED`

Review approval.

**Fields:** `{ Repo, IssueNumber, PrNumber }`

## `REVIEW_DISPUTED`

Review requested changes.

**Fields:** `{ Repo, IssueNumber, PrNumber, Attempt }`

## `HUMAN_GATE_TRIGGERED`

A PR requires human decision before auto-merge.

**Fields:** `{ Repo, IssueNumber, PrNumber, Reason }`

## `HUMAN_GATE_REMINDER`

Gate still pending after N minutes.

**Fields:** `{ Repo, IssueNumber, PrNumber, Attempt }`

## `MERGED`

PR merged.

**Fields:** `{ Repo, IssueNumber, PrNumber, MergeSha }`

## `MERGE_GATE_WAITING`

Merge queue is waiting (checks, reviews, labels).

**Fields:** `{ Repo, IssueNumber, PrNumber, MissingConditions[] }`

## `MERGE_GATE_MERGED`

Merge queue completed.

**Fields:** `{ Repo, IssueNumber, PrNumber }`

## `MERGE_GATE_TIMEOUT`

Merge queue timed out.

**Fields:** `{ Repo, IssueNumber, PrNumber, Reason }`

## `MAIN_CI_STARTED`

Main-branch CI kicked off post-merge.

**Fields:** `{ Repo, IssueNumber, Logs? }`

## `MAIN_CI_PASSED`

**Fields:** `{ Repo, IssueNumber, Logs? }`

## `MAIN_CI_FAILED`

**Fields:** `{ Repo, IssueNumber, PrNumber?, Reason }`

## `DEPLOYED_STAGING`

**Fields:** `{ Repo, IssueNumber, Reason }`

## `DEPLOYED_PRODUCTION`

**Fields:** `{ Repo, IssueNumber, Reason }`

## `SMOKE_PASSED`

**Fields:** `{ Repo, IssueNumber }`

## `SMOKE_FAILED`

**Fields:** `{ Repo, IssueNumber, Reason, Attempt, MaxAttempts }`

## `BUILD_FAILED`

**Fields:** `{ Repo, IssueNumber, PrNumber?, Reason }`

## `VERIFIED`

Post-deploy verification passed.

**Fields:** `{ Repo, IssueNumber }`

## `ISSUE_DONE`

Terminal state for a work item.

**Fields:** `{ Repo, IssueNumber, DurationMinutes }`

## `ESCALATED`

Escalated to human intervention.

**Fields:** `{ Repo, IssueNumber, Reason, Attempts }`

## `MILESTONE_COMPLETE`

**Fields:** `{ Milestone, IssueNumber }`

## `DUPLICATE_PR_CLOSED`

**Fields:** `{ Repo, PrNumber, ClosedPrNumber, IssueNumber }`

## `PR_OPENED`

Human or bot PR opened directly (no parent issue). Used for infra/tooling PRs.

**Fields:** `{ Repo, PrNumber, PrUrl, Title }`

## `PR_REVIEW_ASSIGNED`

**Fields:** `{ Repo, PrNumber, AgentId }`

## `PR_REVIEW_APPROVED`

**Fields:** `{ Repo, PrNumber, AgentId, MergeSha }`

## `PR_REVIEW_REJECTED`

**Fields:** `{ Repo, PrNumber, AgentId, Reason }`

## `AGENT_STARTED`

Pod started; first signal rig-conductor sees from a new instance.

**Fields:** `{ AgentId }`

## `HEARTBEAT`

Liveness + current-work snapshot. StaleHeartbeatService detects missing pods.

**Fields:** `{ AgentId, Status, CurrentIssue?, CurrentRepo?, ActiveProvider?, AvailableProviders[]?, Providers[]?, Integrations[]? }`

## `AGENT_STUCK`

Agent gave up or hit a loop. Surfaced for escalation.

**Fields:** `{ AgentId, Repo, IssueNumber, Reason, Attempt }`

## `CLI_STARTED`

Agent started a Claude Code / Codex / Gemini CLI run.

**Fields:** `{ Repo, IssueNumber, AgentId, Model, IsIteration }`

## `CLI_PROGRESS`

Periodic CLI progress ping.

**Fields:** `{ Repo, IssueNumber, AgentId, DurationMs, Logs? }`

## `CLI_COMPLETED`

CLI session finished. Aggregates cost and turn count.

**Fields:** `{ Repo, IssueNumber, AgentId, CostUsd, Turns, DurationMs, PrNumber?, Logs? }`

## `TOKEN_USAGE`

Per-category cost emission (work vs thinking vs caching etc). Backed by
a TokenUsageProjection in rig-conductor — per-agent / per-task cost is
queryable today. Category values seen: "work", others TBD from source.

**Fields:** `{ AgentId, Repo, IssueNumber, Model, InputTokens, OutputTokens, CostUsd, Category }`

## `TOOL_USED`

Single tool invocation trace. TargetPreview is truncated to 120 chars.

**Fields:** `{ Repo, IssueNumber, AgentId, ToolName, Turn, TargetPreview?, DurationMs, IsMcp }`

## `MEMORY_WRITE`

**Fields:** `{ Repo, IssueNumber, AgentId, Scope, Kind, MemoryId, Tokens }`

## `MEMORY_READ`

**Fields:** `{ Repo, IssueNumber, AgentId, Query, Hits, TokensLoaded }`

## `MEMORY_HIT_USED`

**Fields:** `{ MemoryId, AgentId, UsedInOutput }`

## Notes

- Source of truth: dashecorp/rig-conductor/src/ConductorE.Core/UseCases/SubmitEvent.cs — the MapToEvent switch. Keep this file in sync when the switch changes.
- The mt_events table in rig-conductor's Postgres is the Marten event-store backing.
- Payload shape is close to OTel GenAI attribute conventions so the planned OTel migration is near-lossless. See observability whitepaper.
- Projections live in ConductorE.Core (search: `class *Projection`). Confirmed live: TokenUsageProjection (per-agent/task cost). Others exist — see implementation-status.md.
