Add full documentation: MkDocs setup, API reference, user guide, deployment guide
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 55s
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 55s
This commit is contained in:
259
docs/api.md
Normal file
259
docs/api.md
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
# API Reference
|
||||||
|
|
||||||
|
Base URL: `http://app-01:8080`
|
||||||
|
|
||||||
|
The Work Queue WebUI connects to the Work Queue API to display and manage work items. All endpoints return JSON.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Work Items
|
||||||
|
|
||||||
|
### GET /work
|
||||||
|
|
||||||
|
List work items with optional filters.
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `status` | `string` | Filter by status |
|
||||||
|
| `agent` | `string` | Filter by assigned agent |
|
||||||
|
| `project_id` | `uuid` | Filter by project |
|
||||||
|
| `since` | `ISO8601` | Return items created after this time |
|
||||||
|
| `type` | `string` | Filter by work item type |
|
||||||
|
|
||||||
|
**Status values:** `queued`, `dispatched`, `in_progress`, `completed`, `failed`, `blocked`, `cancelled`
|
||||||
|
|
||||||
|
**Response:** `200 OK`
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"type": "infra_setup",
|
||||||
|
"description": "Set up nginx reverse proxy",
|
||||||
|
"priority": 2,
|
||||||
|
"status": "completed",
|
||||||
|
"assigned_agent": "lennie-s",
|
||||||
|
"created_by": "marcus-a",
|
||||||
|
"created_at": "2026-04-12T00:00:00Z",
|
||||||
|
"updated_at": "2026-04-12T00:30:00Z",
|
||||||
|
"outcome": "success",
|
||||||
|
"notes": "Deployed successfully"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### POST /work
|
||||||
|
|
||||||
|
Submit a new work item.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "code_review",
|
||||||
|
"description": "Review PR #42 in work-queue-api",
|
||||||
|
"priority": 1,
|
||||||
|
"agent": "steve-w",
|
||||||
|
"project_id": "d1457588-d7ad-4bbe-a252-ffe42cb55a77",
|
||||||
|
"payload": {
|
||||||
|
"pr": 42,
|
||||||
|
"repo": "work-queue-api"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Field | Type | Required | Description |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `type` | `string` | Yes | Work category (e.g. `code_review`, `bug_fix`, `infra_setup`) |
|
||||||
|
| `description` | `string` | Yes | Human-readable task description |
|
||||||
|
| `priority` | `integer` | No | 1 (highest) to 5 (lowest), default 3 |
|
||||||
|
| `agent` | `string` | No | Agent username to assign |
|
||||||
|
| `project_id` | `uuid` | No | Associated project |
|
||||||
|
| `payload` | `object` | No | Arbitrary type-specific data |
|
||||||
|
|
||||||
|
**Response:** `201 Created`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### PATCH /work/{id}
|
||||||
|
|
||||||
|
Update a work item.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "completed",
|
||||||
|
"outcome": "success",
|
||||||
|
"notes": "All checks passed",
|
||||||
|
"agent": "lennie-s"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Field | Type | Required | Description |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `status` | `string` | No | New status |
|
||||||
|
| `outcome` | `string` | Yes | Required when status is terminal (`success`, `failed`, `cancelled`) |
|
||||||
|
| `notes` | `string` | No | Human-readable notes |
|
||||||
|
| `agent` | `string` | No | Reassign to different agent |
|
||||||
|
|
||||||
|
**Response:** `200 OK`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### GET /work/{id}
|
||||||
|
|
||||||
|
Get a single work item with dispatch history.
|
||||||
|
|
||||||
|
**Response:** `200 OK`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"type": "infra_setup",
|
||||||
|
"description": "Set up nginx reverse proxy",
|
||||||
|
"priority": 2,
|
||||||
|
"status": "completed",
|
||||||
|
"assigned_agent": "lennie-s",
|
||||||
|
"created_by": "marcus-a",
|
||||||
|
"created_at": "2026-04-12T00:00:00Z",
|
||||||
|
"updated_at": "2026-04-12T00:30:00Z",
|
||||||
|
"completed_at": "2026-04-12T00:30:00Z",
|
||||||
|
"outcome": "success",
|
||||||
|
"notes": "Deployed successfully",
|
||||||
|
"dispatch_log": [
|
||||||
|
{
|
||||||
|
"id": "dispatch-uuid",
|
||||||
|
"work_item_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"dispatched_at": "2026-04-12T00:05:00Z",
|
||||||
|
"agent": "lennie-s",
|
||||||
|
"completed_at": "2026-04-12T00:30:00Z",
|
||||||
|
"outcome": "success"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Projects
|
||||||
|
|
||||||
|
### GET /projects
|
||||||
|
|
||||||
|
List all projects.
|
||||||
|
|
||||||
|
**Response:** `200 OK`
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "d1457588-d7ad-4bbe-a252-ffe42cb55a77",
|
||||||
|
"name": "Work Queue WebUI",
|
||||||
|
"external_ref": "git.danhenry.dev/thelab/work-queue-webui",
|
||||||
|
"created_at": "2026-04-11T00:00:00Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### POST /projects
|
||||||
|
|
||||||
|
Create a new project.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "Shopping List API",
|
||||||
|
"external_ref": "git.danhenry.dev/thelab/shopping-list-api"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Field | Type | Required | Description |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `name` | `string` | Yes | Project name |
|
||||||
|
| `external_ref` | `string` | No | External identifier (repo URL, Todoist ID, etc.) |
|
||||||
|
|
||||||
|
**Response:** `201 Created`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### PATCH /projects/{id}
|
||||||
|
|
||||||
|
Update a project.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "Shopping List API (revived)",
|
||||||
|
"external_ref": "git.danhenry.dev/thelab/shopping-list-api"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:** `200 OK`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## WorkItem Shape
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `id` | `uuid` | Unique identifier |
|
||||||
|
| `type` | `string` | Work category |
|
||||||
|
| `description` | `string` | Task description |
|
||||||
|
| `priority` | `integer` | 1 (highest) to 5 (lowest) |
|
||||||
|
| `status` | `string` | Current lifecycle state |
|
||||||
|
| `assigned_agent` | `string\|null` | Agent username |
|
||||||
|
| `created_by` | `string` | Creator username |
|
||||||
|
| `created_at` | `ISO8601` | Creation timestamp |
|
||||||
|
| `updated_at` | `ISO8601` | Last update timestamp |
|
||||||
|
| `completed_at` | `ISO8601\|null` | Completion timestamp |
|
||||||
|
| `outcome` | `string\|null` | `success`, `failed`, or `cancelled` |
|
||||||
|
| `notes` | `string\|null` | Optional notes |
|
||||||
|
| `payload` | `object\|null` | Type-specific data |
|
||||||
|
| `project_id` | `uuid\|null` | Associated project |
|
||||||
|
| `dispatch_log` | `array` | Dispatch history entries |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Status Lifecycle
|
||||||
|
|
||||||
|
```
|
||||||
|
queued → dispatched → in_progress → completed
|
||||||
|
↘ blocked
|
||||||
|
↘ failed
|
||||||
|
↘ cancelled (from queued or dispatched only)
|
||||||
|
```
|
||||||
|
|
||||||
|
| Transition | From → To | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| submit | — → queued | New work item created |
|
||||||
|
| dispatch | queued → dispatched | Assigned to agent |
|
||||||
|
| pick up | dispatched → in_progress | Agent starts work |
|
||||||
|
| block | in_progress → blocked | Work stalled |
|
||||||
|
| complete | in_progress → completed | Requires `outcome: success` |
|
||||||
|
| fail | in_progress → failed | Requires `outcome: failed` |
|
||||||
|
| cancel | queued/dispatched → cancelled | Requires `outcome: cancelled` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agent Queue
|
||||||
|
|
||||||
|
### GET /work/agent/{agent}
|
||||||
|
|
||||||
|
Get all work items for a specific agent.
|
||||||
|
|
||||||
|
**Response:** `200 OK` — array of WorkItem objects
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Health
|
||||||
|
|
||||||
|
### GET /health
|
||||||
|
|
||||||
|
Returns API health status.
|
||||||
|
|
||||||
|
**Response:** `200 OK`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok"
|
||||||
|
}
|
||||||
|
```
|
||||||
121
docs/deployment.md
Normal file
121
docs/deployment.md
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# Deployment
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
|
||||||
|
The WebUI ships as a multi-stage Docker image.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.danhenry.dev/thelab/work-queue-webui.git
|
||||||
|
cd work-queue-webui
|
||||||
|
docker build -t git.danhenry.dev/thelab/work-queue-webui:latest .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
--name work-queue-webui \
|
||||||
|
-p 8081:80 \
|
||||||
|
git.danhenry.dev/thelab/work-queue-webui:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
The WebUI will be available at `http://localhost:8081`.
|
||||||
|
|
||||||
|
### Environment
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `WORK_QUEUE_API_URL` | `http://app-01:8080` | Work Queue API endpoint |
|
||||||
|
|
||||||
|
### Volumes
|
||||||
|
|
||||||
|
| Path | Description |
|
||||||
|
|---|---|
|
||||||
|
| `/app/data` | Persistent data directory |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Docker Compose
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
webui:
|
||||||
|
image: git.danhenry.dev/thelab/work-queue-webui:latest
|
||||||
|
volumes:
|
||||||
|
- ./data:/app/data
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
proxy:
|
||||||
|
image: nginx:alpine
|
||||||
|
ports:
|
||||||
|
- "8081:80"
|
||||||
|
volumes:
|
||||||
|
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
|
depends_on:
|
||||||
|
webui:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data:
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ansible
|
||||||
|
|
||||||
|
An Ansible role is available in `roles/work_queue_webui/`. See the role's `defaults/main.yml` for configuration options.
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `work_queue_webui_image_tag` | `latest` | Docker image tag |
|
||||||
|
| `work_queue_webui_proxy_port` | `8081` | External port |
|
||||||
|
| `work_queue_webui_data_path` | `.../work-queue-webui/data` | Data volume path |
|
||||||
|
|
||||||
|
### Deploy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd infrastructure/ansible
|
||||||
|
ansible-playbook -i inventory playbooks/services/work_queue_webui.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nginx Reverse Proxy
|
||||||
|
|
||||||
|
If deploying behind an existing nginx instance, proxy to the container port:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:8081;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Health Check
|
||||||
|
|
||||||
|
The WebUI exposes a basic health endpoint at `/health` (returns `{"status": "ok"}`). The container uses `wget` to verify the nginx frontend is responding.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CI Pipeline
|
||||||
|
|
||||||
|
A Gitea Actions workflow (`.gitea/workflows/docker.yml`) automatically builds and pushes the image on every push to `main`:
|
||||||
|
|
||||||
|
- **Triggers:** push to `main`
|
||||||
|
- **Platforms:** `linux/amd64`, `linux/arm64`
|
||||||
|
- **Tags:** `git.danhenry.dev/thelab/work-queue-webui:<sha>` and `:latest`
|
||||||
|
- **Registry:** Gitea container registry at `git.danhenry.dev`
|
||||||
|
|
||||||
|
Required secrets in the repo:
|
||||||
|
- `DOCKER_REGISTRY_USER` — Gitea username
|
||||||
|
- `DOCKER_REGISTRY_TOKEN` — Gitea API token
|
||||||
55
docs/guide.md
Normal file
55
docs/guide.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# User Guide
|
||||||
|
|
||||||
|
## How the Queue System Works
|
||||||
|
|
||||||
|
TheLab's work queue system dispatches tasks to autonomous agents. Each work item has a lifecycle:
|
||||||
|
|
||||||
|
```
|
||||||
|
queued → dispatched → in_progress → completed
|
||||||
|
↘ blocked
|
||||||
|
↘ failed
|
||||||
|
↘ cancelled (from queued or dispatched only)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. **Marcus** (or another human) creates a work item via the Work Queue API
|
||||||
|
2. Work items wait in `queued` until an agent is available
|
||||||
|
3. The item is `dispatched` to an agent — the agent picks it up and it becomes `in_progress`
|
||||||
|
4. On completion, the item reaches `completed` (or `failed` if something went wrong)
|
||||||
|
5. Agents can only have one `in_progress` item at a time
|
||||||
|
|
||||||
|
## Viewing the Queue
|
||||||
|
|
||||||
|
On the main dashboard you can see:
|
||||||
|
- **Queued** — work items waiting for an agent
|
||||||
|
- **In Progress** — items currently being worked on
|
||||||
|
- **Completed** — finished items with outcomes
|
||||||
|
|
||||||
|
## Work Item Fields
|
||||||
|
|
||||||
|
| Field | Description |
|
||||||
|
|---|---|
|
||||||
|
| `id` | Unique identifier (UUID) |
|
||||||
|
| `type` | Category: `code_review`, `bug_fix`, `infra_setup`, etc. |
|
||||||
|
| `description` | Human-readable task description |
|
||||||
|
| `priority` | 1 (highest) to 5 (lowest) |
|
||||||
|
| `status` | Current lifecycle state |
|
||||||
|
| `assigned_agent` | Agent currently handling the item |
|
||||||
|
| `outcome` | `success`, `failed`, or `cancelled` |
|
||||||
|
| `created_at` | ISO8601 timestamp |
|
||||||
|
| `notes` | Optional human notes |
|
||||||
|
|
||||||
|
## Agents
|
||||||
|
|
||||||
|
Agents are autonomous workers assigned to the queue. Each agent picks up dispatched items and works through them one at a time.
|
||||||
|
|
||||||
|
Current known agents:
|
||||||
|
- **lennie-s** — infrastructure and tooling tasks
|
||||||
|
- **steve-w** — general development tasks
|
||||||
|
|
||||||
|
## Projects
|
||||||
|
|
||||||
|
Work items can be grouped under projects. Projects have a name and an optional external reference (e.g., a Git repo URL or Todoist project ID).
|
||||||
|
|
||||||
|
## Priorities
|
||||||
|
|
||||||
|
Work items have priorities from 1 (highest) to 5 (lowest). Higher priority items are picked up first by agents.
|
||||||
34
docs/index.md
Normal file
34
docs/index.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Work Queue WebUI
|
||||||
|
|
||||||
|
A web interface for managing TheLab's distributed work queue system. It connects to the [Work Queue API](https://git.danhenry.dev/thelab/work-queue-api) and presents queue state in real time.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The Work Queue WebUI provides a visual interface for monitoring and managing work items dispatched to agents across TheLab's infrastructure.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Real-time queue status monitoring
|
||||||
|
- Agent activity tracking
|
||||||
|
- Work item lifecycle visibility
|
||||||
|
- Project-based work organization
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. Open the WebUI in your browser (default: `http://localhost:8081`)
|
||||||
|
2. View active work items and their current status
|
||||||
|
3. Monitor agent activity and queue depth
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The WebUI is a React frontend that communicates with the Work Queue API backend. It polls for updates and displays the current state of all queued, in-progress, and completed work items.
|
||||||
|
|
||||||
|
```
|
||||||
|
Browser → Work Queue WebUI → Work Queue API (app-01:8080) → PostgreSQL
|
||||||
|
```
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Work Queue API](https://git.danhenry.dev/thelab/work-queue-api)
|
||||||
|
- [Deployment Guide](./deployment.md)
|
||||||
|
- [API Reference](./api.md)
|
||||||
36
mkdocs.yml
Normal file
36
mkdocs.yml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
site_name: Work Queue WebUI
|
||||||
|
site_description: Web interface for TheLab Work Queue system
|
||||||
|
site_url: https://git.danhenry.dev/thelab/work-queue-webui
|
||||||
|
|
||||||
|
repo_name: thelab/work-queue-webui
|
||||||
|
repo_url: https://git.danhenry.dev/thelab/work-queue-webui
|
||||||
|
|
||||||
|
theme:
|
||||||
|
name: material
|
||||||
|
palette:
|
||||||
|
- media: "(prefers-color-scheme: light)"
|
||||||
|
primary: indigo
|
||||||
|
accent: indigo
|
||||||
|
toggle:
|
||||||
|
icon: material/brightness-7
|
||||||
|
name: Switch to dark mode
|
||||||
|
- media: "(prefers-color-scheme: dark)"
|
||||||
|
primary: indigo
|
||||||
|
accent: indigo
|
||||||
|
toggle:
|
||||||
|
icon: material/brightness-4
|
||||||
|
name: Switch to light mode
|
||||||
|
|
||||||
|
nav:
|
||||||
|
- Home: index.md
|
||||||
|
- User Guide: guide.md
|
||||||
|
- API Reference: api.md
|
||||||
|
- Deployment: deployment.md
|
||||||
|
|
||||||
|
markdown_extensions:
|
||||||
|
- pymdownx.highlight:
|
||||||
|
anchor_linenums: true
|
||||||
|
- pymdownx.superfences
|
||||||
|
- admonition
|
||||||
|
- toc:
|
||||||
|
permalink: true
|
||||||
Reference in New Issue
Block a user