# NimsForest Issue Runbook

## Overview

NimsForest Issue is an issue tracking service for the NimsForest ecosystem. It provides a public web form for reporting issues, an API for programmatic access, and an admin dashboard for triage and management.

## Infrastructure

- **Server**: issues.nimsforest.nimsforest.com
- **Host**: land (46.225.164.179), Docker container, port 8085
- **Image**: registry.nimsforest.com/nimsforestissue:v0.2.0
- **Config**: /opt/nimsforestissue/config.yaml (mounted to ~/.nimsforestissue/config.yaml)
- **Data**: /opt/nimsforestissue/data/ (mounted to /data)
- **NATS**: nats://nimsforest.nimsforest.com:4222

### Environment Variables

| Variable | Purpose | Required |
|----------|---------|----------|
| `NATS_URL` | Wind (NATS) connection for events + chat widget | Optional (events/chat disabled without it) |

## Health Check

```bash
curl https://issues.nimsforest.nimsforest.com/api/v1/health
```

## API Endpoints

| Method | Path | Auth | Description |
|--------|------|------|-------------|
| GET /api/v1/health | none | Health check |
| POST /api/v1/issues | Bearer (api) | Create issue |
| GET /api/v1/issues | Bearer (api) | List issues (query: status, category, project, active_only, stage) |
| GET /api/v1/issues/{id} | Bearer (api) | Get single issue |
| PATCH /api/v1/issues/{id} | Bearer (api) | Update issue |
| DELETE /api/v1/issues/{id} | Bearer (api) | Delete issue |
| PUT /api/v1/issues/{id}/plan | Bearer (api) | Update plan text and status |
| POST /api/v1/issues/{id}/comments | Bearer (api) | Add comment |
| POST /api/v1/issues/{id}/nim-actions | Bearer (api) | Record agent action |
| GET /api/v1/stats | Bearer (api) | Aggregate statistics |
| GET /api/v1/reports/quality | Bearer (api) | Quality review report |
| GET /api/v1/runbook | none | This runbook (markdown) |

## Issue Lifecycle

### Status

| Status | Meaning | Set by |
|--------|---------|--------|
| `open` | New issue, not yet groomed | Issue creation |
| `groomed` | Triaged and ready for planning | groom-issues skill |
| `planning` | Agent is writing an implementation plan | plan-issues skill |
| `proposed` | Plan submitted for human review | plan-issues skill |
| `accepted` | Plan approved, ready for implementation | Human via UI |
| `rejected` | Plan rejected | Human via UI |
| `implementing` | Agent is actively implementing the plan | next-plan skill |
| `done` | Implementation is complete | next-plan skill |
| `closed` | Issue closed manually | Human via UI |

### Stage (shorthand filter)

| Stage | Resolves to | Used by |
|-------|------------|---------|
| `groomable` | `open` | groom-issues |
| `plannable` | `groomed` | plan-issues |
| `implementable` | `accepted` | next-plan |
| `active` | all except `done`, `closed` | dashboards |

## Wind Events

Issue events are published to Wind (NATS) as leaves:

- `issue.created` — new issue filed
- `issue.updated` — status/priority/plan changed
- `issue.commented` — comment added

## Chat Widget

Embeddable nim chat on admin issue detail pages. Uses `github.com/nimsforest/nimschatwidget` package.

### Requirements

- NATS connected (Wind)
- Forest pipeline running (river → tree → nim → agentclaudecode)

### How it works

1. Admin opens `/admin/issues/{id}` → floating green chat button appears (bottom-right)
2. User clicks button → slide panel with nim selector dropdown
3. User sends message → Source publishes to `river.chat.widget` via JetStream
4. Forest tree (`message-chat`) watches `river.chat.>`, routes to target nim with `reply_subject=song.nimschatwidget.{sessionID}`
5. Nim responds via agentclaudecode → response published to `song.nimschatwidget.{sessionID}`
6. Songbird catches response → delivers via SSE → appears in chat panel

### Standalone service

nimschatwidget also runs as a standalone container on land at `chatwidget.nimsforest.com` (:8096). Other services can embed the widget via script tag without importing the Go package:

```html
<script>
window.nimschatwidgetConfig = {
    baseURL: 'https://chatwidget.nimsforest.com',
    sessionId: 'unique-session-id',
    context: 'context for the nim',
    defaultNim: 'nimble'
};
</script>
<script src="https://chatwidget.nimsforest.com/widget"></script>
```

### Endpoints (behind admin auth at /admin/chat/)

| Method | Path | Description |
|--------|------|-------------|
| POST /admin/chat/send | Send message to nim |
| GET /admin/chat/nims | List available nims |
| GET /admin/chat/events?session={id} | SSE stream for responses |
| GET /admin/chat/widget | Serve widget JS |

### Troubleshooting

**Chat button not visible**: Check that NATS is connected. Verify logs show "Chat widget enabled (publishing to river.chat.widget)".

**"Nim is thinking..." never resolves**: Check agentclaudecode logs on land. Most common cause: expired Claude API credentials. Fix: copy fresh `~/.claude/.credentials.json` from neoremote to `/opt/agentclaudecode/credentials.json` on land and restart the container.

**Response not arriving**: If response goes to `song.webchat.*` instead of `song.nimschatwidget.*`, the `message.lua` tree script needs updating. The tree must respect `reply_subject` from the incoming message.

## Authentication

Two separate tokens configured in `config.yaml`:

- **admin_token**: Used for web dashboard login (session cookie)
- **api_token**: Used as Bearer token for API access
