Write down how to test CLI delegation against real opencode children

7ecef50c2678 · Devin AI · · parent 3f782af78d43

Write down how to test CLI delegation against real opencode children

The delegation path only proves itself against a real child harness, and the
setup that makes that reproducible — a private opencode config, a PTY wide
enough to show the fleet, process-tree checks after a stop — is not obvious
from the tests.

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

Not deployed through the forge lane

No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.

Changed files

  • added .agents/skills/testing-cli-delegation/SKILL.md

Diff

1 file changed, +109 -0

.agents/skills/testing-cli-delegation/SKILL.md added +109

@@ -0,0 +1,109 @@

1
---
2
name: testing-cli-delegation
3
description: Run and verify the OpenAgents CLI coder TUI and its `/delegate` child-agent fleet end to end on a Linux box, including a recordable GUI terminal, a child harness with provider credentials, and the process checks that catch orphaned children.
4
---
5
6
# Testing the coder TUI and delegation fleet
7
8
## Build and entry point
9
10
```bash
11
source ~/.nvm/nvm.sh && nvm use 24
12
cd ~/repos/openagents/packages/openagents-cli && npx tsc -p tsconfig.build.json
13
export OA=~/repos/openagents/packages/openagents-cli/dist/main.js   # entry is dist/main.js
14
```
15
16
Always rebuild before testing: `dist/` is committed-independent and can lag `src/`.
17
18
## Child harness (delegation) setup
19
20
Delegation is off unless a child model is named, so a session started without
21
`--child-model` (or `OPENAGENTS_DELEGATE_MODEL`) answers `/delegate` with
22
"This session cannot delegate."
23
24
```bash
25
npm install --global opencode-ai      # provides the `opencode` harness on PATH
26
# Provider credential lives in a private harness config, never in the repo:
27
#   ~/.oa-delegate/opencode.json  (chmod 600) -> passed via --child-config
28
```
29
30
Never print, copy, or screenshot that config. Pass it per invocation:
31
32
```bash
33
COMMON="--child-model vertex-express/gemini-3.7-flash \
34
        --child-config $HOME/.oa-delegate/opencode.json --child-approve"
35
node $OA delegate "create a file x.txt containing kiwi then say done" \
36
  --agents 3 --concurrency 2 $COMMON      # headless; exit 1 if any child failed
37
node $OA coder --offline $COMMON          # interactive TUI; --offline uses a stand-in chat model
38
```
39
40
`--child-approve` is required for any child that must write files or run commands.
41
42
## Recordable GUI terminal
43
44
The TUI must be driven in a real PTY. A GUI terminal makes the recording useful:
45
46
```bash
47
pkill konsole; DISPLAY=:0 setsid konsole --hide-menubar --hide-tabbar \
48
  -p "Font=Monospace,18" -e /bin/bash &
49
DISPLAY=:0 wmctrl -a Konsole; DISPLAY=:0 wmctrl -r :ACTIVE: -b add,maximized_vert,maximized_horz
50
```
51
52
Konsole's `ctrl+shift+plus` font shortcut does not work under xdotool typing — set the
53
font with `-p "Font=Monospace,18"` at launch instead. Resize the terminal grid without
54
touching the window with an escape sequence, which is how you exercise a small terminal:
55
56
```bash
57
printf '\033[8;24;80t'    # 80x24
58
printf '\033[8;37;112t'   # back to a large grid
59
```
60
61
## Designing prompts that make the fleet observable
62
63
Children on a fast model finish in ~5 s and their rows are pruned once their finish
64
notice is read, so a naive prompt gives you nothing to look at:
65
66
- To watch tool/token counters advance: ask for several tool calls, e.g.
67
  `/delegate 2x create five files n1.txt..n5.txt each containing kiwi, one write call per file, then say done`.
68
- To hold rows on screen long enough for `ctrl+x`, resizes, or queue behaviour:
69
  `/delegate 2x run the shell command \`sleep 120\` then say done`.
70
- To exercise the row cap and the "+N more" line: 12 children with the default
71
  `--concurrency 4` shows 4 running + 4 queued rows and `+4 more` (cap is 8 rows).
72
73
## Verification checks that catch real bugs
74
75
- `pgrep -af opencode` after `ctrl+x` and after `ctrl+d`.
76
- Also check **grandchildren**: `pgrep -af "sleep 120"` and `ps -o pid,ppid …`. `opencode`
77
  puts its own tool processes in groups of their own, so a stop that signals only the
78
  agent leaves shell commands it spawned reparented to PID 1. Any orphan is a defect, not
79
  a flake. Match on `pgrep -af "^sleep 120"` and note the pids before the stop: a bare
80
  `pgrep -af "sleep 120"` also matches the shell running your own test command, which
81
  reads as a false orphan.
82
- Also stop the parent rather than the child: `kill -INT` the `delegate` process and
83
  re-check. A handler that only runs after the runtime tears the process down never
84
  reaches the children.
85
- Zoom on the bottom four rows: the key-hint row and the composer row are both
86
  width-truncated, so verify `ctrl+x to stop agents` survives while children run and that
87
  a composer line longer than the terminal leaves no stale text on the rule above the
88
  hints. Screenshot the region rather than trusting the transcript.
89
- The hint row and the right-hand counter compete for the same row, so test the hint
90
  **twice**: once on a fresh transcript and once after it scrolls (send a chat prompt so
91
  `↑N above` appears). At 80 columns the unscrolled case can pass while the scrolled case
92
  drops the hint. `hints()` in `coder-ui.ts` now takes hint objects with a pinned flag:
93
  `ctrl+x to stop agents` is pinned while any child runs, and the row drops the
94
  conveniences first (expect `ctrl+d to quit` / `pgup/pgdn to scroll` to vanish at 80
95
  columns, which is intended), then the counter, and clips only as a last resort. When
96
  verifying a similar row, assert the pinned hint's presence rather than the full hint
97
  list, and record the exact left/right row text in the report.
98
- Composer clipping: type a line longer than the terminal width. Expect one row with a
99
  leading `…` showing the *tail* of what was typed, and confirm the full text was still
100
  sent by reading the echoed reply. A wrapped line is a defect.
101
- A running row that has no usage yet should read `Initializing…` with no trailing `· 0`.
102
- `Stopped N children.` counts only running children; queued ones still each get a
103
  `stopped.` notice, so N is smaller than the number of rows. That is expected.
104
105
## Devin Secrets Needed
106
107
None for delegation itself — the provider credential is a local file at
108
`~/.oa-delegate/opencode.json`. Real (non-`--offline`) chat replies would need an
109
account token via `openagents auth login --scope chat:account`.

This page updates live while a promote is in flight · changelog