Emoji Status Vocabulary and Format Specification
Context
Section titled “Context”The #tasks Discord channel posts a message when each issue opens. Today that message is static text — operators cannot tell at a glance whether an issue is queued, in-flight, blocked, merged, or failed without clicking into the thread or GitHub.
This decision locks the emoji vocabulary and message format so that the renderer service (rc#437), Conductor wiring (rc#438), and rollout (rc#439) all share a single agreed schema. Nothing in this document is implementation guidance — it is the canonical spec.
See rc#433 for the full epic.
Decision
Section titled “Decision”1. Primary state → emoji mapping
Section titled “1. Primary state → emoji mapping”The leftmost emoji on the parent message encodes the current lifecycle state. One emoji per state; no compound primary.
| State | Emoji | Rationale |
|---|---|---|
queued | ⏳ | Hourglass — waiting for dispatch |
assigned | 👋 | Claimed but not started |
in_progress | 🛠️ | Tools — Dev-E working |
in_review | 👀 | Eyes — Review-E reading |
changes_requested | ✏️ | Edit — back to Dev-E |
ready_to_merge | 🎯 | Target — final gate |
in_deploy | 🚀 | Rocket — Flux rolling (rc#413) |
deployed | 📦 | Package — code live |
done | ✅ | Check — all green |
failed | ❌ | X — terminal failure |
cancelled | 🚫 | Forbidden — manual cancel |
stuck | 🐌 | Snail — stuck-watcher fired (rc#232) |
escalated | 🚨 | Siren — needs human (rc#258) |
Rules:
- The primary emoji is always the leftmost token on line 1.
- It changes on every lifecycle state transition.
stuckoverridesin_progress(see edge cases §4).escalatedoverrides all other non-terminal states.
2. Tier overlay
Section titled “2. Tier overlay”The second line begins with the tier emoji from Planner output (rc#157).
| Tier | Emoji | Meaning |
|---|---|---|
| T1 reversible | 🟢 | Low blast radius |
| T2 schema | 🟡 | Needs care |
| T3 irreversible | 🔴 | Human approval required |
The tier is set at issue-open time and does not change during the lifecycle.
3. Modifier emojis
Section titled “3. Modifier emojis”Modifiers are appended to the status row (line 2), after the tier, separated by ·. Multiple modifiers compose in the order listed.
| Signal | Emoji | Trigger condition |
|---|---|---|
| Cost > $2 | 💰 | Budget concern (rc#316) |
| Cost > $5 | 🔥 | Hot — investigate |
| Turns > 50 | ⏱️ | Time concern |
| COI / scope mismatch | ⚠️ | Scope-match gate fired (rar#155) |
| Reverted | ↩️ | Revert-retro fired (rc#392) |
Notes:
- 💰 and 🔥 are mutually exclusive; 🔥 supersedes 💰 when cost > $5.
- Modifiers accumulate; they are not cleared when state changes.
- The status row must not exceed 300 characters (see §5 message length).
4. Parent message format template
Section titled “4. Parent message format template”The Conductor edits the same Discord message in-place on every state transition. The format is:
{primary_emoji} 📋 **{repo}#{number}** — {title}{tier_emoji} {tier_label} · {state_label}{agent_clause}{metric_clause}{modifier_clause}{issue_url}Where:
| Placeholder | Description |
|---|---|
{primary_emoji} | State emoji from §1 |
{repo} | Short repo name (e.g. rig-conductor) |
{number} | Issue number |
{title} | Issue title, truncated at 80 chars with … |
{tier_emoji} | Tier emoji from §2 |
{tier_label} | T1, T2, or T3 |
{state_label} | Human-readable state slug (e.g. in_progress, done) |
{agent_clause} | · {agentId} when an agent is assigned; omitted otherwise |
{metric_clause} | · turn {n} · ${cost} when in-flight; · {duration} · ${total_cost} when terminal |
{modifier_clause} | Zero or more · {emoji} pairs from §3, appended in table order |
{issue_url} | Full GitHub issue URL |
Concrete examples:
Created (queued):
⏳ 📋 **rig-conductor#420** — feat: extend lifecycle with deploy-confirm🟡 T2 · queuedhttps://github.com/dashecorp/rig-conductor/issues/420In progress:
🛠️ 📋 **rig-conductor#420** — feat: extend lifecycle with deploy-confirm🟡 T2 · in_progress · dev-e-dotnet · turn 47 · $0.42https://github.com/dashecorp/rig-conductor/issues/420Done:
✅ 📋 **rig-conductor#420** — feat: extend lifecycle with deploy-confirm🟡 T2 · done · 24m · $1.18 · PR #421 mergedhttps://github.com/dashecorp/rig-conductor/issues/420Failed:
❌ 📋 **rig-conductor#420** — feat: extend lifecycle with deploy-confirm🟡 T2 · failed · dev-e-dotnet timeout @ turn 105https://github.com/dashecorp/rig-conductor/issues/420Stuck with modifiers:
🐌 📋 **rig-conductor#420** — feat: extend lifecycle with deploy-confirm🟡 T2 · in_progress · stuck-watcher (3rd occurrence) · ⏱️ 🔥https://github.com/dashecorp/rig-conductor/issues/4205. Edge case rules
Section titled “5. Edge case rules”5.1 Concurrent state transitions
Section titled “5.1 Concurrent state transitions”Discord rate-limit is 5 edits / 5 s per channel. When multiple state transitions arrive within a 1-second window for the same issue, the renderer coalesces them and emits only the latest state. Implementation must use a per-issue debounce window of 1 second.
5.2 Stuck overrides in_progress
Section titled “5.2 Stuck overrides in_progress”When the stuck-watcher fires (rc#232) while an issue is in_progress:
- Set primary emoji to 🐌 (overrides 🛠️).
- State label remains
in_progresswith annotation· stuck-watcher ({n}th occurrence). - If work resumes (
cli_progressevent fires within 10 minutes of stuck detection), revert to 🛠️ and remove the annotation. - A third occurrence with no resume within 10 minutes escalates to 🚨 via the rebut-cap (rc#258).
5.3 Escalated overrides all
Section titled “5.3 Escalated overrides all”When escalated state is reached via rc#258:
- Set primary emoji to 🚨 regardless of prior state.
- This is a non-terminal state — the issue may return to
in_progressif a human intervenes and re-dispatches.
5.4 Message not found / channel deleted
Section titled “5.4 Message not found / channel deleted”If the Conductor cannot locate the original Discord message (deleted, channel gone, etc.):
- Fall back to posting a new message in the channel.
- Log a
WARNwith the original message ID and reason. - Continue tracking the new message ID for future edits.
5.5 Message length budget
Section titled “5.5 Message length budget”Discord max is 2000 characters. The three-line template must fit within:
| Line | Max chars | Overflow behaviour |
|---|---|---|
| Line 1 (emoji + title) | ~120 | Truncate title at 80 chars with … |
| Line 2 (status row) | 300 | Drop modifier emojis right-to-left until it fits |
| Line 3 (URL) | ~80 | Never truncated |
If line 2 still exceeds 300 chars after dropping all modifiers, truncate {metric_clause} to · ${cost} only.
5.6 Cross-repo dispatched issues
Section titled “5.6 Cross-repo dispatched issues”Use the canonical thread of the originating issue (per rc#425 unified-thread fix). State emoji follows the upstream issue, not chore PRs or sub-issues.
5.7 Multi-turn rebut cycle
Section titled “5.7 Multi-turn rebut cycle”During iterative changes_requested → in_progress cycles:
- Stay on the active primary emoji (✏️ or 🛠️) as appropriate.
- Do not flip to ❌ until a terminal failure event is received.
- Do not flip to 🚨 until rc#258 rebut-cap fires.
5.8 Idempotency
Section titled “5.8 Idempotency”Before making a Discord API edit, compare the new rendered string against the last-known rendered state. If identical, skip the edit. This prevents needless API calls and rate-limit consumption on duplicate events.
5.9 Backfill
Section titled “5.9 Backfill”This feature applies forward only. Existing #tasks posts (pre-feature) remain as static text. No migration or backfill is required or desired.
Status
Section titled “Status”Accepted. This vocabulary and format are the canonical schema for all downstream implementation work in the emoji-status epic (rc#433).
References
Section titled “References”| Ref | Description |
|---|---|
| rc#433 | Epic: emoji status indicators |
| rc#413 | deploy-confirm lifecycle (🚀 / 📦 states) |
| rc#316 | Cost budget (💰 / 🔥 modifiers) |
| rc#392 | Revert-retro (↩️ modifier) |
| rc#232 | Stuck-watcher (🐌 state) |
| rc#258 | Rebut-cap (🚨 escalation) |
| rc#425 | Unified per-issue Discord thread |
| rar#155 | Review-E scope-match gate (⚠️ modifier) |
| rc#157 | Planner tier output |