@calltelemetry/openclaw-linear 0.9.1 → 0.9.3

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.
package/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ <p align="center">
2
+ <img src="docs/logo.jpeg" alt="OpenClaw Linear Plugin" width="720" />
3
+ </p>
4
+
1
5
  # @calltelemetry/openclaw-linear
2
6
 
3
7
  [![CI](https://github.com/calltelemetry/openclaw-linear-plugin/actions/workflows/ci.yml/badge.svg)](https://github.com/calltelemetry/openclaw-linear-plugin/actions/workflows/ci.yml)
@@ -8,6 +12,35 @@
8
12
 
9
13
  Connect Linear to AI agents. Issues get triaged, implemented, and audited — automatically.
10
14
 
15
+ > **Real human here.** I'm actively building this and beta testing it on real projects.
16
+ > Looking for feedback, bug reports, and fellow mad scientists.
17
+ > [Open an issue](https://github.com/calltelemetry/openclaw-linear-plugin/issues) — feedback and bug reports welcome.
18
+
19
+ ### Project Status
20
+
21
+ - [x] Cloudflare tunnel setup (webhook ingress, no inbound ports)
22
+ - [x] Linear webhook sync (Comment + Issue events)
23
+ - [x] Linear OAuth app webhook (AgentSessionEvent created/prompted)
24
+ - [x] Linear API integration (issues, comments, labels, state transitions)
25
+ - [x] Agent routing (`@mentions`, natural language intent classifier)
26
+ - [x] Auto-triage (story points, labels, priority — read-only)
27
+ - [x] Complexity-tier dispatch (small → Haiku, medium → Sonnet, high → Opus)
28
+ - [x] Isolated git worktrees per dispatch
29
+ - [x] Worker → Auditor pipeline (hard-enforced, not LLM-mediated)
30
+ - [x] Audit rework loop (gaps fed back, automatic retry)
31
+ - [x] Watchdog timeout + escalation
32
+ - [x] Webhook deduplication (60s sliding window across session/comment/assignment)
33
+ - [ ] Multi-repo worktree support
34
+ - [ ] Project planner (interview → user stories → sub-issues → DAG dispatch)
35
+ - [ ] Cross-model plan review (Claude ↔ Codex ↔ Gemini)
36
+ - [x] Issue closure with summary report
37
+ - [ ] Sub-issue decomposition (orchestrator-level only)
38
+ - [x] `spawn_agent` / `ask_agent` sub-agent tools
39
+ - [x] CI + coverage badges (1000+ tests, Codecov integration)
40
+ - [ ] **Worktree → PR merge** — `createPullRequest()` exists but is not wired into the pipeline. After audit pass, commits sit on a `codex/{identifier}` branch. You create the PR manually.
41
+ - [ ] **Sub-agent worktree sharing** — Sub-agents spawned via `spawn_agent`/`ask_agent` do not inherit the parent worktree. They run in their own session without code access.
42
+ - [ ] **Parallel worktree conflict resolution** — DAG dispatch runs up to 3 issues concurrently in separate worktrees, but there's no merge conflict detection across them.
43
+
11
44
  ---
12
45
 
13
46
  ## Why This Exists
@@ -16,60 +49,78 @@ Linear is a great project tracker. But it doesn't orchestrate AI agents — it j
16
49
 
17
50
  This plugin makes the full lifecycle hands-off:
18
51
 
19
- ```mermaid
20
- sequenceDiagram
21
- actor You
22
- participant Linear
23
- participant Plugin
24
- participant Worker as Worker Agent
25
- participant Auditor as Auditor Agent
26
-
27
- You->>Linear: Create issue
28
- Note over Plugin: auto-triage
29
- Linear-->>You: Estimate, labels, priority
30
-
31
- You->>Linear: Assign to agent
32
- Plugin->>Worker: dispatch (isolated worktree)
33
- Worker-->>Plugin: implementation done
34
- Plugin->>Auditor: audit (automatic, hard-enforced)
35
- alt Pass
36
- Auditor-->>Plugin: ✅ verdict
37
- Plugin-->>Linear: Done
38
- else Fail (retries left)
39
- Auditor-->>Plugin: ❌ gaps
40
- Plugin->>Worker: rework (gaps injected)
41
- else Fail (no retries)
42
- Auditor-->>Plugin: ❌ stuck
43
- Plugin-->>You: 🚨 needs your help
44
- end
45
52
  ```
53
+ You create an issue
54
+
55
+
56
+ Agent triages it ──── estimate, labels, priority
57
+
58
+
59
+ You assign it
60
+
61
+
62
+ Plugin dispatches ─── picks model tier, creates worktree
63
+
64
+
65
+ Worker implements ─── code, tests, commits
66
+
67
+
68
+ Auditor verifies ─── independent, hard-enforced
69
+
70
+ ┌───┴───┐
71
+ ▼ ▼
72
+ Done Rework ────── gaps fed back, retry automatic
73
+ ```
74
+
75
+ You work in Linear. The agents handle the rest.
46
76
 
47
77
  **What Linear can't do on its own — and what this plugin handles:**
48
78
 
49
- | Problem | What the plugin does |
79
+ | Gap | What the plugin does |
50
80
  |---|---|
51
- | **No agent orchestration** | Assigns complexity tiers, picks the right model, creates isolated worktrees, runs workers, triggers audits, processes verdicts — all from a single issue assignment |
81
+ | **No agent orchestration** | Assesses complexity, picks the right model tier, creates isolated worktrees, runs workers, triggers audits, processes verdicts — all from a single issue assignment |
52
82
  | **No independent verification** | Hard-enforces a worker → auditor boundary in plugin code. The worker cannot mark its own work done. The audit is not optional and not LLM-mediated. |
53
- | **No failure recovery** | Watchdog kills hung agents after configurable silence. Retries once automatically. Feeds audit failures back as context for rework. Escalates when retries are exhausted. |
83
+ | **No failure recovery** | Watchdog kills hung agents after configurable silence. Feeds audit failures back as rework context. Escalates when retries are exhausted. |
54
84
  | **No multi-agent routing** | Routes `@mentions` and natural language ("hey kaylee look at this") to specific agents. Intent classifier handles plan requests, questions, close commands, and work requests. |
55
- | **No webhook deduplication** | Linear sends events from two separate webhook systems that can overlap. The plugin deduplicates across session IDs, comment IDs, and assignment events with a 60s sliding window. |
56
85
  | **No project-scale planning** | Planner interviews you, creates issues with user stories and acceptance criteria, runs a cross-model review, then dispatches the full dependency graph — up to 3 issues in parallel. |
57
86
 
58
87
  The end result: you work in Linear. You create issues, assign them, comment in plain English. The agents do the rest — or tell you when they can't.
59
88
 
60
89
  ---
61
90
 
62
- ## What It Does
91
+ ## Features
92
+
93
+ ### Core Pipeline
94
+
95
+ - **Auto-triage** — New issues get story point estimates, labels, and priority within seconds. Read-only mode — no side effects.
96
+ - **Worker → Auditor pipeline** — Assign an issue and a worker implements it in an isolated git worktree. An independent auditor verifies the work. The worker cannot self-certify — the audit is hard-enforced in plugin code.
97
+ - **Complexity-tier dispatch** — The plugin assesses each issue and picks the right model. Simple typo? Haiku. Multi-service refactor? Opus. Saves cost and latency without manual intervention.
98
+ - **Automatic rework** — Failed audits feed gaps back to the worker as context. Retries up to N times before escalating. No human needed until the agents are stuck.
63
99
 
64
- - **New issue?** Agent estimates story points, adds labels, sets priority.
65
- - **Assign to agent?** A worker implements it, an independent auditor verifies it, done.
66
- - **Comment anything?** The bot understands natural languageno magic commands needed.
67
- - **Say "close this" or "mark as done"?** Agent writes a closure report and transitions the issue to completed.
68
- - **Say "let's plan the features"?** A planner interviews you, writes user stories, and builds your full issue hierarchy.
69
- - **Plan looks good?** A different AI model automatically audits the plan before dispatch.
70
- - **Agent goes silent?** A watchdog kills it and retries automatically.
71
- - **Linear guidance?** Workspace and team-level guidance from Linear flows into every agent prompt — triage, dispatch, worker, audit.
72
- - **Want updates?** Get notified on Discord, Slack, Telegram, or Signal.
100
+ ### Planning & Closure
101
+
102
+ - **Project planner** — Comment "plan this project" and the agent interviews you, builds user stories with acceptance criteria, creates the full issue hierarchy, and dispatches in dependency order up to 3 issues in parallel.
103
+ - **Cross-model review** Plans are automatically audited by a different AI model (Claude Codex Gemini) before dispatch. Two perspectives, one plan.
104
+ - **Issue closure** — Say "close this" or "mark as done" and the agent generates a closure report and transitions the issue to completed.
105
+ - **Sub-issue decomposition** Orchestrators and the planner break complex work into sub-issues via `linear_issues`. Sub-issues inherit team and project from the parent automatically.
106
+
107
+ ### Multi-Agent & Routing
108
+
109
+ - **Named agents** — Define agents with different roles and expertise. Route work by `@mention` or natural language ("hey kaylee look at this").
110
+ - **Intent classification** — An LLM classifier (~300 tokens, ~2s) understands what you want from any comment. Regex fallback if the classifier fails.
111
+ - **One-time detour** — `@mention` a different agent in a session and it handles that single interaction. The session stays with the original agent.
112
+
113
+ ### Multi-Backend & Multi-Repo
114
+
115
+ - **Three coding backends** — Codex (OpenAI), Claude (Anthropic), Gemini (Google). Configurable globally or per-agent. The agent writes the prompt; the plugin handles backend selection.
116
+ - **Multi-repo dispatch** — Tag an issue with `<!-- repos: api, frontend -->` and the worker gets isolated worktrees for each repo. One issue, multiple codebases, one agent session.
117
+
118
+ ### Operations
119
+
120
+ - **Linear Guidance** — Workspace and team-level guidance configured in Linear's admin UI flows into every agent prompt — triage, dispatch, worker, audit. Admins steer agent behavior without touching config files.
121
+ - **Watchdog** — Kills agents that go silent after configurable inactivity. Retries once, then escalates. Covers LLM hangs, API timeouts, and CLI lockups.
122
+ - **Notifications** — Dispatch lifecycle events (started, auditing, done, stuck) to Discord, Slack, Telegram, or Signal. Rich formatting optional.
123
+ - **Webhook deduplication** — Two-tier guard (in-memory set + 60s TTL map) prevents double-processing across Linear's two webhook systems.
73
124
 
74
125
  ---
75
126
 
@@ -81,20 +132,88 @@ The end result: you work in Linear. You create issues, assign them, comment in p
81
132
  openclaw plugins install @calltelemetry/openclaw-linear
82
133
  ```
83
134
 
84
- ### 2. Expose the gateway (Cloudflare Tunnel)
135
+ ### 2. Expose the gateway
136
+
137
+ Linear delivers webhooks over the public internet, so the gateway needs a public HTTPS URL. See [Tunnel Setup (Cloudflare)](#tunnel-setup-cloudflare) for the recommended approach. Any reverse proxy or tunnel that forwards HTTPS to `localhost:18789` will work.
138
+
139
+ ### 3. Create a Linear OAuth app
140
+
141
+ Go to **Linear Settings > API > Applications** and create an app:
142
+
143
+ - Set **Webhook URL** to `https://your-domain.com/linear/webhook`
144
+ - Set **Redirect URI** to `https://your-domain.com/linear/oauth/callback`
145
+ - Enable events: **Agent Sessions**, **Comments**, **Issues**
146
+ - Save your **Client ID** and **Client Secret**
147
+
148
+ > You also need a **workspace webhook** — run `openclaw openclaw-linear webhooks setup` to auto-provision it, or manually create one in Settings > API > Webhooks pointing to the same URL with **Comment + Issue** events enabled. Both webhooks are required.
149
+
150
+ ### 4. Set credentials
151
+
152
+ ```bash
153
+ export LINEAR_CLIENT_ID="your_client_id"
154
+ export LINEAR_CLIENT_SECRET="your_client_secret"
155
+ ```
156
+
157
+ For systemd services, add these to your unit file:
85
158
 
86
- Linear sends webhook events over the public internet, so the gateway must be reachable via HTTPS. A [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) is the recommended approach — no open ports, no TLS cert management, no static IP required.
159
+ ```ini
160
+ [Service]
161
+ Environment=LINEAR_CLIENT_ID=your_client_id
162
+ Environment=LINEAR_CLIENT_SECRET=your_client_secret
163
+ ```
164
+
165
+ Then reload: `systemctl --user daemon-reload && systemctl --user restart openclaw-gateway`
166
+
167
+ ### 5. Authorize
168
+
169
+ ```bash
170
+ openclaw openclaw-linear auth
171
+ ```
172
+
173
+ This opens your browser. Approve the authorization, then restart:
174
+
175
+ ```bash
176
+ systemctl --user restart openclaw-gateway
177
+ ```
178
+
179
+ ### 6. Verify
180
+
181
+ ```bash
182
+ openclaw openclaw-linear status
183
+ ```
184
+
185
+ You should see a valid token and connected status. Check the gateway logs for a clean startup:
186
+
187
+ ```
188
+ Linear agent extension registered (agent: default, token: profile, orchestration: enabled)
189
+ ```
190
+
191
+ Test the webhook endpoint:
192
+
193
+ ```bash
194
+ curl -s -X POST https://your-domain.com/linear/webhook \
195
+ -H "Content-Type: application/json" \
196
+ -d '{"type":"test","action":"ping"}'
197
+ # Returns: "ok"
198
+ ```
199
+
200
+ That's it. Create an issue in Linear and watch the agent respond.
201
+
202
+ ---
203
+
204
+ ## Tunnel Setup (Cloudflare)
205
+
206
+ Linear delivers webhooks over the public internet. The gateway listens on `localhost:18789` and needs a public HTTPS endpoint. A [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) is the recommended approach — no open ports, no TLS cert management, no static IP required.
87
207
 
88
208
  ```mermaid
89
209
  flowchart TB
90
210
  subgraph Internet
91
211
  LW["Linear Webhooks<br/><i>Comment, Issue, AgentSession</i>"]
92
212
  LO["Linear OAuth<br/><i>callback redirect</i>"]
93
- You["You<br/><i>browser, curl</i>"]
94
213
  end
95
214
 
96
215
  subgraph CF["Cloudflare Edge"]
97
- TLS["TLS termination<br/>DDoS protection"]
216
+ TLS["TLS termination + DDoS protection"]
98
217
  end
99
218
 
100
219
  subgraph Server["Your Server"]
@@ -104,14 +223,13 @@ flowchart TB
104
223
 
105
224
  LW -- "POST /linear/webhook" --> TLS
106
225
  LO -- "GET /linear/oauth/callback" --> TLS
107
- You -- "HTTPS" --> TLS
108
226
  TLS -- "tunnel" --> CD
109
227
  CD -- "HTTP" --> GW
110
228
  ```
111
229
 
112
230
  **How it works:** `cloudflared` opens an outbound connection to Cloudflare's edge and keeps it alive. Cloudflare routes incoming HTTPS requests for your hostname back through the tunnel to `localhost:18789`. No inbound firewall rules needed.
113
231
 
114
- #### Install cloudflared
232
+ ### Install cloudflared
115
233
 
116
234
  ```bash
117
235
  # RHEL / Rocky / Alma
@@ -127,7 +245,7 @@ sudo apt update && sudo apt install -y cloudflared
127
245
  brew install cloudflare/cloudflare/cloudflared
128
246
  ```
129
247
 
130
- #### Authenticate with Cloudflare
248
+ ### Authenticate with Cloudflare
131
249
 
132
250
  ```bash
133
251
  cloudflared tunnel login
@@ -142,7 +260,7 @@ Cloudflare writes an origin certificate to `~/.cloudflared/cert.pem`. This cert
142
260
 
143
261
  > **Prerequisite:** Your domain must already be on Cloudflare (nameservers pointed to Cloudflare). If it's not, add it in the Cloudflare dashboard first.
144
262
 
145
- #### Create a tunnel
263
+ ### Create a tunnel
146
264
 
147
265
  ```bash
148
266
  cloudflared tunnel create openclaw-linear
@@ -150,7 +268,7 @@ cloudflared tunnel create openclaw-linear
150
268
 
151
269
  This outputs a **Tunnel ID** (UUID like `da1f21bf-856e-...`) and writes credentials to `~/.cloudflared/<TUNNEL_ID>.json`.
152
270
 
153
- #### DNS — point your hostname to the tunnel
271
+ ### DNS — point your hostname to the tunnel
154
272
 
155
273
  ```bash
156
274
  cloudflared tunnel route dns openclaw-linear linear.yourdomain.com
@@ -160,7 +278,7 @@ This creates a CNAME record in Cloudflare DNS: `linear.yourdomain.com → <TUNNE
160
278
 
161
279
  The hostname you choose here is what you'll use for **both** webhook URLs and the OAuth redirect URI in Linear. Make sure they all match.
162
280
 
163
- #### Configure the tunnel
281
+ ### Configure the tunnel
164
282
 
165
283
  Create `/etc/cloudflared/config.yml` (system-wide) or `~/.cloudflared/config.yml` (user):
166
284
 
@@ -176,7 +294,7 @@ ingress:
176
294
 
177
295
  The `ingress` rule routes all traffic for your hostname to the gateway on localhost. The catch-all `http_status:404` rejects requests for any other hostname.
178
296
 
179
- #### Run as a service
297
+ ### Run as a service
180
298
 
181
299
  ```bash
182
300
  # Install as system service (recommended for production)
@@ -190,7 +308,7 @@ To test without installing as a service:
190
308
  cloudflared tunnel run openclaw-linear
191
309
  ```
192
310
 
193
- #### Verify end-to-end
311
+ ### Verify end-to-end
194
312
 
195
313
  ```bash
196
314
  curl -s https://linear.yourdomain.com/linear/webhook \
@@ -201,134 +319,99 @@ curl -s https://linear.yourdomain.com/linear/webhook \
201
319
 
202
320
  > **Tip:** Keep the tunnel running at all times. If `cloudflared` stops, Linear webhook deliveries will fail silently — the gateway won't know about new issues, comments, or agent sessions until the tunnel is restored.
203
321
 
204
- ### 3. Create a Linear OAuth app
205
-
206
- Go to **Linear Settings > API > Applications** and create an app:
207
-
208
- - Set **Webhook URL** to `https://your-domain.com/linear/webhook`
209
- - Set **Redirect URI** to `https://your-domain.com/linear/oauth/callback`
210
- - Enable events: **Agent Sessions**, **Comments**, **Issues**
211
- - Save your **Client ID** and **Client Secret**
212
-
213
- > You also need a **workspace webhook** — run `openclaw openclaw-linear webhooks setup` to auto-provision it, or manually create one in Settings > API > Webhooks pointing to the same URL with **Comment + Issue** events enabled. Both webhooks are required.
214
-
215
- ### 4. Set credentials
216
-
217
- ```bash
218
- export LINEAR_CLIENT_ID="your_client_id"
219
- export LINEAR_CLIENT_SECRET="your_client_secret"
220
- ```
221
-
222
- For systemd services, add these to your unit file:
223
-
224
- ```ini
225
- [Service]
226
- Environment=LINEAR_CLIENT_ID=your_client_id
227
- Environment=LINEAR_CLIENT_SECRET=your_client_secret
228
- ```
229
-
230
- Then reload: `systemctl --user daemon-reload && systemctl --user restart openclaw-gateway`
231
-
232
- ### 5. Authorize
233
-
234
- ```bash
235
- openclaw openclaw-linear auth
236
- ```
237
-
238
- This opens your browser. Approve the authorization, then restart:
239
-
240
- ```bash
241
- systemctl --user restart openclaw-gateway
242
- ```
243
-
244
- ### 6. Verify
245
-
246
- ```bash
247
- openclaw openclaw-linear status
248
- ```
249
-
250
- You should see a valid token and connected status. Check the gateway logs for a clean startup:
322
+ ---
251
323
 
252
- ```
253
- Linear agent extension registered (agent: default, token: profile, orchestration: enabled)
254
- ```
324
+ ## How It Works — Step by Step
255
325
 
256
- Test the webhook endpoint:
326
+ A project goes through a complete lifecycle — from planning to implementation to closure. Here's every phase, what triggers it, and what you'll see in Linear.
257
327
 
258
- ```bash
259
- curl -s -X POST https://your-domain.com/linear/webhook \
260
- -H "Content-Type: application/json" \
261
- -d '{"type":"test","action":"ping"}'
262
- # Returns: "ok"
328
+ ```mermaid
329
+ flowchart LR
330
+ P["Plan<br/><i>(optional)</i>"] --> T["Triage<br/><i>(auto)</i>"]
331
+ T --> D["Dispatch<br/><i>(assign)</i>"]
332
+ D --> W["Worker<br/><i>(auto)</i>"]
333
+ W --> A["Audit<br/><i>(auto)</i>"]
334
+ A --> Done["Done ✔"]
335
+ A --> R["Rework<br/><i>(auto retry)</i>"]
336
+ A --> S["Escalate ⚠"]
337
+ R --> W
338
+ Done --> CL["Close<br/><i>(comment or auto)</i>"]
263
339
  ```
264
340
 
265
- That's it. Create an issue in Linear and watch the agent respond.
266
-
267
- ---
341
+ ### Phase 1: Planning (optional)
268
342
 
269
- ## How It Works Step by Step
343
+ **Trigger:** Comment "let's plan the features" on a project issue.
270
344
 
271
- Every issue moves through a clear pipeline. Here's the full interaction flow between you, Linear, the plugin, and the agents:
345
+ For larger work, the planner breaks a project into issues before any code is written. It enters **interview mode** asking questions, creating issues with user stories and acceptance criteria, and building a dependency graph in real time.
272
346
 
273
347
  ```mermaid
274
348
  sequenceDiagram
275
- participant You
349
+ actor Human
276
350
  participant Linear
277
351
  participant Plugin
278
- participant Agents
352
+ participant Planner as Planner Agent
353
+ participant Reviewer as Cross-Model Reviewer
354
+
355
+ Human->>Linear: "plan this project"
356
+ Plugin->>Planner: start interview
357
+ loop Until plan is complete
358
+ Planner-->>Linear: question
359
+ Human->>Linear: reply
360
+ Planner-->>Linear: create/update issues
361
+ end
362
+ Human->>Linear: "looks good"
363
+ Plugin->>Plugin: validate DAG + descriptions
364
+ Plugin->>Reviewer: cross-model audit
365
+ Reviewer-->>Plugin: recommendations
366
+ Plugin-->>Linear: summary + ask for approval
367
+ Human->>Linear: "approve plan"
368
+ Plugin-->>Linear: dispatch issues in dependency order
369
+ ```
279
370
 
280
- You->>Linear: Create issue
281
- Linear->>Plugin: Webhook (Issue.create)
282
- Plugin->>Agents: Triage agent
283
- Agents-->>Plugin: Estimate + labels
284
- Plugin-->>Linear: Update issue
285
- Plugin-->>Linear: Post assessment
371
+ The planner proactively asks for:
372
+ - **User stories** — "As a [role], I want [feature] so that [benefit]"
373
+ - **Acceptance criteria** — Given/When/Then format
374
+ - **UAT test scenarios** — How to manually verify the feature
286
375
 
287
- You->>Linear: Assign to agent
288
- Linear->>Plugin: Webhook (Issue.update)
289
- Plugin->>Agents: Worker agent
290
- Agents-->>Linear: Streaming status
291
- Plugin->>Agents: Audit agent (automatic)
292
- Agents-->>Plugin: JSON verdict
293
- Plugin-->>Linear: Result comment
376
+ **What you'll see in Linear:**
294
377
 
295
- You->>Linear: Comment "@kaylee review"
296
- Linear->>Plugin: Webhook (Comment)
297
- Plugin->>Agents: Kaylee agent
298
- Agents-->>Plugin: Response
299
- Plugin-->>Linear: Branded comment
300
- ```
378
+ > I've created 3 issues:
379
+ > - **PROJ-2:** Build search API endpoint (3 pts, blocks PROJ-3)
380
+ > - **PROJ-3:** Search results page (2 pts, blocked by PROJ-2)
381
+ > - **PROJ-4:** Autocomplete suggestions (1 pt, independent)
382
+ >
383
+ > Does that cover it? Should the autocomplete call a separate endpoint or share the search API?
301
384
 
302
- Here's what each stage does, and what you'll see in Linear:
385
+ When you say "looks good", the planner validates the plan (descriptions, estimates, no circular deps) and sends it to a **different AI model** for a cross-model review:
303
386
 
304
- ```mermaid
305
- flowchart LR
306
- A["Triage<br/><i>(auto)</i>"] --> B["Dispatch<br/><i>(you assign)</i>"]
307
- B --> C["Worker<br/><i>(auto)</i>"]
308
- C --> D["Audit<br/><i>(auto)</i>"]
309
- D --> E["Done ✔"]
310
- D --> F["Rework<br/><i>(auto retry)</i>"]
311
- D --> G["Needs Your<br/>Help ⚠<br/><i>(escalated)</i>"]
312
- F --> C
313
- ```
387
+ | Your primary model | Auto-reviewer |
388
+ |---|---|
389
+ | Claude / Anthropic | Codex |
390
+ | Codex / OpenAI | Gemini |
391
+ | Gemini / Google | Codex |
392
+ | Other (Kimi, Mistral, etc.) | Gemini |
393
+
394
+ After approval, issues are dispatched automatically in dependency order — up to 3 in parallel.
395
+
396
+ > `📊 Search Feature: 2/3 complete`
314
397
 
315
- ### Stage 1: Triage (automatic)
398
+ ### Phase 2: Triage (automatic)
316
399
 
317
- **Trigger:** You create a new issue.
400
+ **Trigger:** A new issue is created (manually or by the planner).
318
401
 
319
- The agent reads your issue, estimates story points, adds labels, sets priority, and posts an assessment comment — all within seconds. Triage runs in **read-only mode** (no file writes, no code execution) to prevent side effects.
402
+ The agent reads the issue, estimates story points, adds labels, sets priority, and posts an assessment comment — all within seconds. Triage runs in **read-only mode** (no file writes, no code execution) to prevent side effects.
320
403
 
321
404
  **What you'll see in Linear:**
322
405
 
323
406
  > **[Mal]** This looks like a medium complexity change — the search API integration touches both the backend GraphQL schema and the frontend query layer. I've estimated 3 points and tagged it `backend` + `frontend`.
324
407
 
325
- The estimate, labels, and priority are applied silently to the issue fields. You don't need to do anything.
408
+ The estimate, labels, and priority are applied silently to the issue fields.
326
409
 
327
- ### Stage 2: Dispatch (you assign the issue)
410
+ ### Phase 3: Dispatch (assign the issue)
328
411
 
329
- **Trigger:** You assign the issue to the agent (or it gets auto-assigned after planning).
412
+ **Trigger:** The issue is assigned to the agent (manually or auto-assigned after planning).
330
413
 
331
- The agent assesses complexity, picks an appropriate model, creates an isolated git worktree, and starts working.
414
+ The plugin assesses complexity, picks an appropriate model tier, creates an isolated git worktree, and starts the worker.
332
415
 
333
416
  **What you'll see in Linear:**
334
417
 
@@ -353,25 +436,23 @@ The agent assesses complexity, picks an appropriate model, creates an isolated g
353
436
  | Medium | claude-sonnet-4-6 | Standard features, multi-file changes |
354
437
  | High | claude-opus-4-6 | Complex refactors, architecture changes |
355
438
 
356
- ### Stage 3: Implementation (automatic)
439
+ ### Phase 4: Implementation (automatic)
357
440
 
358
- The worker agent reads the issue, plans its approach, writes code, and runs tests — all in the isolated worktree. You don't need to do anything during this stage.
441
+ The worker agent reads the issue, plans its approach, writes code, and runs tests — all in the isolated worktree.
359
442
 
360
443
  If this is a **retry** after a failed audit, the worker gets the previous audit feedback as context so it knows exactly what to fix.
361
444
 
362
- **Notifications you'll receive:**
363
- > `ENG-100 working on it (attempt 1)`
445
+ **Notification:** `ENG-100 working on it (attempt 1)`
364
446
 
365
- ### Stage 4: Audit (automatic)
447
+ ### Phase 5: Audit (automatic)
366
448
 
367
- After the worker finishes, a separate auditor agent independently verifies the work. The auditor checks the issue requirements against what was actually implemented.
449
+ After the worker finishes, a separate auditor agent independently verifies the work checking issue requirements against what was actually implemented, running tests, and reviewing the diff.
368
450
 
369
451
  This is **not optional** — the worker cannot mark its own work as done. The audit is triggered by the plugin, not by the AI.
370
452
 
371
- **Notifications you'll receive:**
372
- > `ENG-100 checking the work...`
453
+ **Notification:** `ENG-100 checking the work...`
373
454
 
374
- ### Stage 5: Verdict
455
+ ### Phase 6: Verdict
375
456
 
376
457
  The audit produces one of three outcomes:
377
458
 
@@ -399,7 +480,7 @@ The issue is marked done automatically. A summary is posted.
399
480
 
400
481
  #### Fail (retries left) — Automatic rework
401
482
 
402
- The worker gets the audit feedback and tries again. You don't need to do anything.
483
+ The worker gets the audit feedback and tries again automatically.
403
484
 
404
485
  **What you'll see in Linear:**
405
486
 
@@ -417,9 +498,9 @@ The worker gets the audit feedback and tries again. You don't need to do anythin
417
498
 
418
499
  **Notification:** `ENG-100 needs more work (attempt 1). Issues: missing validation, no empty query test`
419
500
 
420
- #### Fail (no retries left) — Needs your help
501
+ #### Fail (no retries left) — Escalation
421
502
 
422
- After all retries are exhausted (default: 3 attempts), the issue is escalated to you.
503
+ After all retries are exhausted (default: 3 attempts), the issue is escalated.
423
504
 
424
505
  **What you'll see in Linear:**
425
506
 
@@ -440,25 +521,137 @@ After all retries are exhausted (default: 3 attempts), the issue is escalated to
440
521
 
441
522
  **Notification:** `🚨 ENG-100 needs your help — couldn't fix it after 3 tries`
442
523
 
443
- **What you can do:**
524
+ **Options:**
444
525
  1. **Clarify the issue** — Add more detail to the description, then re-assign to try again
445
526
  2. **Fix it yourself** — The agent's work is in the worktree, ready to edit
446
527
  3. **Force retry** — `/dispatch retry ENG-100`
447
528
  4. **Check logs** — Worker output in `.claw/worker-*.md`, audit verdicts in `.claw/audit-*.json`
448
529
 
449
- ### Stage 6: Timeout (if the agent goes silent)
530
+ ### Phase 7: Closure
531
+
532
+ **Trigger:** Comment "close this", "mark as done", or "this is resolved" on any issue.
450
533
 
451
- If the agent produces no output for 2 minutes (configurable), the watchdog kills it and retries once. If the retry also times out, the issue is escalated.
534
+ The plugin generates a closure report and transitions the issue to completed. This is a **static action** the plugin orchestrates the API calls directly, the agent only writes the report text.
535
+
536
+ ```mermaid
537
+ flowchart LR
538
+ A["'close this'"] --> B["Fetch issue details"]
539
+ B --> C["Generate closure report<br/><i>(read-only agent)</i>"]
540
+ C --> D["Transition → completed"]
541
+ D --> E["Post report to issue"]
542
+ ```
452
543
 
453
544
  **What you'll see in Linear:**
454
545
 
455
- > ## Agent Timed Out
546
+ > ## Closed
456
547
  >
457
- > The agent stopped responding for over 120s and was automatically restarted, but the retry also failed.
548
+ > This issue has been reviewed and closed.
458
549
  >
459
- > **What to do:** Re-assign this issue to try again. If it keeps timing out, the issue might be too complex try breaking it into smaller issues.
550
+ > **Summary:** The search API endpoint was implemented with pagination, input validation, and error handling. All 14 tests pass. The frontend search page renders results correctly.
551
+
552
+ ### Watchdog & timeout recovery
553
+
554
+ Every running agent has an inactivity watchdog. If the agent goes silent — no text, no tool calls, no thinking — the watchdog kills it.
555
+
556
+ ```
557
+ Agent runs ─────────── output ──→ timer resets (120s default)
558
+ output ──→ timer resets
559
+ ...
560
+ silence ─→ 120s passes ─→ KILL
561
+
562
+ ┌────────┴────────┐
563
+ ▼ ▼
564
+ Retry (auto) Already retried?
565
+ │ │
566
+ ▼ ▼
567
+ Agent runs again STUCK → you're notified
568
+ ```
569
+
570
+ **What resets the timer:** any agent output — partial text, tool call start/result, reasoning stream, or error.
571
+
572
+ **What triggers a kill:** LLM hangs, API timeouts, CLI lockups, rate limiting — anything that causes the agent to stop producing output.
573
+
574
+ **After a kill:**
575
+ 1. First timeout → automatic retry (new attempt, same worktree)
576
+ 2. Second timeout → dispatch transitions to `stuck`, Linear comment posted with remediation steps, you get a notification
577
+
578
+ **The "Agent Timed Out" comment includes:**
579
+ - `/dispatch retry ENG-100` command to try again
580
+ - Suggestion to break the issue into smaller pieces
581
+ - How to increase `inactivitySec` in agent profiles
582
+ - Path to `.claw/log.jsonl` for debugging
583
+
584
+ **Configure per agent** in `~/.openclaw/agent-profiles.json`:
585
+ ```json
586
+ { "agents": { "mal": { "watchdog": { "inactivitySec": 180 } } } }
587
+ ```
588
+
589
+ ### Audit rework loop
590
+
591
+ When the auditor finds problems, it doesn't just fail — it tells the worker exactly what's wrong, and the worker tries again automatically.
592
+
593
+ ```
594
+ Worker implements ──→ Auditor reviews
595
+
596
+ ┌────┴────┐
597
+ ▼ ▼
598
+ PASS FAIL
599
+ │ │
600
+ ▼ ▼
601
+ Done Gaps extracted
602
+
603
+
604
+ Worker gets gaps as context ──→ "PREVIOUS AUDIT FAILED:
605
+ │ - Missing input validation
606
+ │ - No test for empty query"
607
+
608
+ Rework attempt (same worktree)
609
+
610
+ ┌────┴────┐
611
+ ▼ ▼
612
+ PASS FAIL again?
613
+ │ │
614
+ ▼ ▼
615
+ Done Retries left?
616
+
617
+ ┌────┴────┐
618
+ ▼ ▼
619
+ Retry STUCK → you're notified
620
+ ```
621
+
622
+ **How gaps flow back:**
623
+ 1. Auditor returns a structured verdict: `{ pass: false, gaps: ["missing validation", "no empty query test"], criteria: [...] }`
624
+ 2. Pipeline extracts the `gaps` array
625
+ 3. Next worker prompt gets a "PREVIOUS AUDIT FAILED" addendum with the gap list
626
+ 4. Worker sees exactly what to fix — no guessing
460
627
 
461
- **Notification:** `⚡ ENG-100 timed out (no activity for 120s). Will retry.`
628
+ **What you control:**
629
+ - `maxReworkAttempts` (default: `2`) — how many audit failures before escalation
630
+ - After max attempts, issue goes to `stuck` with reason `audit_failed_Nx`
631
+ - You get a Linear comment with what went wrong and a notification
632
+
633
+ **What the worker sees on rework:**
634
+ ```
635
+ PREVIOUS AUDIT FAILED — fix these gaps before proceeding:
636
+ 1. Missing input validation on the search endpoint
637
+ 2. No test for empty query string
638
+
639
+ Your previous work is still in the worktree. Fix the issues above and run tests again.
640
+ ```
641
+
642
+ **Artifacts per attempt:** Each rework cycle writes `worker-{N}.md` and `audit-{N}.json` to `.claw/`, so you can see what happened at every attempt.
643
+
644
+ ### Project-level progress
645
+
646
+ When issues are dispatched from a plan, you get project-level progress tracking:
647
+
648
+ > `📊 Search Feature: 2/3 complete`
649
+
650
+ When everything is done:
651
+
652
+ > `✅ Search Feature: complete (3/3 issues)`
653
+
654
+ If an issue gets stuck, dependent issues are blocked and you're notified.
462
655
 
463
656
  ### What's in the worktree
464
657
 
@@ -572,73 +765,16 @@ The webhook handler prevents double-processing through a two-tier guard system:
572
765
 
573
766
  ---
574
767
 
575
- ## Planning a Project
576
-
577
- For larger work, the planner helps you break a project into issues with dependencies, then dispatches them automatically.
578
-
579
- ### Start planning
580
-
581
- Comment on any issue that belongs to a Linear project — use natural language:
768
+ ## Planning Validation Details
582
769
 
583
- > "let's plan out the features for this project"
770
+ See [Phase 1: Planning](#phase-1-planning-optional) for the full walkthrough. This section covers the validation rules that run when you say "finalize plan".
584
771
 
585
- The planner enters **interview mode** and asks you questions one at a time:
772
+ ### Validation checks
586
773
 
587
- > I'm entering planning mode for **Search Feature**. I'll interview you about the features you want to build, then structure everything into Linear issues.
588
- >
589
- > Let's start — what is this project about, and what are the main feature areas?
590
-
591
- ### Build the plan
592
-
593
- Reply with your ideas. The planner creates issues with **user stories** and **acceptance criteria**, sets dependencies, and asks follow-up questions:
594
-
595
- > I've created 3 issues:
596
- > - **PROJ-2:** Build search API endpoint (3 pts, blocks PROJ-3)
597
- > - **PROJ-3:** Search results page (2 pts, blocked by PROJ-2)
598
- > - **PROJ-4:** Autocomplete suggestions (1 pt, independent)
599
- >
600
- > For PROJ-2, here's what I wrote for acceptance criteria:
601
- > - *Given* a user sends a search query, *When* results exist, *Then* they are returned with pagination
602
- >
603
- > Does that cover it? Should the autocomplete call a separate endpoint or share the search API?
604
-
605
- The planner proactively asks for:
606
- - **User stories** — "As a [role], I want [feature] so that [benefit]"
607
- - **Acceptance criteria** — Given/When/Then format
608
- - **UAT test scenarios** — How to manually verify the feature
609
-
610
- Keep replying until the plan looks right. The planner updates issues in real time.
611
-
612
- ### Finalize & Cross-Model Review
613
-
614
- When you're happy, say something like "looks good" or "finalize plan". The planner runs a validation check:
615
774
  - Every issue has a description (50+ characters) with acceptance criteria
616
775
  - Every non-epic issue has an estimate and priority
617
776
  - No circular dependencies in the DAG
618
777
 
619
- **If validation passes, a cross-model review runs automatically:**
620
-
621
- > ## Plan Passed Checks
622
- >
623
- > **3 issues** with valid dependency graph.
624
- >
625
- > Let me have **Codex** audit this and make recommendations.
626
-
627
- A different AI model (always the complement of your primary model) reviews the plan for gaps:
628
-
629
- | Your primary model | Auto-reviewer |
630
- |---|---|
631
- | Claude / Anthropic | Codex |
632
- | Codex / OpenAI | Gemini |
633
- | Gemini / Google | Codex |
634
- | Other (Kimi, Mistral, etc.) | Gemini |
635
-
636
- After the review, the planner summarizes recommendations and asks you to approve:
637
-
638
- > Codex suggested adding error handling scenarios to PROJ-2 and noted PROJ-4 could be split into frontend/backend. I've updated PROJ-2's acceptance criteria. The PROJ-4 split is optional — your call.
639
- >
640
- > If you're happy with this plan, say **approve plan** to start dispatching.
641
-
642
778
  **If validation fails:**
643
779
 
644
780
  > ## Plan Audit Failed
@@ -652,19 +788,7 @@ After the review, the planner summarizes recommendations and asks you to approve
652
788
  >
653
789
  > Please address these issues, then say "finalize plan" again.
654
790
 
655
- Fix the issues and try again. You can also say "cancel" or "stop planning" to exit without dispatching.
656
-
657
- ### DAG dispatch progress
658
-
659
- After approval, issues are assigned to the agent automatically in dependency order. Up to 3 issues run in parallel.
660
-
661
- > `📊 Search Feature: 2/3 complete`
662
-
663
- When everything is done:
664
-
665
- > `✅ Search Feature: complete (3/3 issues)`
666
-
667
- If an issue gets stuck (all retries failed), dependent issues are blocked and you'll be notified.
791
+ Fix the issues and try again. Say "cancel" or "stop planning" to exit without dispatching.
668
792
 
669
793
  ---
670
794
 
@@ -1113,7 +1237,7 @@ For programmatic access, the plugin registers these RPC methods:
1113
1237
  If an agent goes silent (LLM timeout, API hang, CLI lockup), the watchdog handles it automatically:
1114
1238
 
1115
1239
  1. No output for `inactivitySec` → kill and retry once
1116
- 2. Second silence → escalate to stuck (you get notified, see [Stage 6](#stage-6-timeout-if-the-agent-goes-silent) above)
1240
+ 2. Second silence → escalate to stuck (you get notified, see [Timeout recovery](#timeout-recovery) above)
1117
1241
 
1118
1242
  | Setting | Default | What it controls |
1119
1243
  |---|---|---|
@@ -1146,26 +1270,35 @@ Agents call `linear_issues` with typed JSON parameters. The tool wraps the Linea
1146
1270
  | `list_states` | Get available workflow states for a team | `teamId` |
1147
1271
  | `list_labels` | Get available labels for a team | `teamId` |
1148
1272
 
1149
- **Sub-issues:** Use `action="create"` with `parentIssueId` to create sub-issues under an existing issue. The new issue inherits `teamId` and `projectId` from its parent automatically. Agents are instructed to break large work into sub-issues for granular trackingany task with multiple distinct deliverables should be decomposed. Auditors can also create sub-issues for remaining work when an implementation is partial.
1273
+ **Sub-issues:** Use `action="create"` with `parentIssueId` to create sub-issues under an existing issue. The new issue inherits `teamId` and `projectId` from its parent automatically. Only orchestrators on triaged issues have `create` accessworkers and auditors cannot create issues.
1150
1274
 
1151
1275
  ### `spawn_agent` / `ask_agent` — Multi-agent orchestration
1152
1276
 
1153
1277
  Delegate work to other crew agents. `spawn_agent` is fire-and-forget (parallel), `ask_agent` waits for a reply (synchronous). Disabled with `enableOrchestration: false`.
1154
1278
 
1279
+ Sub-agents run in their own context — they do **not** share the parent's worktree or get `code_run` access. They're useful for reasoning, research, and coordination (e.g., "ask Inara how to phrase this error message") but cannot directly modify code. To give a sub-agent code context, include the relevant snippets in the task message.
1280
+
1155
1281
  ### `dispatch_history` — Recent dispatch context
1156
1282
 
1157
1283
  Returns recent dispatch activity. Agents use this for situational awareness when working on related issues.
1158
1284
 
1159
1285
  ### Access model
1160
1286
 
1161
- Not all agents get write access. The webhook prompts enforce this:
1287
+ Tool access varies by context. Orchestrators get the full toolset; workers and auditors are restricted:
1162
1288
 
1163
- | Context | `linear_issues` access | `code_run` |
1164
- |---|---|---|
1165
- | Triaged issue (In Progress, etc.) | Full (read + create + update + comment) | Yes |
1166
- | Untriaged issue (Backlog, Triage) | Read only | Yes |
1167
- | Auditor | Full (read + create + update + comment) | Yes |
1168
- | Worker (inside `code_run`) | None | N/A |
1289
+ | Context | `linear_issues` | `code_run` | `spawn_agent` / `ask_agent` | Filesystem |
1290
+ |---|---|---|---|---|
1291
+ | Orchestrator (triaged issue) | Full (read, create, update, comment) | Yes | Yes | Read + write |
1292
+ | Orchestrator (untriaged issue) | Read only | Yes | Yes | Read + write |
1293
+ | Worker | None | None | None | Read + write |
1294
+ | Auditor | Prompt-constrained (has tool, instructed to verify only) | None | None | Read only (by prompt) |
1295
+ | Sub-agent (spawn/ask) | None | None | Yes (can chain) | Inherited from parent |
1296
+
1297
+ **Workers** run inside the coding backend (Codex, Claude, Gemini) — they have full filesystem access to the worktree but no Linear tools and no orchestration. Their only job is to write code and return a summary.
1298
+
1299
+ **Auditors** have access to `linear_issues` (the tool is registered) but are instructed via prompt to verify only — they return a JSON verdict, not code or issue mutations. Write access is not enforced at the tool level.
1300
+
1301
+ **Sub-agents** spawned via `spawn_agent`/`ask_agent` run in their own session with no worktree access and no `code_run`. They're information workers — useful for reasoning and coordination, not code execution.
1169
1302
 
1170
1303
  ---
1171
1304
 
@@ -1302,14 +1435,14 @@ The full dispatch flow for implementing an issue:
1302
1435
 
1303
1436
  ```mermaid
1304
1437
  flowchart TD
1305
- A["Issue assigned to app user"] --> B["1. Assess complexity tier<br/><i>junior / medior / senior</i>"]
1438
+ A["Issue assigned to app user"] --> B["1. Assess complexity tier<br/><i>small / medium / high</i>"]
1306
1439
  B --> C["2. Create isolated git worktree"]
1307
1440
  C --> D["3. Register dispatch in state file"]
1308
1441
  D --> E["4. Write .claw/manifest.json"]
1309
1442
  E --> F["5. Notify: dispatched as tier"]
1310
1443
 
1311
- F --> W["6. Worker phase<br/><i>code_run: YES, linear_issues: NO</i><br/>Build prompt → implement → save to .claw/"]
1312
- W -->|"plugin code — automatic"| AU["7. Audit phase<br/><i>code_run: YES, linear_issues: READ+WRITE</i><br/>Verify criteria → run tests → JSON verdict"]
1444
+ F --> W["6. Worker phase<br/><i>filesystem: full, linear_issues: NO</i><br/>Build prompt → implement → save to .claw/"]
1445
+ W -->|"plugin code — automatic"| AU["7. Audit phase<br/><i>filesystem: read, linear_issues: prompt-constrained</i><br/>Verify criteria → inspect diff → JSON verdict"]
1313
1446
 
1314
1447
  AU --> V{"8. Verdict"}
1315
1448
  V -->|PASS| DONE["Done ✔<br/>updateIssue → notify"]
@@ -1442,7 +1575,7 @@ This is separate from the main `doctor` because each live test spawns a real CLI
1442
1575
 
1443
1576
  ### Unit tests
1444
1577
 
1445
- 551 tests covering the full pipeline — triage, dispatch, audit, planning, intent classification, native issue tools, cross-model review, notifications, and infrastructure:
1578
+ 1000+ tests covering the full pipeline — triage, dispatch, audit, planning, intent classification, native issue tools, cross-model review, notifications, watchdog, and infrastructure:
1446
1579
 
1447
1580
  ```bash
1448
1581
  cd ~/claw-extensions/linear