From 44cc72fdb2f9ecd73ed772fc125ec28fe8d381a9 Mon Sep 17 00:00:00 2001 From: Lauren ten Hoor Date: Sun, 8 Feb 2026 15:30:00 +0800 Subject: [PATCH] Rewrite README with architecture docs and mermaid diagrams Co-Authored-By: Claude Opus 4.6 --- README.md | 235 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 214 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 5f16622..b672eb6 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,220 @@ # 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 -| Tool | Description | -|------|-------------| -| `task_pickup` | Pick up a task from the GitLab queue. Handles label transition, model selection, state update, and session reuse detection. | -| `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. | -| `session_health` | Detect zombie sessions, stale workers, and state mismatches. Auto-fix with `autoFix: true`. | +### `task_pickup` + +Pick up a task from the GitLab queue for a DEV or QA worker. + +**Parameters:** +- `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 ```bash -# Local development (link from extensions directory) -openclaw plugins install -l ~/.openclaw/extensions/devclaw +# Local (place in extensions directory — auto-discovered) +cp -r devclaw ~/.openclaw/extensions/ # From npm (future) openclaw plugins install @openclaw/devclaw @@ -25,7 +222,7 @@ openclaw plugins install @openclaw/devclaw ## Configuration -Optional plugin config in `openclaw.json`: +Optional config in `openclaw.json`: ```json { @@ -33,11 +230,7 @@ Optional plugin config in `openclaw.json`: "entries": { "devclaw": { "config": { - "glabPath": "/usr/local/bin/glab", - "modelSelection": { - "enabled": true, - "analyzerModel": "anthropic/claude-haiku-4-5" - } + "glabPath": "/usr/local/bin/glab" } } } @@ -45,13 +238,13 @@ Optional plugin config in `openclaw.json`: } ``` -Restrict tools to your orchestrator agent: +Restrict tools to your orchestrator agent only: ```json { "agents": { "list": [{ - "id": "henk-development", + "id": "my-orchestrator", "tools": { "allow": ["task_pickup", "task_complete", "queue_status", "session_health"] } @@ -62,10 +255,10 @@ Restrict tools to your orchestrator agent: ## Requirements -- OpenClaw >= 0.x +- [OpenClaw](https://openclaw.ai) - Node.js >= 20 -- `glab` CLI installed and authenticated -- `memory/projects.json` in the orchestrator agent's workspace +- [`glab`](https://gitlab.com/gitlab-org/cli) CLI installed and authenticated +- A `memory/projects.json` in the orchestrator agent's workspace ## License