# Discord Bot Startup Guide

## Overview

The GooseFactory Discord Bot bridges factory events into Discord with rich embeds and interactive buttons. It provides real-time notifications, approval workflows, and pipeline management via slash commands.

---

## 📋 Command Inventory (7 Commands)

All commands are under the `/factory` command group:

### 1. `/factory status`
- **Purpose:** Quick dashboard summary of the factory
- **Returns:** Embed showing pipelines, tasks, agents, and SLA status
- **Options:** None
- **Use case:** Get a quick overview of factory health

### 2. `/factory pipelines`
- **Purpose:** List active pipelines or get details for a specific pipeline
- **Options:**
  - `status` (optional): Filter by status (active/paused/completed/failed)
  - `pipeline_id` (optional): Get detailed view of a specific pipeline
- **Returns:** List embed or detailed pipeline status with progress bar
- **Use case:** Monitor pipeline status and progression through stages

### 3. `/factory queue`
- **Purpose:** Show pending decision queue
- **Options:**
  - `priority` (optional): Filter by priority (critical/high/medium/low)
  - `batch` (optional): Show as batch review grouped by risk
- **Returns:** List of pending tasks with SLA info, or batch review embed
- **Features:** Includes "Approve Low-Risk" batch button
- **Use case:** Review pending approvals and identify urgent items

### 4. `/factory approve`
- **Purpose:** Approve a pending task
- **Options:**
  - `task_id` (required): The task ID to approve
  - `notes` (optional): Approval notes
- **Returns:** Updated approval embed
- **Use case:** Fast-track approval from command line

### 5. `/factory reject`
- **Purpose:** Reject a pending task with a reason
- **Options:**
  - `task_id` (required): The task ID to reject
  - `reason` (required): Why this is being rejected
  - `changes` (optional): Requested changes (comma-separated)
- **Returns:** Updated rejection embed
- **Use case:** Block task progression with actionable feedback

### 6. `/factory deploy`
- **Purpose:** Deploy a pipeline to staging or production
- **Options:**
  - `pipeline_id` (required): The pipeline to deploy
  - `target` (required): staging or production
  - `dry_run` (optional): Preview without actually deploying
- **Returns:** Deploy status embed with URL or error details
- **Use case:** Trigger deployments from Discord

### 7. `/factory blockers`
- **Purpose:** Show what's stuck and why
- **Options:**
  - `pipeline_id` (optional): Filter to a specific pipeline
- **Returns:** List of blockers with suggested actions
- **Use case:** Identify and resolve pipeline bottlenecks

---

## 🎨 Embed Types (5)

### 1. **Deploy Notification** (`embeds/deploy-notification.ts`)
- **Channel:** `#factory-deploys`
- **Triggers:** Deploy started/succeeded/failed
- **Features:**
  - Status-specific colors and emojis
  - Deploy URL for successful deploys
  - Error logs for failed deploys
  - Retry button on failures
- **Data:** pipeline, target, version, status, url, error, triggeredBy

### 2. **SLA Warning** (`embeds/sla-warning.ts`)
- **Channel:** `#factory-alerts`
- **Triggers:** Task approaching SLA deadline or breached
- **Features:**
  - @here for warnings, @everyone for breaches
  - Escalation level tracking
  - Time remaining/overdue display
  - Quick approve/reject buttons
- **Variants:** Standard warning, critical escalation (T+SLA+2h)
- **Data:** taskId, title, pipelineId, slaDeadline, minutesRemaining, escalationLevel

### 3. **Batch Review** (`embeds/batch-review.ts`)
- **Channel:** `#factory-tasks`
- **Triggers:** Multiple tasks ready for review
- **Features:**
  - Groups tasks by risk level (low/medium/high)
  - Shows test results and coverage
  - Batch approve buttons
  - Select menu for individual review
- **Risk classification:** Based on priority, SLA, test results, coverage, diff size
- **Data:** Array of {task, riskLevel}

### 4. **Pipeline Status** (`embeds/pipeline-status.ts`)
- **Channel:** Responses to `/factory pipelines`
- **Features:**
  - Progress bar showing stage completion
  - Stage duration tracking
  - SLA deadline countdown
  - Status-specific colors
- **Variants:** List view (compact), detail view (full status)
- **Also includes:** Stage transition notifications for `#factory-feed`

### 5. **Approval Request** (`embeds/approval-request.ts`)
- **Channel:** `#factory-tasks`
- **Triggers:** New task requires human approval
- **Features:**
  - Test results, coverage, and diff summary
  - Priority indicators
  - SLA countdown
  - Interactive buttons: Approve/Reject/Details/Defer
  - Details button creates a thread for discussion
- **State transitions:**
  - Approved: Green embed with approver
  - Rejected: Red embed with reason
  - Deferred: Gray embed (escalates internally)

---

## 🎮 Interaction Types

### Buttons (`interactions/button-handler.ts`)

| Button ID Pattern | Action | Handler |
|-------------------|--------|---------|
| `approve:{taskId}` | Approve task | Finds approval, calls API, updates embed |
| `reject:{taskId}` | Show rejection modal | Opens modal for reason + changes |
| `details:{taskId}` | Show task details | Creates thread or ephemeral reply |
| `defer:{taskId}` | Defer decision | Escalates task internally |
| `batch-approve-low:{ids}` | Batch approve low-risk | Calls bulk API |
| `batch-approve-all:{ids}` | Batch approve all | Calls bulk API |
| `batch-review-individual` | Switch to individual mode | Info message |
| `deploy-retry:{pipelineId}:{target}` | Retry failed deploy | Calls deploy API |

### Modals (`interactions/modal-handler.ts`)

| Modal ID Pattern | Inputs | Handler |
|------------------|--------|---------|
| `reject-modal:{taskId}` | reason (required, paragraph)<br>requested_changes (optional, paragraph) | Rejects approval via API, updates embed |

### Select Menus (`interactions/select-handler.ts`)

| Select Menu ID | Options | Handler |
|----------------|---------|---------|
| `batch-select-review` | Task list (up to 25) | Loads selected task as ephemeral approval request |

---

## 🔌 Factory API Calls

All API calls go through `api-client.ts` → Factory API at `FACTORY_API_URL` (default: `https://api.goosefactory.dev/v1`)

### Endpoints Used:

| Method | Endpoint | Used By | Purpose |
|--------|----------|---------|---------|
| GET | `/dashboard/summary` | `/factory status` | Dashboard overview |
| GET | `/pipelines` | `/factory pipelines` | List pipelines |
| GET | `/pipelines/{id}` | `/factory pipelines` | Get pipeline details |
| GET | `/pipelines/{id}/stages` | `/factory pipelines` | Get stage progress |
| GET | `/tasks` | `/factory queue` | List pending tasks |
| GET | `/tasks/{id}` | Button handlers | Get task details |
| GET | `/tasks/stats` | `/factory queue` | Task statistics |
| POST | `/tasks/bulk` | Batch approve | Bulk approve/reject |
| GET | `/approvals` | Button handlers | Find approval for task |
| GET | `/approvals/{id}` | Button handlers | Get approval details |
| POST | `/approvals/{id}/approve` | Approve handlers | Approve a task |
| POST | `/approvals/{id}/reject` | Reject handlers | Reject a task |
| POST | `/approvals/{id}/escalate` | Defer handler | Escalate/defer a task |
| POST | `/deploy` | `/factory deploy` | Trigger deploy |
| GET | `/blockers` | `/factory blockers` | Get blockers |

**API Headers:**
- `X-API-Key: {FACTORY_API_KEY}`
- `X-Request-Id: {uuid}`
- `Content-Type: application/json`

---

## 🔐 Environment Variables

Create a `.env` file in `packages/discord-bot/` with:

```bash
# Discord Bot Configuration
DISCORD_TOKEN=                     # Bot token from Discord Developer Portal
DISCORD_CLIENT_ID=                 # Application ID (for registering commands)
DISCORD_GUILD_ID=                  # Your Discord server ID (for guild commands)

# Channel Routing
FACTORY_FEED_CHANNEL_ID=           # General activity feed (#factory-feed)
FACTORY_TASKS_CHANNEL_ID=          # Approval requests (#factory-tasks)
FACTORY_DEPLOYS_CHANNEL_ID=        # Deploy notifications (#factory-deploys)
FACTORY_ALERTS_CHANNEL_ID=         # SLA warnings and critical alerts (#factory-alerts)

# Factory API
FACTORY_API_URL=https://api.goosefactory.dev/v1  # Factory API base URL
FACTORY_WS_URL=wss://api.goosefactory.dev/v1/ws  # WebSocket for real-time events
FACTORY_API_KEY=                   # API key for Factory authentication

# Optional
LOG_LEVEL=info                     # debug | info | warn | error
NODE_ENV=development               # development | production | test
```

**Required variables:**
- All `DISCORD_*` variables
- All channel IDs
- `FACTORY_API_KEY`

**How to get these values:**

1. **Discord Bot Setup:**
   - Go to [Discord Developer Portal](https://discord.com/developers/applications)
   - Create new application or select existing
   - Go to Bot section → Reset Token → Copy `DISCORD_TOKEN`
   - Copy Application ID → `DISCORD_CLIENT_ID`
   - Enable Message Content Intent, Server Members Intent

2. **Guild & Channel IDs:**
   - Enable Developer Mode in Discord (User Settings → Advanced)
   - Right-click server → Copy ID → `DISCORD_GUILD_ID`
   - Right-click each channel → Copy ID → Channel ID variables

3. **Factory API Key:**
   - Contact Factory admin or generate via Factory dashboard
   - If self-hosting, check Factory API `.env` for key generation

---

## 🚀 Prerequisites

Before starting the bot:

### 1. **Services Must Be Running**
   - ✅ Factory API (at `FACTORY_API_URL`)
   - ✅ Factory WebSocket (at `FACTORY_WS_URL`) — for real-time events
   - ✅ PostgreSQL (if Factory API depends on it)

### 2. **Discord Bot Setup**
   - ✅ Bot created in Discord Developer Portal
   - ✅ Bot added to your Discord server with permissions:
     - Send Messages
     - Embed Links
     - Read Message History
     - Use Slash Commands
     - Create Public Threads
     - Manage Threads
   - ✅ Intents enabled: Message Content, Server Members

### 3. **Dependencies Installed**
```bash
cd packages/discord-bot
npm install
```

### 4. **Missing Files to Create**

The bot is missing these core files (they need to be created):

#### `src/index.ts` (Main bot entry point)
- Load Discord.js client
- Register command handlers
- Register interaction handlers
- Connect to Factory WebSocket
- Listen for events and route to correct channels

#### `src/register-commands.ts` (Command registration script)
- Load all command definitions
- Use Discord REST API to register commands
- Should support both guild and global registration

#### `src/logger.ts` (Logging utility)
- Simple console logger or winston/pino
- Used throughout codebase (`import { logger } from './logger.js'`)

#### `src/bridge/` (WebSocket event bridge)
- Connect to Factory WebSocket
- Listen for factory events (deploy, stage change, task created, SLA warning)
- Route events to correct Discord channels using embeds
- Should be empty currently — needs implementation

#### `.env.example` (Template for environment variables)
- Copy of env vars with placeholder values
- Documents what each variable is for

---

## 📝 How to Register Slash Commands

**Important:** Commands must be registered before the bot can respond to them.

### Option 1: Guild Commands (Fast, recommended for dev)

```bash
cd packages/discord-bot
npm run register-commands
```

This registers commands to your specific Discord server (via `DISCORD_GUILD_ID`). Commands appear **instantly**.

### Option 2: Global Commands (Slow, for production)

Modify `register-commands.ts` to use global endpoint instead of guild endpoint. Commands take **up to 1 hour** to propagate.

**Note:** You need to create `src/register-commands.ts` first. It should:

```typescript
import { REST } from '@discordjs/rest';
import { Routes } from 'discord-api-types/v10';
import { SlashCommandBuilder } from 'discord.js';
import { config } from './config.js';

// Import all command modules
import * as status from './commands/status.js';
import * as pipelines from './commands/pipelines.js';
// ... import all 7 commands

const commands = [
  new SlashCommandBuilder()
    .setName('factory')
    .setDescription('GooseFactory pipeline management')
    .addSubcommand(status.data)
    .addSubcommand(pipelines.data)
    // ... add all subcommands
].map(cmd => cmd.toJSON());

const rest = new REST({ version: '10' }).setToken(config.DISCORD_TOKEN);

// Register commands
await rest.put(
  Routes.applicationGuildCommands(config.DISCORD_CLIENT_ID, config.DISCORD_GUILD_ID),
  { body: commands }
);

console.log('✅ Commands registered!');
```

---

## ▶️ How to Start the Bot

### Development Mode (with hot reload)

```bash
cd packages/discord-bot
npm run dev
```

This uses `tsx watch` to automatically reload on file changes.

### Production Mode

```bash
cd packages/discord-bot
npm run build    # Compile TypeScript
npm start        # Run compiled JavaScript
```

### Expected Startup Output

```
[INFO] Loading configuration...
[INFO] Environment validated
[INFO] Connecting to Discord...
[INFO] Logged in as GooseFactory#1234
[INFO] Connecting to Factory WebSocket at wss://api.goosefactory.dev/v1/ws
[INFO] Factory bridge connected
[INFO] Bot is ready!
```

**If startup fails:**
- Check `.env` for missing/invalid values
- Verify Factory API is reachable
- Check bot token is valid
- Ensure bot is added to Discord server

---

## 🧪 How to Test Each Command

Once bot is running and commands are registered:

### 1. Test `/factory status`
```
/factory status
```
**Expected:** Dashboard embed with pipeline counts, task stats, agent status, SLA info.

### 2. Test `/factory pipelines`
```
/factory pipelines
/factory pipelines status:active
/factory pipelines pipeline_id:pipe_abc123
```
**Expected:** List of pipelines or detailed pipeline view with progress bar.

### 3. Test `/factory queue`
```
/factory queue
/factory queue priority:high
/factory queue batch:true
```
**Expected:** List of pending tasks or batch review embed with approve buttons.

### 4. Test `/factory approve`
```
/factory approve task_id:task_xyz789 notes:"LGTM!"
```
**Expected:** Task embed updated to "Approved" state, green color.

### 5. Test `/factory reject`
```
/factory reject task_id:task_xyz789 reason:"Tests are failing" changes:"Fix unit tests, Add error handling"
```
**Expected:** Task embed updated to "Rejected" state, red color, reason displayed.

### 6. Test `/factory deploy`
```
/factory deploy pipeline_id:pipe_abc123 target:staging dry_run:true
/factory deploy pipeline_id:pipe_abc123 target:staging
```
**Expected:** Deploy status embed posted to `#factory-deploys` channel.

### 7. Test `/factory blockers`
```
/factory blockers
/factory blockers pipeline_id:pipe_abc123
```
**Expected:** List of blockers with suggested actions, or "No blockers" message.

### 8. Test Button Interactions

Find an approval request message in `#factory-tasks` and click:
- **Approve button:** Should update embed to green "Approved" state
- **Reject button:** Should open modal for rejection reason
- **Details button:** Should create thread with full task details
- **Defer button:** Should escalate task internally

### 9. Test Modal Submission

Click Reject button → Fill in modal → Submit
**Expected:** Embed updates to red "Rejected" state with reason displayed.

### 10. Test Batch Actions

Use `/factory queue batch:true` → Click "Approve All Low-Risk"
**Expected:** Multiple tasks approved at once, summary message displayed.

---

## 🛠️ Troubleshooting

### Commands not appearing
- Run `npm run register-commands` again
- Check `DISCORD_GUILD_ID` is correct
- Wait up to 1 hour if using global commands
- Try kicking and re-inviting the bot

### "Missing Access" errors
- Check bot has correct permissions in channel
- Verify channel IDs in `.env` are correct
- Ensure bot role is above any channel-specific permission overrides

### API errors
- Verify `FACTORY_API_URL` is correct and reachable
- Check `FACTORY_API_KEY` is valid
- Look for 401/403 errors in logs (auth issue)
- Check Factory API logs for request details

### WebSocket disconnects
- Factory WebSocket may require reconnection logic
- Check `FACTORY_WS_URL` is correct
- Verify API key works for WebSocket auth

### Buttons not working
- Check interaction handlers are registered in `index.ts`
- Verify message was sent by bot (can't interact with old messages)
- Check bot has "Use Application Commands" permission

---

## 📦 Missing Implementation

The following features are **designed but not yet implemented:**

1. **WebSocket Bridge** (`src/bridge/`)
   - Should listen to Factory events and post to Discord
   - Events to handle:
     - `task.created` → Post approval request to `#factory-tasks`
     - `task.sla_warning` → Post SLA warning to `#factory-alerts`
     - `task.sla_breach` → Post critical alert to `#factory-alerts`
     - `deploy.started` → Post to `#factory-deploys`
     - `deploy.completed` → Update deploy message
     - `pipeline.stage_changed` → Post to `#factory-feed`

2. **Core Bot Files**
   - `src/index.ts` — Main entry point
   - `src/logger.ts` — Logging utility
   - `src/register-commands.ts` — Command registration script

3. **Configuration**
   - `.env.example` — Template for environment setup

---

## 📊 Summary

### ✅ What's Complete
- 7 slash commands fully implemented
- 5 embed types with rich formatting
- 3 interaction handlers (buttons, modals, selects)
- API client with full Factory API coverage
- Type-safe config with Zod validation

### ⏳ What's Needed to Go Live
1. Create `src/index.ts` (bot entry point)
2. Create `src/register-commands.ts` (command registration)
3. Create `src/logger.ts` (logging)
4. Implement `src/bridge/` (WebSocket event bridge)
5. Create `.env.example` template
6. Get Discord bot token from Developer Portal
7. Get Factory API key
8. Set up 4 Discord channels and get their IDs
9. Register commands: `npm run register-commands`
10. Start bot: `npm run dev`

### 🎯 Next Steps
1. **Create missing infrastructure files** (index, logger, register-commands)
2. **Set up Discord bot** (get token, add to server, get channel IDs)
3. **Get Factory API access** (API key, verify endpoints)
4. **Register commands** and test each one
5. **Implement WebSocket bridge** for real-time events
6. **Deploy to production** (PM2, Docker, or systemd service)

---

**Total Implementation Status:**
- Commands: 7/7 ✅
- Embeds: 5/5 ✅
- Interactions: 3/3 ✅
- API Integration: 100% ✅
- Infrastructure: 0% ⏳
- Event Bridge: 0% ⏳
