Rewrite README with architecture docs and mermaid diagrams
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
235
README.md
235
README.md
@@ -1,23 +1,220 @@
|
|||||||
# DevClaw
|
# DevClaw
|
||||||
|
|
||||||
Multi-project dev/qa pipeline orchestration plugin for [OpenClaw](https://openclaw.ai).
|
An [OpenClaw](https://openclaw.ai) plugin that turns a single orchestrator agent into a development team lead managing multiple projects simultaneously.
|
||||||
|
|
||||||
Replaces manual orchestration steps with atomic agent tools. Instead of 10+ error-prone manual steps per task, the agent calls a single tool that handles GitLab labels, state management, model selection, and audit logging atomically.
|
## The idea
|
||||||
|
|
||||||
|
You have one AI agent — the orchestrator. It lives in a Telegram group per project. Each project has its own GitLab repo, its own task backlog, and its own pair of sub-agent workers: a **DEV** that writes code and a **QA** that reviews it. The orchestrator decides what to work on, spawns the right worker with the right model, and moves tasks through the pipeline — across all projects at once.
|
||||||
|
|
||||||
|
DevClaw gives the orchestrator four tools that replace hundreds of lines of manual orchestration logic. Instead of the agent following a 10-step checklist (fetch issue, check labels, pick model, check for existing session, transition label, update state, log audit event...), it calls `task_pickup` and the plugin handles everything atomically.
|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TB
|
||||||
|
subgraph "Orchestrator Agent"
|
||||||
|
O[Orchestrator]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "Project A — Telegram Group"
|
||||||
|
direction TB
|
||||||
|
A_GL[GitLab Issues]
|
||||||
|
A_DEV[DEV sub-agent]
|
||||||
|
A_QA[QA sub-agent]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "Project B — Telegram Group"
|
||||||
|
direction TB
|
||||||
|
B_GL[GitLab Issues]
|
||||||
|
B_DEV[DEV sub-agent]
|
||||||
|
B_QA[QA sub-agent]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "Project C — Telegram Group"
|
||||||
|
direction TB
|
||||||
|
C_GL[GitLab Issues]
|
||||||
|
C_DEV[DEV sub-agent]
|
||||||
|
C_QA[QA sub-agent]
|
||||||
|
end
|
||||||
|
|
||||||
|
O -->|task_pickup / task_complete| A_GL
|
||||||
|
O -->|task_pickup / task_complete| B_GL
|
||||||
|
O -->|task_pickup / task_complete| C_GL
|
||||||
|
O -->|sessions_spawn / sessions_send| A_DEV
|
||||||
|
O -->|sessions_spawn / sessions_send| A_QA
|
||||||
|
O -->|sessions_spawn / sessions_send| B_DEV
|
||||||
|
O -->|sessions_spawn / sessions_send| B_QA
|
||||||
|
O -->|sessions_spawn / sessions_send| C_DEV
|
||||||
|
O -->|sessions_spawn / sessions_send| C_QA
|
||||||
|
```
|
||||||
|
|
||||||
|
Each project is identified by its **Telegram group ID** — the orchestrator receives messages from project groups and knows which project context it's operating in.
|
||||||
|
|
||||||
|
## Task lifecycle
|
||||||
|
|
||||||
|
Every task (GitLab issue) moves through a fixed pipeline of label states. DevClaw tools handle every transition atomically — label change, state update, audit log, and session management in a single call.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
stateDiagram-v2
|
||||||
|
[*] --> Planning
|
||||||
|
Planning --> ToDo: Ready for development
|
||||||
|
|
||||||
|
ToDo --> Doing: task_pickup (DEV)
|
||||||
|
Doing --> ToTest: task_complete (DEV done)
|
||||||
|
|
||||||
|
ToTest --> Testing: task_pickup (QA)
|
||||||
|
Testing --> Done: task_complete (QA pass)
|
||||||
|
Testing --> ToImprove: task_complete (QA fail)
|
||||||
|
Testing --> Refining: task_complete (QA refine)
|
||||||
|
|
||||||
|
ToImprove --> Doing: task_pickup (DEV fix)
|
||||||
|
Refining --> ToDo: Human decision
|
||||||
|
|
||||||
|
Done --> [*]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Session reuse
|
||||||
|
|
||||||
|
Sub-agent sessions are expensive to start — each new spawn requires the agent to read the full codebase (~50K tokens). DevClaw preserves session IDs across task completions. When a DEV finishes task A and picks up task B on the same project, the plugin detects the existing session and returns `"sessionAction": "send"` instead of `"spawn"` — the orchestrator sends the new task to the running session instead of creating a new one.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant O as Orchestrator
|
||||||
|
participant DC as DevClaw Plugin
|
||||||
|
participant GL as GitLab
|
||||||
|
participant S as Sub-agent Session
|
||||||
|
|
||||||
|
O->>DC: task_pickup({ issueId: 42, role: "dev" })
|
||||||
|
DC->>GL: Fetch issue, verify label
|
||||||
|
DC->>DC: Select model (haiku/sonnet/opus)
|
||||||
|
DC->>DC: Check existing session
|
||||||
|
DC->>GL: Transition label (To Do → Doing)
|
||||||
|
DC->>DC: Update projects.json, write audit log
|
||||||
|
DC-->>O: { sessionAction: "send", sessionId: "...", model: "sonnet" }
|
||||||
|
O->>S: sessions_send (task description)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Model selection
|
||||||
|
|
||||||
|
The plugin selects the cheapest model that can handle each task:
|
||||||
|
|
||||||
|
| Complexity | Model | When |
|
||||||
|
|------------|-------|------|
|
||||||
|
| Simple | Haiku | Typos, CSS, renames, copy changes |
|
||||||
|
| Standard | Sonnet | Features, bug fixes, multi-file changes |
|
||||||
|
| Complex | Opus | Architecture, migrations, security, system-wide refactoring |
|
||||||
|
| QA | Grok | All QA tasks (code review, test validation) |
|
||||||
|
|
||||||
|
Selection is based on issue title/description keywords. The orchestrator can override with `modelOverride` on any `task_pickup` call.
|
||||||
|
|
||||||
|
## State management
|
||||||
|
|
||||||
|
All project state lives in a single `memory/projects.json` file in the orchestrator's workspace, keyed by Telegram group ID:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"-5044836116": {
|
||||||
|
"name": "trainerswap",
|
||||||
|
"repo": "~/git/trainerswap",
|
||||||
|
"groupName": "Henk - Trainerswap",
|
||||||
|
"baseBranch": "development",
|
||||||
|
"dev": {
|
||||||
|
"active": false,
|
||||||
|
"sessionId": "agent:henk-dev:subagent:a9e4d078-...",
|
||||||
|
"issueId": null,
|
||||||
|
"model": "haiku"
|
||||||
|
},
|
||||||
|
"qa": {
|
||||||
|
"active": false,
|
||||||
|
"sessionId": "agent:henk-dev:subagent:18707821-...",
|
||||||
|
"issueId": null,
|
||||||
|
"model": "grok"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Key design decision: when a worker completes a task, `sessionId` and `model` are **preserved** (only `active` and `issueId` are cleared). This enables session reuse on the next pickup.
|
||||||
|
|
||||||
|
All writes go through atomic temp-file-then-rename to prevent corruption.
|
||||||
|
|
||||||
## Tools
|
## Tools
|
||||||
|
|
||||||
| Tool | Description |
|
### `task_pickup`
|
||||||
|------|-------------|
|
|
||||||
| `task_pickup` | Pick up a task from the GitLab queue. Handles label transition, model selection, state update, and session reuse detection. |
|
Pick up a task from the GitLab queue for a DEV or QA worker.
|
||||||
| `task_complete` | Complete a task (DEV done, QA pass/fail/refine). Handles label transition, issue close/reopen, and fix cycle preparation. |
|
|
||||||
| `queue_status` | Show task queue counts and worker status across all projects. |
|
**Parameters:**
|
||||||
| `session_health` | Detect zombie sessions, stale workers, and state mismatches. Auto-fix with `autoFix: true`. |
|
- `issueId` (number, required) — GitLab issue ID
|
||||||
|
- `role` ("dev" | "qa", required) — Worker role
|
||||||
|
- `projectGroupId` (string, required) — Telegram group ID
|
||||||
|
- `modelOverride` (string, optional) — Force a specific model
|
||||||
|
|
||||||
|
**What it does atomically:**
|
||||||
|
1. Resolves project from `projects.json`
|
||||||
|
2. Validates no active worker for this role
|
||||||
|
3. Fetches issue from GitLab, verifies correct label state
|
||||||
|
4. Selects model based on task complexity
|
||||||
|
5. Detects session reuse opportunity
|
||||||
|
6. Transitions GitLab label (e.g. `To Do` → `Doing`)
|
||||||
|
7. Updates `projects.json` state
|
||||||
|
8. Writes audit log entry
|
||||||
|
9. Returns structured instructions for the orchestrator
|
||||||
|
|
||||||
|
### `task_complete`
|
||||||
|
|
||||||
|
Complete a task with one of four results.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `role` ("dev" | "qa", required)
|
||||||
|
- `result` ("done" | "pass" | "fail" | "refine", required)
|
||||||
|
- `projectGroupId` (string, required)
|
||||||
|
- `summary` (string, optional) — For the Telegram announcement
|
||||||
|
|
||||||
|
**Results:**
|
||||||
|
- **DEV "done"** — Pulls latest code, moves label `Doing` → `To Test`, deactivates worker
|
||||||
|
- **QA "pass"** — Moves label `Testing` → `Done`, closes issue, deactivates worker
|
||||||
|
- **QA "fail"** — Moves label `Testing` → `To Improve`, reopens issue, prepares DEV fix cycle with model selection
|
||||||
|
- **QA "refine"** — Moves label `Testing` → `Refining`, awaits human decision
|
||||||
|
|
||||||
|
### `queue_status`
|
||||||
|
|
||||||
|
Returns task queue counts and worker status across all projects (or a specific one).
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `projectGroupId` (string, optional) — Omit for all projects
|
||||||
|
|
||||||
|
### `session_health`
|
||||||
|
|
||||||
|
Detects and optionally fixes state inconsistencies.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `autoFix` (boolean, optional) — Auto-fix zombies and stale state
|
||||||
|
- `activeSessions` (string[], optional) — Live session IDs from `sessions_list`
|
||||||
|
|
||||||
|
**Checks:**
|
||||||
|
- Active worker with no session ID (critical)
|
||||||
|
- Active worker whose session is dead — zombie (critical)
|
||||||
|
- Worker active for >2 hours (warning)
|
||||||
|
- Inactive worker with lingering issue ID (warning)
|
||||||
|
|
||||||
|
## Audit logging
|
||||||
|
|
||||||
|
Every tool call automatically appends an NDJSON entry to `memory/audit.log`. No manual logging required from the orchestrator agent.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"ts":"2026-02-08T10:30:00Z","event":"task_pickup","project":"trainerswap","issue":42,"role":"dev","model":"sonnet","sessionAction":"send"}
|
||||||
|
{"ts":"2026-02-08T10:30:01Z","event":"model_selection","issue":42,"role":"dev","selected":"sonnet","reason":"Standard dev task"}
|
||||||
|
{"ts":"2026-02-08T10:45:00Z","event":"task_complete","project":"trainerswap","issue":42,"role":"dev","result":"done"}
|
||||||
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Local development (link from extensions directory)
|
# Local (place in extensions directory — auto-discovered)
|
||||||
openclaw plugins install -l ~/.openclaw/extensions/devclaw
|
cp -r devclaw ~/.openclaw/extensions/
|
||||||
|
|
||||||
# From npm (future)
|
# From npm (future)
|
||||||
openclaw plugins install @openclaw/devclaw
|
openclaw plugins install @openclaw/devclaw
|
||||||
@@ -25,7 +222,7 @@ openclaw plugins install @openclaw/devclaw
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Optional plugin config in `openclaw.json`:
|
Optional config in `openclaw.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -33,11 +230,7 @@ Optional plugin config in `openclaw.json`:
|
|||||||
"entries": {
|
"entries": {
|
||||||
"devclaw": {
|
"devclaw": {
|
||||||
"config": {
|
"config": {
|
||||||
"glabPath": "/usr/local/bin/glab",
|
"glabPath": "/usr/local/bin/glab"
|
||||||
"modelSelection": {
|
|
||||||
"enabled": true,
|
|
||||||
"analyzerModel": "anthropic/claude-haiku-4-5"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,13 +238,13 @@ Optional plugin config in `openclaw.json`:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Restrict tools to your orchestrator agent:
|
Restrict tools to your orchestrator agent only:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"agents": {
|
"agents": {
|
||||||
"list": [{
|
"list": [{
|
||||||
"id": "henk-development",
|
"id": "my-orchestrator",
|
||||||
"tools": {
|
"tools": {
|
||||||
"allow": ["task_pickup", "task_complete", "queue_status", "session_health"]
|
"allow": ["task_pickup", "task_complete", "queue_status", "session_health"]
|
||||||
}
|
}
|
||||||
@@ -62,10 +255,10 @@ Restrict tools to your orchestrator agent:
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- OpenClaw >= 0.x
|
- [OpenClaw](https://openclaw.ai)
|
||||||
- Node.js >= 20
|
- Node.js >= 20
|
||||||
- `glab` CLI installed and authenticated
|
- [`glab`](https://gitlab.com/gitlab-org/cli) CLI installed and authenticated
|
||||||
- `memory/projects.json` in the orchestrator agent's workspace
|
- A `memory/projects.json` in the orchestrator agent's workspace
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user