@lifeaitools/rdc-skills 0.27.0 → 0.29.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rdc",
3
- "version": "0.27.0",
3
+ "version": "0.29.0",
4
4
  "description": "RDC typed-agent dispatch skill suite for Claude Code — plan, build, review, overnight unattended builds with work-item tracking and TDD enforcement.",
5
5
  "author": {
6
6
  "name": "LIFEAI",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/rdc-skills",
3
- "version": "0.27.0",
3
+ "version": "0.29.0",
4
4
  "description": "RDC typed-agent dispatch skill suite for Claude Code - plan, build, review, overnight builds",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -44,34 +44,100 @@ not an evasion.
44
44
 
45
45
  ---
46
46
 
47
+ ## The boundary — you are in a CONVERSATION, not a build
48
+
49
+ **Do not write to the repository during a collab. Not one file.**
50
+
51
+ This is not a restriction on you; it is what a collab *is*. Your deliverable is
52
+ the **reply**. If settling the point requires code, config, or a document change,
53
+ say what should change — the change itself happens afterward, in a session built
54
+ for it (`rdc:build`, an isolated worktree agent, or you working your own lane
55
+ against a work item).
56
+
57
+ **Why it matters to you specifically:** a peer that tries to write mid-conversation
58
+ can end up holding finished, correct work it cannot deliver — refused by a write
59
+ guard, then refused permission to stop by a gate demanding the delivery evidence
60
+ that guard just made impossible. That happened on 2026-08-14 and cost a complete
61
+ negotiation result. **Your reasoning in the reply is always deliverable. A file
62
+ write may not be.**
63
+
64
+ ---
65
+
47
66
  ## What you owe BACK — your responsibilities
48
67
 
68
+ ### 0. Answer the `status` handshake honestly, by PROBING.
69
+
70
+ Before the real conversation starts you will be asked for `COLLAB-STATUS/1`.
71
+ Emit every field. **Capability fields must be probed, not assumed** — actually
72
+ attempt the seam and report the literal result.
73
+
74
+ ```
75
+ COLLAB-STATUS/1
76
+ agent: <you>
77
+ engine_version: <version>
78
+ skill_version: <rdc-skills version>
79
+
80
+ --- managed identity (all 8; an absent field IS the diagnosis) ---
81
+ lane: <lane | NONE>
82
+ role: worker | supervisor | NONE
83
+ repo_identity: <repo>
84
+ owner_pid: <pid | NONE>
85
+ owner_start_fingerprint: <present | ABSENT>
86
+ session_id: <id | NONE>
87
+ lease_epoch: <epoch | NONE>
88
+ owner_token: present | ABSENT ← NEVER the value
89
+
90
+ --- capability (PROBED — name the probe) ---
91
+ can_write: yes | no | unknown probe: <what you actually ran>
92
+ can_commit: yes | no | unknown probe: <…>
93
+ can_push: yes | no | unknown probe: <…>
94
+
95
+ --- position ---
96
+ cwd: <path> branch: <branch> head: <sha> dirty: <n tracked files>
97
+ ahead/behind: <n>/<n> vs <named upstream>
98
+
99
+ --- services ---
100
+ codeflow: <status> clauth: <status> work_items: reachable | no
101
+ ```
102
+
103
+ **Rules that make this worth asking for:**
104
+
105
+ - **Never emit the `owner_token` value.** `present`/`ABSENT` only — this output
106
+ lands in transcripts and logs.
107
+ - **`unknown` is an honest answer. `yes` without a probe is not.** If you could
108
+ not test the seam, say `unknown` and name why. A capability you assumed and
109
+ cannot demonstrate is precisely the claim this protocol exists to eliminate.
110
+ - **Report the lane you are ACTUALLY in**, not the one you were asked to be in.
111
+ If they differ, your session identity is poisoned — say so in the same reply.
112
+ That one line saves the initiator an entire wasted round.
113
+ - A missing identity field is not an embarrassment to smooth over. It is the
114
+ most useful thing you can tell the initiator.
115
+
49
116
  ### 1. Answer in the required format. Nothing outside it.
50
117
 
51
118
  If the dispatch gives you a contract, use it verbatim. Prose around the blocks
52
119
  is not helpful — it is what the format exists to remove.
53
120
 
54
- **Negotiate — one block per point:**
121
+ **One block per point:**
55
122
 
56
123
  ```
57
124
  POINT <n>: AGREE | AGREE-WITH-AMENDMENT | DISAGREE
58
- EDIT: <the exact section and change you will make, or NONE>
125
+ EDIT: <the exact section and change that SHOULD be made, or NONE — describe it, do not make it>
59
126
  REASON: <one sentence — only if AMENDMENT or DISAGREE>
60
127
  ```
61
128
 
62
- **Delegate:**
129
+ **For a factual question rather than a proposal:**
63
130
 
64
131
  ```
65
- STATUS: DONE | PARTIAL | BLOCKED
66
- CHANGED: <file paths, or NONE>
132
+ FINDING <n>: <the answer, one sentence>
67
133
  EVIDENCE: <command run + literal result — exit code, row count, probe status>
68
- BLOCKED: <what stopped you, or NONE>
134
+ CONFIDENCE: VERIFIED | INFERRED | UNKNOWN
69
135
  ```
70
136
 
71
137
  **Always close with:**
72
138
 
73
139
  ```
74
- OWNER: <who writes the change — exactly one agent>
140
+ OWNER: <who lands the resulting Decision or work item — exactly one agent>
75
141
  BLOCKED: <what you cannot do from where you are, or NONE>
76
142
  ```
77
143
 
@@ -87,11 +153,11 @@ answer in the reply body. Do not let it die inside a failed tool call.
87
153
 
88
154
  ### 3. Do not write outside your own lane or scope.
89
155
 
90
- - **Codex:** you must be running in a Codex-owned lane (`x-codex-N`, `x-codex-sv`).
91
- If the initiator invoked you with its own cwd, every write will be refused with
156
+ - **Codex:** if you were started by `codex exec` (headless), you CANNOT write in any lane — your managed identity was never minted and `-C` does not create it. Report `BLOCKED: headless codex exec has no lane claim` and put your answer in the reply. If you were started by the launcher in a Codex-owned lane (`x-codex-N`, `x-codex-sv`), you can write, but not during a collab.
157
+ A session created in the wrong cwd is poisoned for its whole life `resume` replays the recorded identity. Writes are refused with
92
158
  `CODEX MANAGED LANE: App Local must use an owned managed Codex lane`. That is a
93
- **dispatch defect, not your failure** — report it as `BLOCKED: wrong lane
94
- attachment, re-dispatch with -C <my-lane>` and do not attempt a workaround.
159
+ **dispatch defect, not your failure** — report it as `BLOCKED: poisoned session identity, start a NEW session in
160
+ my lane` `-C` will NOT repair it. Do not attempt a workaround.
95
161
  - **Claude agents:** if you will commit, you must have been given
96
162
  `isolation: "worktree"` as a real tool parameter. A sentence in your prompt
97
163
  claiming isolation is inert.
@@ -155,6 +221,7 @@ cannot act on a guess it has to verify.
155
221
  | Filing a settled agreement as a lesson | Buries a queryable Decision |
156
222
  | Going silent when blocked | Indistinguishable from being dead |
157
223
  | Editing a document you do not own | Lost work, no error, no trace |
224
+ | Writing ANY file during a collab | Not your job here — the reply is the deliverable |
158
225
  | Committing to whatever branch you happen to be on | The change strands where nobody looks for it |
159
226
  | Answering an easier adjacent question | The real point stays open and looks settled |
160
227
  | Attempting a workaround for a guard block | The guard is usually right; the dispatch is usually wrong |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: rdc:collab
3
- description: "Usage `rdc:collab <collaborator> [mode] <topic>` — Structured collaboration with another agent: Codex, a local LLM, a Claude agent, or a claude.ai session. Modes: negotiate (converge on a decision), delegate (hand off work), listen (claude.ai relay). Every dispatch carries a response contract."
3
+ description: "Usage `rdc:collab <collaborator> [inbound] <topic>` — Structured agent-to-agent CONVERSATION with Codex, a local LLM, a Claude agent, or a claude.ai session. Converges on a decision and never writes to the repo — work that needs writing becomes a work item for rdc:build. Run `rdc:collab status <peer>` first — both sides emit probed capability state. Every dispatch carries a response contract."
4
4
  ---
5
5
 
6
6
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
@@ -11,9 +11,50 @@ description: "Usage `rdc:collab <collaborator> [mode] <topic>` — Structured co
11
11
 
12
12
  # /rdc:collab — Structured Agent-to-Agent Collaboration
13
13
 
14
- > `rdc:collab <collaborator> [mode] <topic>`
14
+ > `rdc:collab <collaborator> [inbound] <topic>`
15
15
  > Collaborators: `codex` · `local-llm` · `claude-agent` · `claude-ai`
16
- > Modes: `negotiate` (default for a decision) · `delegate` · `listen`
16
+ > Direction: outbound (default, you dispatch) · `inbound` (claude.ai relay, peer initiates)
17
+
18
+ ---
19
+
20
+ ## Collab is CONVERSATION. It never writes to the repo.
21
+
22
+ **There is one mode, because there was only ever one.** v0.27.0 shipped a
23
+ `delegate` mode whose contract asked the peer for `CHANGED: <file paths>` — an
24
+ instruction to go mutate the repo and report back. Handing work off is a real
25
+ need; routing it through a *conversation channel* is a category error. Work goes
26
+ to `rdc:build`, to an `Agent` with `isolation: "worktree"` as a real parameter, or
27
+ to a launcher-started session working its own lane against a work item. Those have
28
+ isolation, a work item, review, and landing. A chat channel has none of them.
29
+
30
+ **This is a design boundary, not a workaround for a broken door.** A separate,
31
+ real constraint exists — a headless `codex exec` peer currently cannot write at
32
+ all (see the note under Step 1) — but that constraint is a **bug being fixed**,
33
+ not the reason for this rule. Even once headless Codex can write, work handoff
34
+ still goes through the build path. Do not read the boundary as "collab can't
35
+ write"; read it as "collab isn't where writing belongs."
36
+
37
+ **The boundary:**
38
+
39
+ | Collab does | Collab never does |
40
+ |---|---|
41
+ | Ask, answer, converge, disagree | Edit a file |
42
+ | Produce a **Decision** for the governing document | Commit or push |
43
+ | Produce a **work item** when writing is required | Build, deploy, or land |
44
+ | Return findings, verdicts, evidence *as text* | Claim to have changed anything |
45
+
46
+ **When code must be written, collab is over.** Its output is a work item, and the
47
+ writing happens where writing belongs — `rdc:build`, an `Agent` with
48
+ `isolation: "worktree"` as a real parameter, or the peer working its own lane
49
+ against that item. A conversation channel is not a build channel.
50
+
51
+ **Why this is structural, not a style rule.** Because collab never mutates, a
52
+ collab session is non-mutating *by definition* — there is no mode to select
53
+ wrongly and no flag to leave on. Delivery gates (truth-gate, completion gate,
54
+ CodeFlow preflight) have nothing to gate, and safety guards (credential exposure,
55
+ cross-tree write, push-main, lane identity) remain fully live because nothing
56
+ here goes near them. The peer that tries to write is not blocked by policy; it is
57
+ simply doing something this skill never asks for.
17
58
 
18
59
  ---
19
60
 
@@ -75,8 +116,11 @@ diagnosis ladder in order and stop at the first hit:
75
116
  2. **Did it exit, and with what?** A non-zero exit or exit 143 (killed) is a
76
117
  result, not silence. Read it.
77
118
  3. **Was it guard-blocked?** Grep the output for a `deny`/`Blocked` line. The
78
- `CODEX MANAGED LANE` block is the common one and is a *dispatch* defect
79
- (wrong `-C`), not a peer failurefix and re-dispatch once.
119
+ `CODEX MANAGED LANE` block is the common one and is a *dispatch* defect, not a
120
+ peer failure. **It is not fixed by `-C`**the session's identity was recorded
121
+ at creation and `resume` replays it, so a mis-started session is poisoned for
122
+ life. Start a **new** session in the right lane. Had `status` run first
123
+ (Step 0.5), this would have been visible before any content was sent.
80
124
  4. **Is the session still addressable?** A stale `resume <session-id>`, a stopped
81
125
  chitchat session, or a dead local-LLM endpoint all present as silence.
82
126
  5. **Did it answer somewhere you are not reading?** A peer that cannot write its
@@ -93,13 +137,83 @@ outliving its dispatch is noise, and noise is how a real stall gets ignored.
93
137
  ## Step 0 — Parse arguments
94
138
 
95
139
  ```
96
- rdc:collab <collaborator> [mode] <topic…>
97
- rdc:collab --session <id> legacy form, implies `claude-ai listen`
140
+ rdc:collab status <collaborator> handshake; run BEFORE round 1
141
+ rdc:collab <collaborator> [inbound] <topic…>
142
+ rdc:collab --session <id> ← legacy form, implies `claude-ai inbound`
98
143
  ```
99
144
 
100
145
  - No collaborator → list active chitchat sessions and available engines, then stop.
101
- - No mode → `negotiate` if the topic names a document, decision, plan, or review;
102
- `delegate` if it names work to perform; `listen` for `claude-ai` with `--session`.
146
+ - `inbound` (or the legacy `--session <id>` form) the peer initiates; see the
147
+ claude.ai relay section. Same conversation, opposite direction.
148
+ - **If the topic names work to be performed rather than a question to settle, this
149
+ is the wrong skill.** Create the work item and use `rdc:build` / `rdc:fixit`.
150
+
151
+ ---
152
+
153
+ ## Step 0.5 — `status` handshake (run BEFORE round 1)
154
+
155
+ `rdc:collab status <collaborator>` — both sides emit their state. **This is a
156
+ precondition, not a debugging command.** Reaching for it after a failure is
157
+ already too late; the point is to never dispatch into a session that cannot
158
+ deliver.
159
+
160
+ **The probe rule — the whole value of this step.** Every capability field is
161
+ **PROBED, never asserted.** A peer that *reports* `can_write: yes` from an
162
+ assumption has produced another unverified capability claim, which is the defect
163
+ class this entire protocol exists to remove. `-C` "should" have set lane identity
164
+ too. Probe the seam, report the literal result, and if you cannot probe, say
165
+ `unknown` — never `yes`.
166
+
167
+ ### `COLLAB-STATUS/1` payload
168
+
169
+ ```
170
+ COLLAB-STATUS/1
171
+ agent: codex | claude-code | claude-ai | local-llm
172
+ engine_version: <version>
173
+ skill_version: <rdc-skills version>
174
+
175
+ --- managed identity (the 8 fields; absent ones are the diagnosis) ---
176
+ lane: <lane | NONE>
177
+ role: worker | supervisor | NONE
178
+ repo_identity: <repo>
179
+ owner_pid: <pid | NONE>
180
+ owner_start_fingerprint: <present | ABSENT>
181
+ session_id: <id | NONE>
182
+ lease_epoch: <epoch | NONE>
183
+ owner_token: present | ABSENT ← NEVER the value
184
+
185
+ --- capability (PROBED — state the probe used) ---
186
+ can_write: yes | no | unknown probe: <what you actually ran>
187
+ can_commit: yes | no | unknown probe: <…>
188
+ can_push: yes | no | unknown probe: <…>
189
+
190
+ --- position ---
191
+ cwd: <path>
192
+ branch: <branch>
193
+ head: <sha>
194
+ dirty: <n tracked files>
195
+ ahead/behind: <n>/<n> vs <named upstream>
196
+
197
+ --- services ---
198
+ codeflow: <status> clauth: <status> work_items: reachable | no
199
+ ```
200
+
201
+ **`owner_token` reports `present`/`ABSENT` only. Never emit the value** — status
202
+ output lands in transcripts and logs.
203
+
204
+ ### How the initiator reads it
205
+
206
+ | Signal | Meaning | Action |
207
+ |---|---|---|
208
+ | `lane: NONE` or missing identity fields | No managed identity was ever minted | Conversation only. Do not name this peer as writer. |
209
+ | `can_write: no` | Structurally read-only right now | Fine for collab. Name someone else to land the outcome. |
210
+ | `can_write: unknown` | It could not probe | Treat as `no` until proven. Never as `yes`. |
211
+ | `lane` ≠ the lane you dispatched to | **Poisoned session** — identity is recorded at creation and `resume` replays it | Start a NEW session. `-C` will not repair it. |
212
+ | `dirty` > 0 on a peer you are about to name as writer | Pre-existing uncommitted work | Surface it before it gets swept into your commit |
213
+
214
+ **Mismatch between what you dispatched and what `status` reports is the single
215
+ highest-value signal in this protocol.** It is exactly the failure that cost a
216
+ full negotiation on 2026-08-14, and it is visible in one line here.
103
217
 
104
218
  ---
105
219
 
@@ -110,7 +224,28 @@ most common failure and it fails at the guard layer, not the prompt layer.
110
224
 
111
225
  | Collaborator | Invocation | Isolation requirement | Known failure mode |
112
226
  |---|---|---|---|
113
- | **`codex`** | `codex exec -C <its-lane> "<msg>"` · resume: `codex exec -C <its-lane> resume <session-id> "<msg>"` | **MUST run with `-C` pointing at a Codex-owned lane** (`x-codex-N` or `x-codex-sv`) | Inheriting your cwd attaches Codex to *your* lane; `managedAppAttachmentDecision()` refuses every write with `CODEX MANAGED LANE: App Local must use an owned managed Codex lane`. The guard is correct fix the `-C`, never the guard. |
227
+ | **`codex`** | `codex exec [-C <dir>] "<msg>"` · resume: `codex exec resume <session-id> "<msg>"` | **A headless `codex exec` peer is READ-ONLY. It cannot write to any lane see below.** Never dispatch it from your own lane. | Its managed identity is fixed at session creation and `-C` does **not** change it. Dispatch from your lane and every write is refused with `CODEX MANAGED LANE: App Local must use an owned managed Codex lane`permanently, for that session's whole life. |
228
+
229
+ > **`-C` does not establish lane identity — verified 2026-08-14, and an earlier
230
+ > version of this table said the opposite.** Managed identity is an 8-field record
231
+ > (`lane, role, repoIdentity, ownerPid, ownerStartFingerprint, sessionId,
232
+ > leaseEpoch, ownerToken`) built by `buildStartupIdentity()` in
233
+ > [`pool/codex-topology.mjs`](file:///C:/Dev/lifeai-env/pool/codex-topology.mjs)
234
+ > and minted **only by the interactive launcher**, which also claims the lease.
235
+ > `codex exec` has no lane-claim path, so it cannot produce that record — which
236
+ > means **a headless Codex peer cannot write in any lane, including its own**.
237
+ >
238
+ > Two consequences: (1) `resume` replays the session's *recorded* identity, so a
239
+ > session created in the wrong cwd is poisoned for life and `-C` will not repair
240
+ > it — start a new session instead; (2) treat a `codex exec` peer as a
241
+ > conversational participant only. Writing work belongs to a launcher-started
242
+ > Codex session, `rdc:build`, or an isolated-worktree agent.
243
+ >
244
+ > Beware the error text: `App Local denied: <lane> has a foreign live lease` also
245
+ > fires when there is **no lease at all** (`ownerMatchesLease` returns false for a
246
+ > null lease), so it will send you hunting a conflicting owner that does not exist.
247
+
248
+ file:///C:/Dev/lifeai-env/pool/codex-topology.mjs
114
249
  | **`local-llm`** | local endpoint per `.claude/context/clauth.md`; credential via `curl -s http://127.0.0.1:52437/v/<service>` | none (no repo attachment) | Small context windows: send the contract and the open points, never the whole document. Link paths instead of pasting files. |
115
250
  | **`claude-agent`** | `Agent` tool, or `claude -p --bare` / `claude --bg` | **`isolation: "worktree"` as an actual tool parameter** if it will commit — a prose claim of isolation is inert | Parallel agents on a shared checkout race on `git stash` and `.git/index`. See `.claude/rules/subagent-credentials.md`. |
116
251
  | **`claude-ai`** | chitchat MCP (`chitchat_send` / `chitchat_poll` / `chitchat_reply`) + SSE | session-scoped | Messages evaporate when the session stops — export durable decisions to TinTin. |
@@ -122,31 +257,28 @@ behind a `timeout` guess. A truncated call looks like a failure and is not one.
122
257
 
123
258
  ## Step 2 — Compose the response contract (mandatory)
124
259
 
125
- Every dispatch in `negotiate` or `delegate` mode carries an explicit answer
126
- format. The contract is not politeness — it is what makes the reply *checkable*.
260
+ Every dispatch carries an explicit answer format. The contract is not politeness —
261
+ it is what makes the reply *checkable*.
262
+
263
+ **Every field returns information. No field asks the peer what it changed** — if a
264
+ contract invites `CHANGED: <file paths>`, it has invited the peer to mutate the
265
+ repo mid-conversation, which is the v0.27.0 defect this version removes.
127
266
 
128
- **Negotiate contract — one block per open point:**
267
+ **The contract — one block per open point:**
129
268
 
130
269
  ```
131
270
  POINT <n>: AGREE | AGREE-WITH-AMENDMENT | DISAGREE
132
- EDIT: <the exact section and change you will make, or NONE>
271
+ EDIT: <the exact section and change that SHOULD be made, or NONE — describe it, do not make it>
133
272
  REASON: <one sentence — only if AMENDMENT or DISAGREE>
134
273
  ```
135
274
 
136
- Plus one closing block, always:
137
-
138
- ```
139
- OWNER: <who writes the change — exactly one agent>
140
- BLOCKED: <what you cannot do from where you are, or NONE>
141
- ```
142
-
143
- **Delegate contract:**
275
+ **When the point is a factual question rather than a proposal**, the peer answers
276
+ with findings — still text, still no repo mutation:
144
277
 
145
278
  ```
146
- STATUS: DONE | PARTIAL | BLOCKED
147
- CHANGED: <file paths, or NONE>
279
+ FINDING <n>: <the answer, one sentence>
148
280
  EVIDENCE: <command run + literal result — exit code, row count, probe status>
149
- BLOCKED: <what stopped you, or NONE>
281
+ CONFIDENCE: VERIFIED | INFERRED | UNKNOWN
150
282
  ```
151
283
 
152
284
  Rules that make the contract hold:
@@ -161,7 +293,7 @@ Rules that make the contract hold:
161
293
 
162
294
  ---
163
295
 
164
- ## Step 3 — Converge (negotiate mode)
296
+ ## Step 3 — Converge
165
297
 
166
298
  ```
167
299
  open_points = [all points]
@@ -189,18 +321,20 @@ negotiation becomes a loop that never terminates.
189
321
 
190
322
  ---
191
323
 
192
- ## Step 4 — Single-writer rule
324
+ ## Step 4 — Single-writer rule (for the OUTCOME, not the conversation)
193
325
 
194
- Before round 1, name **one** agent as the writer of the document or code under
195
- discussion, and say so in the dispatch.
326
+ Nobody writes during a collab. The single-writer rule governs **who lands the
327
+ settled Decision afterward** — name that agent before round 1 and say so in the
328
+ dispatch.
196
329
 
197
330
  > Two active writers on one surface is forbidden — the same rule the fleet plans
198
331
  > state as *"never run two active writers for one effect."*
199
332
 
200
333
  If the named writer turns out to be **structurally blocked** (wrong lane, no
201
334
  credentials, read-only mount), ownership transfers to the other agent *for that
202
- artifact only*, and the transfer is recorded in the change itself with
203
- attribution. A blocked writer does not mean the agreed work is abandoned.
335
+ artifact only*, recorded in the change itself with attribution. A blocked writer
336
+ never means the agreed work is abandoned the reasoning already exists in the
337
+ reply, which is exactly why the reply, not a file, is the deliverable.
204
338
 
205
339
  ---
206
340
 
@@ -283,6 +417,8 @@ and avoids acting on a misread premise (lesson
283
417
  | Wrapping dispatch in a `timeout` guess | A still-running call reads as a failure |
284
418
  | Escalating a transcript | The human has to find the question themselves |
285
419
  | Two agents editing one document | Lost work, no error |
420
+ | Writing to the repo during a collab | Your answer may be guard-blocked and stranded; the reply is always deliverable, a write may not be |
421
+ | Using collab to hand off WORK | Wrong skill. Create a work item and use rdc:build or an isolated-worktree agent |
286
422
 
287
423
  ---
288
424