@laurentenhoor/devclaw 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +406 -0
  3. package/dist/index.d.ts +88 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +107 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/audit.d.ts +2 -0
  8. package/dist/lib/audit.d.ts.map +1 -0
  9. package/dist/lib/audit.js +42 -0
  10. package/dist/lib/audit.js.map +1 -0
  11. package/dist/lib/binding-manager.d.ts +35 -0
  12. package/dist/lib/binding-manager.d.ts.map +1 -0
  13. package/dist/lib/binding-manager.js +88 -0
  14. package/dist/lib/binding-manager.js.map +1 -0
  15. package/dist/lib/cli.d.ts +12 -0
  16. package/dist/lib/cli.d.ts.map +1 -0
  17. package/dist/lib/cli.js +69 -0
  18. package/dist/lib/cli.js.map +1 -0
  19. package/dist/lib/dispatch.d.ts +58 -0
  20. package/dist/lib/dispatch.d.ts.map +1 -0
  21. package/dist/lib/dispatch.js +163 -0
  22. package/dist/lib/dispatch.js.map +1 -0
  23. package/dist/lib/model-selector.d.ts +21 -0
  24. package/dist/lib/model-selector.d.ts.map +1 -0
  25. package/dist/lib/model-selector.js +74 -0
  26. package/dist/lib/model-selector.js.map +1 -0
  27. package/dist/lib/notify.d.ts +54 -0
  28. package/dist/lib/notify.d.ts.map +1 -0
  29. package/dist/lib/notify.js +143 -0
  30. package/dist/lib/notify.js.map +1 -0
  31. package/dist/lib/onboarding.d.ts +5 -0
  32. package/dist/lib/onboarding.d.ts.map +1 -0
  33. package/dist/lib/onboarding.js +124 -0
  34. package/dist/lib/onboarding.js.map +1 -0
  35. package/dist/lib/projects.d.ts +64 -0
  36. package/dist/lib/projects.d.ts.map +1 -0
  37. package/dist/lib/projects.js +127 -0
  38. package/dist/lib/projects.js.map +1 -0
  39. package/dist/lib/providers/github.d.ts +23 -0
  40. package/dist/lib/providers/github.d.ts.map +1 -0
  41. package/dist/lib/providers/github.js +130 -0
  42. package/dist/lib/providers/github.js.map +1 -0
  43. package/dist/lib/providers/gitlab.d.ts +23 -0
  44. package/dist/lib/providers/gitlab.d.ts.map +1 -0
  45. package/dist/lib/providers/gitlab.js +133 -0
  46. package/dist/lib/providers/gitlab.js.map +1 -0
  47. package/dist/lib/providers/index.d.ts +12 -0
  48. package/dist/lib/providers/index.d.ts.map +1 -0
  49. package/dist/lib/providers/index.js +25 -0
  50. package/dist/lib/providers/index.js.map +1 -0
  51. package/dist/lib/providers/provider.d.ts +35 -0
  52. package/dist/lib/providers/provider.d.ts.map +1 -0
  53. package/dist/lib/providers/provider.js +13 -0
  54. package/dist/lib/providers/provider.js.map +1 -0
  55. package/dist/lib/services/health.d.ts +38 -0
  56. package/dist/lib/services/health.d.ts.map +1 -0
  57. package/dist/lib/services/health.js +100 -0
  58. package/dist/lib/services/health.js.map +1 -0
  59. package/dist/lib/services/heartbeat.d.ts +38 -0
  60. package/dist/lib/services/heartbeat.d.ts.map +1 -0
  61. package/dist/lib/services/heartbeat.js +199 -0
  62. package/dist/lib/services/heartbeat.js.map +1 -0
  63. package/dist/lib/services/pipeline.d.ts +36 -0
  64. package/dist/lib/services/pipeline.d.ts.map +1 -0
  65. package/dist/lib/services/pipeline.js +90 -0
  66. package/dist/lib/services/pipeline.js.map +1 -0
  67. package/dist/lib/services/queue.d.ts +14 -0
  68. package/dist/lib/services/queue.d.ts.map +1 -0
  69. package/dist/lib/services/queue.js +31 -0
  70. package/dist/lib/services/queue.js.map +1 -0
  71. package/dist/lib/services/tick.d.ts +62 -0
  72. package/dist/lib/services/tick.d.ts.map +1 -0
  73. package/dist/lib/services/tick.js +160 -0
  74. package/dist/lib/services/tick.js.map +1 -0
  75. package/dist/lib/setup/agent.d.ts +14 -0
  76. package/dist/lib/setup/agent.d.ts.map +1 -0
  77. package/dist/lib/setup/agent.js +72 -0
  78. package/dist/lib/setup/agent.js.map +1 -0
  79. package/dist/lib/setup/config.d.ts +22 -0
  80. package/dist/lib/setup/config.d.ts.map +1 -0
  81. package/dist/lib/setup/config.js +67 -0
  82. package/dist/lib/setup/config.js.map +1 -0
  83. package/dist/lib/setup/index.d.ts +53 -0
  84. package/dist/lib/setup/index.d.ts.map +1 -0
  85. package/dist/lib/setup/index.js +68 -0
  86. package/dist/lib/setup/index.js.map +1 -0
  87. package/dist/lib/setup/workspace.d.ts +6 -0
  88. package/dist/lib/setup/workspace.d.ts.map +1 -0
  89. package/dist/lib/setup/workspace.js +69 -0
  90. package/dist/lib/setup/workspace.js.map +1 -0
  91. package/dist/lib/templates.d.ts +9 -0
  92. package/dist/lib/templates.d.ts.map +1 -0
  93. package/dist/lib/templates.js +163 -0
  94. package/dist/lib/templates.js.map +1 -0
  95. package/dist/lib/tiers.d.ts +55 -0
  96. package/dist/lib/tiers.d.ts.map +1 -0
  97. package/dist/lib/tiers.js +74 -0
  98. package/dist/lib/tiers.js.map +1 -0
  99. package/dist/lib/tool-helpers.d.ts +44 -0
  100. package/dist/lib/tool-helpers.d.ts.map +1 -0
  101. package/dist/lib/tool-helpers.js +65 -0
  102. package/dist/lib/tool-helpers.js.map +1 -0
  103. package/dist/lib/tools/health.d.ts +28 -0
  104. package/dist/lib/tools/health.d.ts.map +1 -0
  105. package/dist/lib/tools/health.js +61 -0
  106. package/dist/lib/tools/health.js.map +1 -0
  107. package/dist/lib/tools/onboard.d.ts +24 -0
  108. package/dist/lib/tools/onboard.d.ts.map +1 -0
  109. package/dist/lib/tools/onboard.js +27 -0
  110. package/dist/lib/tools/onboard.js.map +1 -0
  111. package/dist/lib/tools/project-register.d.ts +51 -0
  112. package/dist/lib/tools/project-register.d.ts.map +1 -0
  113. package/dist/lib/tools/project-register.js +172 -0
  114. package/dist/lib/tools/project-register.js.map +1 -0
  115. package/dist/lib/tools/queue-status.test.d.ts +2 -0
  116. package/dist/lib/tools/queue-status.test.d.ts.map +1 -0
  117. package/dist/lib/tools/queue-status.test.js +48 -0
  118. package/dist/lib/tools/queue-status.test.js.map +1 -0
  119. package/dist/lib/tools/setup.d.ts +76 -0
  120. package/dist/lib/tools/setup.d.ts.map +1 -0
  121. package/dist/lib/tools/setup.js +102 -0
  122. package/dist/lib/tools/setup.js.map +1 -0
  123. package/dist/lib/tools/status.d.ts +24 -0
  124. package/dist/lib/tools/status.d.ts.map +1 -0
  125. package/dist/lib/tools/status.js +53 -0
  126. package/dist/lib/tools/status.js.map +1 -0
  127. package/dist/lib/tools/task-comment.d.ts +40 -0
  128. package/dist/lib/tools/task-comment.d.ts.map +1 -0
  129. package/dist/lib/tools/task-comment.js +84 -0
  130. package/dist/lib/tools/task-comment.js.map +1 -0
  131. package/dist/lib/tools/task-create.d.ts +54 -0
  132. package/dist/lib/tools/task-create.d.ts.map +1 -0
  133. package/dist/lib/tools/task-create.js +77 -0
  134. package/dist/lib/tools/task-create.js.map +1 -0
  135. package/dist/lib/tools/task-update.d.ts +40 -0
  136. package/dist/lib/tools/task-update.d.ts.map +1 -0
  137. package/dist/lib/tools/task-update.js +79 -0
  138. package/dist/lib/tools/task-update.js.map +1 -0
  139. package/dist/lib/tools/task-update.test.d.ts +7 -0
  140. package/dist/lib/tools/task-update.test.d.ts.map +1 -0
  141. package/dist/lib/tools/task-update.test.js +55 -0
  142. package/dist/lib/tools/task-update.test.js.map +1 -0
  143. package/dist/lib/tools/work-finish.d.ts +43 -0
  144. package/dist/lib/tools/work-finish.d.ts.map +1 -0
  145. package/dist/lib/tools/work-finish.js +77 -0
  146. package/dist/lib/tools/work-finish.js.map +1 -0
  147. package/dist/lib/tools/work-start.d.ts +39 -0
  148. package/dist/lib/tools/work-start.d.ts.map +1 -0
  149. package/dist/lib/tools/work-start.js +129 -0
  150. package/dist/lib/tools/work-start.js.map +1 -0
  151. package/dist/lib/types.d.ts +17 -0
  152. package/dist/lib/types.d.ts.map +1 -0
  153. package/dist/lib/types.js +8 -0
  154. package/dist/lib/types.js.map +1 -0
  155. package/docs/ARCHITECTURE.md +662 -0
  156. package/docs/CONFIGURATION.md +336 -0
  157. package/docs/MANAGEMENT.md +120 -0
  158. package/docs/ONBOARDING.md +251 -0
  159. package/docs/QA_WORKFLOW.md +120 -0
  160. package/docs/ROADMAP.md +96 -0
  161. package/docs/TESTING.md +339 -0
  162. package/docs/TOOLS.md +361 -0
  163. package/package.json +55 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 laurentenhoor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,406 @@
1
+ <p align="center">
2
+ <img src="assets/DevClaw.png" width="300" alt="DevClaw Logo">
3
+ </p>
4
+
5
+ # DevClaw — Development Plugin for OpenClaw
6
+
7
+ **Turn any group chat into a dev team that ships.**
8
+
9
+ DevClaw is a plugin for [OpenClaw](https://openclaw.ai) that turns your orchestrator agent into a development manager. It hires developers, assigns tasks, reviews code, and keeps the pipeline moving — across as many projects as you have group chats. [Get started &rarr;](#getting-started)
10
+
11
+ ---
12
+
13
+ ## What it looks like
14
+
15
+ You have two projects in two Telegram groups. You go to bed. You wake up:
16
+
17
+ ```
18
+ ── Group: "Dev - My Webapp" ──────────────────────────────
19
+
20
+ Agent: "⚡ Sending DEV (medior) for #42: Add login page"
21
+ Agent: "✅ DEV DONE #42 — Login page with OAuth. Moved to QA."
22
+ Agent: "🔍 Sending QA (reviewer) for #42: Add login page"
23
+ Agent: "🎉 QA PASS #42. Issue closed."
24
+ Agent: "⚡ Sending DEV (junior) for #43: Fix button color on /settings"
25
+ Agent: "✅ DEV DONE #43 — Updated to brand blue. Moved to QA."
26
+ Agent: "❌ QA FAIL #43 — Color doesn't match dark mode. Back to DEV."
27
+ Agent: "⚡ Sending DEV (junior) for #43: Fix button color on /settings"
28
+
29
+ You: "Create an issue for refactoring the profile page, pick it up."
30
+
31
+ Agent: created #44 "Refactor user profile page" on GitHub — To Do
32
+ Agent: "⚡ Sending DEV (medior) for #44: Refactor user profile page"
33
+
34
+ Agent: "✅ DEV DONE #43 — Fixed dark-mode color. Back to QA."
35
+ Agent: "🎉 QA PASS #43. Issue closed."
36
+
37
+ ── Group: "Dev - My API" ─────────────────────────────────
38
+
39
+ Agent: "🧠 Spawning DEV (senior) for #18: Migrate auth to OAuth2"
40
+ Agent: "✅ DEV DONE #18 — OAuth2 provider with refresh tokens. Moved to QA."
41
+ Agent: "🎉 QA PASS #18. Issue closed."
42
+ Agent: "⚡ Sending DEV (medior) for #19: Add rate limiting to /api/search"
43
+ ```
44
+
45
+ Multiple issues shipped, a QA failure automatically retried, and a second project's migration completed — all while you slept. When you dropped in mid-stream to create an issue, the scheduler kept going before, during, and after.
46
+
47
+ ---
48
+
49
+ ## Why DevClaw
50
+
51
+ ### Autonomous multi-project development
52
+
53
+ Each project is fully isolated — own queue, workers, sessions, and state. DEV and QA execute in parallel within each project, and multiple projects run simultaneously. A token-free scheduling engine drives it all autonomously:
54
+
55
+ - **[Scheduling engine](#automatic-scheduling)** — `work_heartbeat` continuously scans queues, dispatches workers, and drives DEV → QA → DEV [feedback loops](#how-tasks-flow-between-roles)
56
+ - **[Project isolation](#execution-modes)** — parallel workers per project, parallel projects across the system
57
+ - **[Role instructions](#custom-instructions-per-project)** — per-project, per-role prompts injected at dispatch time
58
+
59
+ ### Process enforcement
60
+
61
+ GitHub/GitLab issues are the single source of truth — not an internal database. Every tool call wraps the full operation into deterministic code with rollback on failure:
62
+
63
+ - **[External task state](#your-issues-stay-in-your-tracker)** — labels, transitions, and status queries go through your issue tracker
64
+ - **[Atomic operations](#what-atomic-means-here)** — label transition + state update + session dispatch + audit log in one call
65
+ - **[Tool-based guardrails](#the-toolbox)** — 11 tools enforce the process; the agent provides intent, the plugin handles mechanics
66
+
67
+ ### ~60-80% token savings
68
+
69
+ Three mechanisms compound to cut token usage dramatically versus running one large model with fresh context each time:
70
+
71
+ - **[Tier selection](#meet-your-team)** — Haiku for typos, Sonnet for features, Opus for architecture (~30-50% on simple tasks)
72
+ - **[Session reuse](#sessions-accumulate-context)** — workers accumulate codebase knowledge across tasks (~40-60% per task)
73
+ - **[Token-free scheduling](#automatic-scheduling)** — `work_heartbeat` runs on pure CLI calls, zero LLM tokens for orchestration
74
+
75
+ ---
76
+
77
+ ## The problem DevClaw solves
78
+
79
+ OpenClaw is a great multi-agent runtime. It handles sessions, tools, channels, gateway RPC — everything you need to run AI agents. But it's a general-purpose platform. It has no opinion about how software gets built.
80
+
81
+ Without DevClaw, your orchestrator agent has to figure out on its own how to:
82
+ - Pick the right model for the task complexity
83
+ - Create or reuse the right worker session
84
+ - Transition issue labels in the right order
85
+ - Track which worker is doing what across projects
86
+ - Schedule QA after DEV completes, and re-schedule DEV after QA fails
87
+ - Detect crashed workers and recover
88
+ - Log everything for auditability
89
+
90
+ That's a lot of reasoning per task. LLMs do it imperfectly — they forget steps, corrupt state, pick the wrong model, lose session references. You end up babysitting the thing you built to avoid babysitting.
91
+
92
+ DevClaw moves all of that into deterministic plugin code. The agent says "pick up issue #42." The plugin handles the other 10 steps atomically. Every time, the same way, zero reasoning tokens spent on orchestration.
93
+
94
+ ---
95
+
96
+ ## Meet your team
97
+
98
+ DevClaw doesn't think in model IDs. It thinks in people.
99
+
100
+ When a task comes in, you don't configure `anthropic/claude-sonnet-4-5` — you assign a **medior developer**. The orchestrator evaluates task complexity and picks the right person for the job:
101
+
102
+ ### Developers
103
+
104
+ | Level | Assigns to | Model |
105
+ |---|---|---|
106
+ | **Junior** | Typos, CSS fixes, renames, single-file changes | Haiku |
107
+ | **Medior** | Features, bug fixes, multi-file changes | Sonnet |
108
+ | **Senior** | Architecture, migrations, system-wide refactoring | Opus |
109
+
110
+ ### QA
111
+
112
+ | Level | Assigns to | Model |
113
+ |---|---|---|
114
+ | **Reviewer** | Code review, test validation, PR inspection | Sonnet |
115
+ | **Tester** | Manual testing, smoke tests | Haiku |
116
+
117
+ A CSS typo gets the intern. A database migration gets the architect. You're not burning Opus tokens on a color change, and you're not sending Haiku to redesign your auth system.
118
+
119
+ Every mapping is [configurable](docs/CONFIGURATION.md#model-tiers) — swap in any model you want per level.
120
+
121
+ ---
122
+
123
+ ## How a task moves through the pipeline
124
+
125
+ Every issue follows the same path, no exceptions. DevClaw enforces it:
126
+
127
+ ```
128
+ Planning → To Do → Doing → To Test → Testing → Done
129
+ ```
130
+
131
+ ```mermaid
132
+ stateDiagram-v2
133
+ [*] --> Planning
134
+ Planning --> ToDo: Ready for development
135
+
136
+ ToDo --> Doing: DEV picks up
137
+ Doing --> ToTest: DEV done
138
+
139
+ ToTest --> Testing: Scheduler picks up QA
140
+ Testing --> Done: QA pass (issue closed)
141
+ Testing --> ToImprove: QA fail (back to DEV)
142
+ Testing --> Refining: QA needs human input
143
+
144
+ ToImprove --> Doing: Scheduler picks up DEV fix
145
+ Refining --> ToDo: Human decides
146
+
147
+ Done --> [*]
148
+ ```
149
+
150
+ These labels live on your actual GitHub/GitLab issues. Not in some internal database — in the tool you already use. Filter by `Doing` in GitHub to see what's in progress. Set up a webhook on `Done` to trigger deploys. The issue tracker is the source of truth.
151
+
152
+ ### What "atomic" means here
153
+
154
+ When you say "pick up #42 for DEV", the plugin does all of this in one operation:
155
+ 1. Verifies the issue is in the right state
156
+ 2. Picks the developer level (or uses what you specified)
157
+ 3. Transitions the label (`To Do` → `Doing`)
158
+ 4. Creates or reuses the right worker session
159
+ 5. Dispatches the task with project-specific instructions
160
+ 6. Updates internal state
161
+ 7. Logs an audit entry
162
+
163
+ If step 4 fails, step 3 is rolled back. No half-states, no orphaned labels, no "the issue says Doing but nobody's working on it."
164
+
165
+ ---
166
+
167
+ ## What happens behind the scenes
168
+
169
+ ### Workers report back themselves
170
+
171
+ When a developer finishes, they call `work_finish` directly — no orchestrator involved:
172
+
173
+ - **DEV "done"** → label moves to `To Test`, scheduler picks up QA on next tick
174
+ - **DEV "blocked"** → label moves back to `To Do`, task returns to queue
175
+ - **QA "pass"** → label moves to `Done`, issue closes
176
+ - **QA "fail"** → label moves to `To Improve`, scheduler picks up DEV on next tick
177
+
178
+ The orchestrator doesn't need to poll, check, or coordinate. Workers are self-reporting.
179
+
180
+ ### Sessions accumulate context
181
+
182
+ Each developer level gets its own persistent session per project. Your medior dev that's done 5 features on `my-app` already knows the codebase — it doesn't re-read 50K tokens of source code every time it picks up a new task.
183
+
184
+ That's a **~40-60% token saving per task** from session reuse alone.
185
+
186
+ Combined with tier selection (not using Opus when Haiku will do) and the token-free heartbeat (more on that next), DevClaw significantly reduces your token bill versus running everything through one large model.
187
+
188
+ ### Everything is logged
189
+
190
+ Every tool call writes an NDJSON line to `audit.log`:
191
+
192
+ ```bash
193
+ cat audit.log | jq 'select(.event=="work_start")'
194
+ ```
195
+
196
+ Full trace of every task, every level selection, every label transition, every health fix. No manual logging needed.
197
+
198
+ ---
199
+
200
+ ## Automatic scheduling
201
+
202
+ DevClaw doesn't wait for you to tell it what to do next. A background scheduling system continuously scans for available work and dispatches workers — zero LLM tokens, pure deterministic code. This is the engine that keeps the pipeline moving: when DEV finishes, the scheduler sees a `To Test` issue and dispatches QA. When QA fails, the scheduler sees a `To Improve` issue and dispatches DEV. No hand-offs, no orchestrator reasoning — just label-driven scheduling.
203
+
204
+ ### The `work_heartbeat`
205
+
206
+ Every tick (default: 60 seconds), the scheduler runs two passes:
207
+
208
+ 1. **Health pass** — detects workers stuck for >2 hours, reverts their labels back to queue, deactivates them. Catches crashed sessions, context overflows, or workers that died without reporting back.
209
+ 2. **Queue pass** — scans for available tasks by priority (`To Improve` > `To Test` > `To Do`), fills free worker slots. DEV and QA slots are filled independently.
210
+
211
+ All CLI calls and JSON reads. Workers only consume tokens when they actually start coding or reviewing. The scheduler also fires immediately after every `work_finish` (as a tick), so transitions happen without waiting for the next interval.
212
+
213
+ ### How tasks flow between roles
214
+
215
+ When a worker calls `work_finish`, the plugin transitions the label. The scheduler picks up the rest:
216
+
217
+ - **DEV "done"** → label moves to `To Test` → next tick dispatches QA
218
+ - **QA "fail"** → label moves to `To Improve` → next tick dispatches DEV (reuses previous level)
219
+ - **QA "pass"** → label moves to `Done`, issue closes
220
+ - **"blocked"** → label reverts to queue (`To Do` or `To Test`) for retry
221
+
222
+ No orchestrator involvement. Workers self-report, the scheduler fills free slots.
223
+
224
+ ### Execution modes
225
+
226
+ Each project is fully isolated — its own queue, workers, sessions, state. No cross-project contamination. Two levels of parallelism control how work gets scheduled:
227
+
228
+ - **Project-level (`roleExecution`)** — DEV and QA work simultaneously on different tasks (default: `parallel`) or take turns (`sequential`)
229
+ - **Plugin-level (`projectExecution`)** — all registered projects dispatch workers independently (default: `parallel`) or only one project runs at a time (`sequential`)
230
+
231
+ ### Configuration
232
+
233
+ All scheduling behavior is configurable in `openclaw.json`:
234
+
235
+ ```json
236
+ {
237
+ "plugins": {
238
+ "entries": {
239
+ "devclaw": {
240
+ "config": {
241
+ "work_heartbeat": {
242
+ "enabled": true,
243
+ "intervalSeconds": 60,
244
+ "maxPickupsPerTick": 4
245
+ },
246
+ "projectExecution": "parallel"
247
+ }
248
+ }
249
+ }
250
+ }
251
+ }
252
+ ```
253
+
254
+ Per-project settings live in `projects.json`:
255
+
256
+ ```json
257
+ {
258
+ "-1234567890": {
259
+ "name": "my-app",
260
+ "roleExecution": "parallel"
261
+ }
262
+ }
263
+ ```
264
+
265
+ | Setting | Where | Default | What it controls |
266
+ |---|---|---|---|
267
+ | `work_heartbeat.enabled` | `openclaw.json` | `true` | Turn the heartbeat on/off |
268
+ | `work_heartbeat.intervalSeconds` | `openclaw.json` | `60` | Seconds between ticks |
269
+ | `work_heartbeat.maxPickupsPerTick` | `openclaw.json` | `4` | Max workers dispatched per tick |
270
+ | `projectExecution` | `openclaw.json` | `"parallel"` | All projects at once, or one at a time |
271
+ | `roleExecution` | `projects.json` | `"parallel"` | DEV+QA at once, or one role at a time |
272
+
273
+ See the [Configuration reference](docs/CONFIGURATION.md) for the full schema.
274
+
275
+ ---
276
+
277
+ ## Task management
278
+
279
+ ### Your issues stay in your tracker
280
+
281
+ DevClaw doesn't have its own task database. All task state lives in **GitHub Issues** or **GitLab Issues** — auto-detected from your git remote. The eight pipeline labels are created on your repo when you register a project. Your project manager sees progress in GitHub without knowing DevClaw exists. Your CI/CD can trigger on label changes. If you stop using DevClaw, your issues and labels stay exactly where they are.
282
+
283
+ The provider is pluggable (`IssueProvider` interface). GitHub and GitLab work today. Jira, Linear, or anything else just needs to implement the same interface.
284
+
285
+ ### Creating, updating, and commenting
286
+
287
+ Tasks can come from anywhere — the orchestrator creates them from chat, workers file bugs they discover mid-task, or you create them directly in GitHub/GitLab:
288
+
289
+ ```
290
+ You: "Create an issue: fix the broken OAuth redirect"
291
+ Agent: creates issue #43 with label "Planning"
292
+
293
+ You: "Move #43 to To Do"
294
+ Agent: transitions label Planning → To Do
295
+
296
+ You: "Add a comment on #42: needs to handle the edge case for expired tokens"
297
+ Agent: adds comment attributed to "orchestrator"
298
+ ```
299
+
300
+ Workers can also comment during work — QA leaves review feedback, DEV posts implementation notes. Every comment carries role attribution so you know who said what.
301
+
302
+ ### Custom instructions per project
303
+
304
+ Each project gets instruction files that workers receive with every task they pick up:
305
+
306
+ ```
307
+ workspace/projects/roles/
308
+ ├── my-webapp/
309
+ │ ├── dev.md "Run npm test before committing. Deploy URL: staging.example.com"
310
+ │ └── qa.md "Check OAuth flow. Verify mobile responsiveness."
311
+ ├── my-api/
312
+ │ ├── dev.md "Run cargo test. Follow REST conventions in CONTRIBUTING.md"
313
+ │ └── qa.md "Verify all endpoints return correct status codes."
314
+ └── default/
315
+ ├── dev.md (fallback for projects without custom instructions)
316
+ └── qa.md
317
+ ```
318
+
319
+ Deployment steps, test commands, coding standards, acceptance criteria — all injected at dispatch time, per project, per role.
320
+
321
+ ---
322
+
323
+ ## Getting started
324
+
325
+ ### Prerequisites
326
+
327
+ - [OpenClaw](https://openclaw.ai) installed (`openclaw --version`)
328
+ - Node.js >= 20
329
+ - `gh` CLI ([GitHub](https://cli.github.com)) or `glab` CLI ([GitLab](https://gitlab.com/gitlab-org/cli)), authenticated
330
+
331
+ ### Install
332
+
333
+ ```bash
334
+ cp -r devclaw ~/.openclaw/extensions/
335
+ ```
336
+
337
+ ### Set up through conversation
338
+
339
+ The easiest way to configure DevClaw is to just talk to your agent:
340
+
341
+ ```
342
+ You: "Help me set up DevClaw"
343
+ Agent: "I'll walk you through it. Should I use this agent as the
344
+ orchestrator, or create a new one?"
345
+ You: "Use this one"
346
+
347
+ Agent: "Want to bind a messaging channel?"
348
+ You: "Telegram"
349
+
350
+ Agent: "Here are the default developer assignments:
351
+ Junior → Haiku, Medior → Sonnet, Senior → Opus
352
+ Reviewer → Sonnet, Tester → Haiku
353
+ Keep these or customize?"
354
+ You: "Keep them"
355
+
356
+ Agent: "Done. Want to register a project?"
357
+ You: "Yes — my-app at ~/git/my-app, main branch"
358
+
359
+ Agent: "Project registered. 8 labels created on your repo.
360
+ Role instructions scaffolded. Try: 'check the queue'"
361
+ ```
362
+
363
+ You can also use the [CLI wizard or non-interactive setup](docs/ONBOARDING.md#step-2-run-setup) for scripted environments.
364
+
365
+ ---
366
+
367
+ ## The toolbox
368
+
369
+ DevClaw gives the orchestrator 11 tools. These aren't just convenience wrappers — they're **guardrails**. Each tool encodes a complex multi-step operation into a single atomic call. The agent provides intent, the plugin handles mechanics. The agent physically cannot skip a label transition, forget to update state, or dispatch to the wrong session — those decisions are made by deterministic code, not LLM reasoning.
370
+
371
+ | Tool | What it does |
372
+ |---|---|
373
+ | `work_start` | Pick up a task — resolves level, transitions label, dispatches session, logs audit |
374
+ | `work_finish` | Complete a task — transitions label, updates state, ticks queue for next dispatch |
375
+ | `task_create` | Create a new issue (used by workers to file bugs they discover) |
376
+ | `task_update` | Manually change an issue's state label |
377
+ | `task_comment` | Add a comment to an issue (with role attribution) |
378
+ | `status` | Dashboard: queue counts + who's working on what |
379
+ | `health` | Detect zombie workers, stale sessions, state inconsistencies |
380
+ | `work_heartbeat` | Manually trigger a health check + queue dispatch cycle |
381
+ | `project_register` | One-time project setup: creates labels, scaffolds instructions, initializes state |
382
+ | `setup` | Agent + workspace initialization |
383
+ | `onboard` | Conversational setup guide |
384
+
385
+ Full parameters and usage in the [Tools Reference](docs/TOOLS.md).
386
+
387
+ ---
388
+
389
+ ## Documentation
390
+
391
+ | | |
392
+ |---|---|
393
+ | **[Architecture](docs/ARCHITECTURE.md)** | System design, session model, data flow, end-to-end diagrams |
394
+ | **[Tools Reference](docs/TOOLS.md)** | Complete reference for all 11 tools |
395
+ | **[Configuration](docs/CONFIGURATION.md)** | `openclaw.json`, `projects.json`, heartbeat, notifications |
396
+ | **[Onboarding Guide](docs/ONBOARDING.md)** | Full step-by-step setup |
397
+ | **[QA Workflow](docs/QA_WORKFLOW.md)** | QA process and review templates |
398
+ | **[Testing](docs/TESTING.md)** | Test suite, fixtures, CI/CD |
399
+ | **[Management Theory](docs/MANAGEMENT.md)** | The delegation model behind the design |
400
+ | **[Roadmap](docs/ROADMAP.md)** | What's coming next |
401
+
402
+ ---
403
+
404
+ ## License
405
+
406
+ MIT
@@ -0,0 +1,88 @@
1
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
2
+ declare const plugin: {
3
+ id: string;
4
+ name: string;
5
+ description: string;
6
+ configSchema: {
7
+ type: string;
8
+ properties: {
9
+ models: {
10
+ type: string;
11
+ description: string;
12
+ properties: {
13
+ dev: {
14
+ type: string;
15
+ description: string;
16
+ properties: {
17
+ junior: {
18
+ type: string;
19
+ };
20
+ medior: {
21
+ type: string;
22
+ };
23
+ senior: {
24
+ type: string;
25
+ };
26
+ };
27
+ };
28
+ qa: {
29
+ type: string;
30
+ description: string;
31
+ properties: {
32
+ reviewer: {
33
+ type: string;
34
+ };
35
+ tester: {
36
+ type: string;
37
+ };
38
+ };
39
+ };
40
+ };
41
+ };
42
+ projectExecution: {
43
+ type: string;
44
+ enum: string[];
45
+ description: string;
46
+ default: string;
47
+ };
48
+ notifications: {
49
+ type: string;
50
+ description: string;
51
+ properties: {
52
+ workerStart: {
53
+ type: string;
54
+ default: boolean;
55
+ };
56
+ workerComplete: {
57
+ type: string;
58
+ default: boolean;
59
+ };
60
+ };
61
+ };
62
+ work_heartbeat: {
63
+ type: string;
64
+ description: string;
65
+ properties: {
66
+ enabled: {
67
+ type: string;
68
+ default: boolean;
69
+ description: string;
70
+ };
71
+ intervalSeconds: {
72
+ type: string;
73
+ default: number;
74
+ description: string;
75
+ };
76
+ maxPickupsPerTick: {
77
+ type: string;
78
+ default: number;
79
+ description: string;
80
+ };
81
+ };
82
+ };
83
+ };
84
+ };
85
+ register(api: OpenClawPluginApi): void;
86
+ };
87
+ export default plugin;
88
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAc7D,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAwEI,iBAAiB;CAgChC,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,107 @@
1
+ import { createWorkStartTool } from "./lib/tools/work-start.js";
2
+ import { createWorkFinishTool } from "./lib/tools/work-finish.js";
3
+ import { createTaskCreateTool } from "./lib/tools/task-create.js";
4
+ import { createTaskUpdateTool } from "./lib/tools/task-update.js";
5
+ import { createTaskCommentTool } from "./lib/tools/task-comment.js";
6
+ import { createStatusTool } from "./lib/tools/status.js";
7
+ import { createHealthTool } from "./lib/tools/health.js";
8
+ import { createProjectRegisterTool } from "./lib/tools/project-register.js";
9
+ import { createSetupTool } from "./lib/tools/setup.js";
10
+ import { createOnboardTool } from "./lib/tools/onboard.js";
11
+ import { registerCli } from "./lib/cli.js";
12
+ import { registerHeartbeatService } from "./lib/services/heartbeat.js";
13
+ const plugin = {
14
+ id: "devclaw",
15
+ name: "DevClaw",
16
+ description: "Multi-project dev/qa pipeline orchestration with GitHub/GitLab integration, developer tiers, and audit logging.",
17
+ configSchema: {
18
+ type: "object",
19
+ properties: {
20
+ models: {
21
+ type: "object",
22
+ description: "Model mapping per role and tier",
23
+ properties: {
24
+ dev: {
25
+ type: "object",
26
+ description: "Developer tier models",
27
+ properties: {
28
+ junior: { type: "string" },
29
+ medior: { type: "string" },
30
+ senior: { type: "string" },
31
+ },
32
+ },
33
+ qa: {
34
+ type: "object",
35
+ description: "QA tier models",
36
+ properties: {
37
+ reviewer: { type: "string" },
38
+ tester: { type: "string" },
39
+ },
40
+ },
41
+ },
42
+ },
43
+ projectExecution: {
44
+ type: "string",
45
+ enum: ["parallel", "sequential"],
46
+ description: "Plugin-level: parallel (each project independent) or sequential (one project at a time)",
47
+ default: "parallel",
48
+ },
49
+ notifications: {
50
+ type: "object",
51
+ description: "Per-event-type notification toggles. All default to true — set to false to suppress.",
52
+ properties: {
53
+ workerStart: { type: "boolean", default: true },
54
+ workerComplete: { type: "boolean", default: true },
55
+ },
56
+ },
57
+ work_heartbeat: {
58
+ type: "object",
59
+ description: "Token-free interval-based heartbeat service. Runs health checks + queue dispatch automatically. Discovers all DevClaw agents from openclaw.json and processes each independently.",
60
+ properties: {
61
+ enabled: {
62
+ type: "boolean",
63
+ default: true,
64
+ description: "Enable automatic periodic heartbeat service.",
65
+ },
66
+ intervalSeconds: {
67
+ type: "number",
68
+ default: 60,
69
+ description: "Seconds between automatic heartbeat ticks.",
70
+ },
71
+ maxPickupsPerTick: {
72
+ type: "number",
73
+ default: 4,
74
+ description: "Max worker dispatches per agent per tick. Applied to each DevClaw agent independently.",
75
+ },
76
+ },
77
+ },
78
+ },
79
+ },
80
+ register(api) {
81
+ // Worker lifecycle
82
+ api.registerTool(createWorkStartTool(api), { names: ["work_start"] });
83
+ api.registerTool(createWorkFinishTool(api), { names: ["work_finish"] });
84
+ // Task management
85
+ api.registerTool(createTaskCreateTool(api), { names: ["task_create"] });
86
+ api.registerTool(createTaskUpdateTool(api), { names: ["task_update"] });
87
+ api.registerTool(createTaskCommentTool(api), { names: ["task_comment"] });
88
+ // Operations
89
+ api.registerTool(createStatusTool(api), { names: ["status"] });
90
+ api.registerTool(createHealthTool(), { names: ["health"] });
91
+ // Setup & config
92
+ api.registerTool(createProjectRegisterTool(), {
93
+ names: ["project_register"],
94
+ });
95
+ api.registerTool(createSetupTool(api), { names: ["setup"] });
96
+ api.registerTool(createOnboardTool(api), { names: ["onboard"] });
97
+ // CLI
98
+ api.registerCli(({ program }) => registerCli(program, api), {
99
+ commands: ["devclaw"],
100
+ });
101
+ // Services
102
+ registerHeartbeatService(api);
103
+ api.logger.info("DevClaw plugin registered (10 tools, 1 CLI command group, 1 service)");
104
+ },
105
+ };
106
+ export default plugin;
107
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function log(workspaceDir: string, event: string, data: Record<string, unknown>): Promise<void>;
2
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../lib/audit.ts"],"names":[],"mappings":"AAUA,wBAAsB,GAAG,CACvB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC,CAkBf"}