@irythill/orq 0.4.0 → 0.6.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.
- package/README.md +62 -37
- package/README.pt-BR.md +59 -33
- package/dist/agents.js +59 -5
- package/dist/ci.js +4 -2
- package/dist/cli.js +5 -1
- package/dist/commands/agent.js +145 -31
- package/dist/commands/block.js +26 -3
- package/dist/commands/board.js +113 -31
- package/dist/commands/claim.js +2 -0
- package/dist/commands/completion.js +3 -3
- package/dist/commands/conductor.js +104 -0
- package/dist/commands/gc.js +48 -10
- package/dist/commands/handoff.js +1 -0
- package/dist/commands/pick.js +1 -1
- package/dist/commands/rounds.js +77 -3
- package/dist/commands/stats.js +1 -1
- package/dist/commands/verify.js +2 -0
- package/dist/commands/wait.js +7 -1
- package/dist/config.js +2 -1
- package/dist/diagnose.js +105 -0
- package/dist/notice.js +310 -0
- package/dist/pick.js +33 -4
- package/dist/process.js +7 -0
- package/dist/roles.js +11 -2
- package/dist/rounds.js +14 -5
- package/dist/stats.js +6 -4
- package/dist/testrun.js +4 -27
- package/package.json +1 -1
- package/skills/issue/SKILL.md +50 -45
- package/templates/workspace.CLAUDE.md +8 -6
package/README.md
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
<p align="center"><img src="docs/img/orq-logo.svg" alt="orq — an orc in a tailcoat raising a conductor's baton" width="304"></p>
|
|
4
4
|
|
|
5
|
-
# orq — orchestrating coding agents
|
|
5
|
+
# orq — orchestrating coding agents
|
|
6
6
|
|
|
7
7
|
You describe the work in a Plane issue. A **conductor** (Claude, ideally Opus) reads it, picks the right agent for
|
|
8
|
-
each step, dispatches the **implementer**, the **tests** and a **cross-vendor review** in
|
|
9
|
-
|
|
8
|
+
each step, dispatches the **implementer**, the **tests** and a **cross-vendor review** (each in its own tab or window
|
|
9
|
+
in [herdr](https://herdr.dev) or tmux, or in the background), and hands the issue back *In Review* with a summary in
|
|
10
|
+
Plane. Merge, PR and deploy stay with you.
|
|
10
11
|
|
|
11
12
|
What orq does **not** decide for you: which agents you have, how much each may spend and how you like to work. All of
|
|
12
13
|
that lives in your config.
|
|
@@ -19,17 +20,18 @@ that lives in your config.
|
|
|
19
20
|
## How it works
|
|
20
21
|
|
|
21
22
|
```
|
|
22
|
-
You ── "/issue DEMO-123" ──► conductor (Claude in
|
|
23
|
-
│ orq
|
|
24
|
-
├─► implementer
|
|
25
|
-
├─► tests
|
|
26
|
-
│ orq
|
|
27
|
-
├─► reviewer
|
|
23
|
+
You ── "/issue DEMO-123" ──► conductor (Claude, in any terminal)
|
|
24
|
+
│ orq pick impl ──► which agent/model implements (config + history + quota)
|
|
25
|
+
├─► implementer orq agent own tab/window or background · worktree from origin/<base> · memory cap
|
|
26
|
+
├─► tests orq verify only the diff's tests · queue of one suite at a time
|
|
27
|
+
│ orq pick review ─► a reviewer from ANOTHER vendor
|
|
28
|
+
├─► reviewer orq agent -r read only · diff + criteria + test results attached
|
|
28
29
|
└─► Plane comment, state, labels
|
|
29
|
-
◄── "[HERDR-AGENT DONE] ..."
|
|
30
|
+
◄── "[HERDR-AGENT DONE] ..." typed into the conductor's herdr pane, or `orq wait` printing "[ORQ AGENT DONE] ..."
|
|
30
31
|
```
|
|
31
32
|
|
|
32
|
-
- **Every step in
|
|
33
|
+
- **Every step in its own tab or window.** In herdr or tmux you watch it live and the tab closes when it's done;
|
|
34
|
+
without them the step runs in the background (`orq board` shows it). Results stay in
|
|
33
35
|
`.orquestra/<ID>/` (`.out.md`, `.log`, `.done`).
|
|
34
36
|
- **Fixed order every round:** implementer ok → tests with no new failure → review. Only a `[blocker]` with
|
|
35
37
|
`file:line` and a concrete failure becomes a fix round; the rest goes into the Plane comment (configurable maximum).
|
|
@@ -37,7 +39,7 @@ You ── "/issue DEMO-123" ──► conductor (Claude in herdr)
|
|
|
37
39
|
one level up), fixes only the listed blockers with a test each, and the next review, by the same reviewer, checks
|
|
38
40
|
those blockers and the fix's own diff instead of starting over. The implementer ends with a `## Decisions` section, so
|
|
39
41
|
a deliberate choice doesn't come back as a blocker.
|
|
40
|
-
- **Nobody picks an agent by gut feeling.** `orq
|
|
42
|
+
- **Nobody picks an agent by gut feeling.** `orq pick` decides from data: what each agent delivered in the history,
|
|
41
43
|
how many tokens it spent, how long it took, the current quota, and a rotation so no agent gets all the work.
|
|
42
44
|
- **The machine stays up.** Each agent runs under its own memory cap; tests wait in a queue.
|
|
43
45
|
|
|
@@ -146,13 +148,13 @@ roles = ["review"] # here it only reviews; for someone els
|
|
|
146
148
|
[agents.opencode.models.review]
|
|
147
149
|
default = "minimax/MiniMax-M3"
|
|
148
150
|
|
|
149
|
-
[agents.
|
|
151
|
+
[agents.revtool] # a review tool, not a chat: no prompt, no session
|
|
150
152
|
vendor = "minimax" # the vendor of the model it runs, for the cross-vendor rule
|
|
151
153
|
roles = ["review"]
|
|
152
|
-
run = "
|
|
154
|
+
run = "revtool --markdown -b {base}" # {base} = orq agent -b; it reads the diff itself
|
|
153
155
|
write = false
|
|
154
156
|
ok_exit = [0, 1] # exit 1 = findings, still a verdict
|
|
155
|
-
no_review = "
|
|
157
|
+
no_review = "Nothing to review" # matched on the answer's first line (or a short answer): not a verdict, status=fail
|
|
156
158
|
# filter = "jq -r '...'" # optional: its output → [blocker]/[suggestion] lines
|
|
157
159
|
|
|
158
160
|
[conductor]
|
|
@@ -188,13 +190,12 @@ orq pick fix --same .orquestra/<ID>/impl-<repo>.pick # a fix round: the implem
|
|
|
188
190
|
```
|
|
189
191
|
|
|
190
192
|
### Language and theme
|
|
191
|
-
orq speaks English and Portuguese: CLI messages, `
|
|
193
|
+
orq speaks English and Portuguese: CLI messages, `orq board`, notices and `install.sh`. It follows
|
|
192
194
|
`[ui] lang` in your config (`"auto"` = system locale, `"en"`, `"pt"`), or the `ORQ_LANG` environment variable.
|
|
193
195
|
Switch it any time:
|
|
194
196
|
- `orq-lang pt` / `orq-lang en` / `orq-lang toggle` (`orq-lang` alone shows the current one);
|
|
195
197
|
- `l` inside `orq board`;
|
|
196
|
-
-
|
|
197
|
-
`herdr-plugin/herdr-plugin.toml`) — e.g. `prefix+shift+l` — and `orq.board` to open the board as an overlay.
|
|
198
|
+
- in herdr, a key for it: see [With herdr](#with-herdr).
|
|
198
199
|
|
|
199
200
|
`orq board` has its own look, from the [SYNTH.DECK](https://github.com/irythill/synth-deck-portfolio)
|
|
200
201
|
portfolio: `[ui] theme = "gunmetal"` (default, dark graphite), `"chrome"` (light silver), `"lcd"` (phosphor green) or
|
|
@@ -205,26 +206,49 @@ Whatever is already running keeps its language. Conductors always talk to you in
|
|
|
205
206
|
|
|
206
207
|
## Daily use
|
|
207
208
|
|
|
209
|
+
Open the conductor in any terminal, in your workspace folder (the one `orq setup` prepared):
|
|
208
210
|
```bash
|
|
209
|
-
|
|
210
|
-
cd ~/Code/<workspace> && herdr-conductor # inside a herdr pane: opens the conductor (account and model optional)
|
|
211
|
+
cd ~/Code/<workspace> && orq conductor [account] [model] # any terminal: loads the conductor instructions, the workspace CLAUDE.md and the /issue skill
|
|
211
212
|
```
|
|
212
|
-
|
|
213
|
+
With several conductors, give each a fixed name (`export ORQ_CONDUCTOR_ID=<name>`) so `orq claim` can tell them apart.
|
|
214
|
+
Variants:
|
|
215
|
+
- **herdr:** run `herdr` (the server runs as a service), then the same `orq conductor` in a pane (`herdr-conductor` still works).
|
|
216
|
+
- **tmux:** run `orq conductor` in a pane; children open as tmux windows.
|
|
217
|
+
- **Neither:** children run in the background and the conductor waits with `orq wait`.
|
|
218
|
+
|
|
219
|
+
In the conductor: **`/issue DEMO-123`**. It answers in one line and moves on by itself at every completion signal
|
|
220
|
+
(`[HERDR-AGENT DONE]` in a herdr pane, otherwise the `[ORQ AGENT DONE]` line printed by `orq wait`).
|
|
213
221
|
You only come back when it asks for a decision or says it's done.
|
|
214
222
|
|
|
215
223
|
To see everything at once, keep **`orq board`** open in a tab or window (any terminal, any OS; `herdr-board` calls it):
|
|
216
224
|
test queue, running agents (model, memory against the cap, last action), conductors and their issues, memory, quota,
|
|
217
|
-
CI/CD per claimed issue, blocks and the 7-day scoreboard. `--once` prints it once, `--json` for scripts.
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
[
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
CI/CD per claimed issue, blocks and the 7-day scoreboard. `--once` prints it once, `--json` for scripts.
|
|
226
|
+
A failure (tests red, agent `status=fail`, CI red) is also **loud**: besides the line typed into the conductor's pane
|
|
227
|
+
(delivered by orq with retries and a log, `orq notice`), you get a `✗` title on the conductor's pane (herdr) and, on
|
|
228
|
+
Linux, a desktop notification (`[ui] desktop_notify = false` turns that one off; needs `notify-send`). Successes are
|
|
229
|
+
quiet. The board's red top line lists failures from the last hour whose notice was not delivered or that the conductor
|
|
230
|
+
has not yet acted on (it clears when the conductor runs `orq wait`, `orq verify` or `orq agent` for the issue).
|
|
231
|
+
`orq quota --line` prints quota in one line for any status bar. `orq ci` shows each claimed issue's PR checks (queued,
|
|
232
|
+
running, passed, failed or none, read from `gh` right then — it is a status check the user asked for, so unlike the
|
|
233
|
+
board's CI column it does not just read the cache); a failure pings the owning conductor once per commit. After
|
|
234
|
+
merges, `orq gc` lists and removes the issue worktrees left behind.
|
|
235
|
+
|
|
236
|
+
Several issues at once: one conductor per issue (ideally on different accounts). `orq claim` (`herdr-claim`) keeps two
|
|
237
|
+
conductors off the same issue.
|
|
238
|
+
|
|
239
|
+
## With herdr
|
|
240
|
+
|
|
241
|
+
herdr is optional, but it gives orq the most polish: children in their own tabs, notices typed into the conductor's
|
|
242
|
+
pane, and a few extras:
|
|
243
|
+
- `orq conductor` (or `herdr-conductor`) in a herdr pane also names the pane "conductor".
|
|
244
|
+
- `ui.toast.delivery = "system"` in herdr's config makes each finished step pop up a native OS notification; failures
|
|
245
|
+
also get a herdr notification with sound, and a CI run turning red or green pops one too.
|
|
246
|
+
- `orq quota --line` fits herdr's tab bar (a `tab_bar_right` command entry,
|
|
247
|
+
[docs/herdr.md](docs/herdr.md#quota-in-the-tab-bar)).
|
|
248
|
+
- A key for the language: `install.sh` links the `orq` herdr plugin; bind its `orq.lang-toggle` action (snippet in
|
|
249
|
+
`herdr-plugin/herdr-plugin.toml`) — e.g. `prefix+shift+l` — and `orq.board` to open the board as an overlay.
|
|
250
|
+
|
|
251
|
+
Day to day, shortcuts and several issues at once: [docs/herdr.md](docs/herdr.md).
|
|
228
252
|
|
|
229
253
|
## Skills
|
|
230
254
|
|
|
@@ -240,18 +264,19 @@ off the same issue. Details, shortcuts and scenarios: [docs/herdr.md](docs/herdr
|
|
|
240
264
|
|
|
241
265
|
| Command | What it does |
|
|
242
266
|
|---|---|
|
|
243
|
-
| `orq agent -a <agent> ...` (`herdr-agent`) | Runs an agent with a memory cap in a herdr tab, a tmux window or the background; `-r` read only, `-R <id>` continue the session, `-i` attach a file, `-b <base>` attach the diff, `-T` the agent's own screen (herdr or tmux; `-R` with it open types the follow-up into it) |
|
|
267
|
+
| `orq agent -a <agent> ...` (`herdr-agent`) | Runs an agent with a memory cap in a herdr tab, a tmux window or the background; `-r` read only, `-R <id>` continue the session, `-i` attach a file, `-b <base>` attach the diff, `-T` the agent's own screen (herdr or tmux; `-R` with it open types the follow-up into it; a finished screen closes after `[machine] tui_idle_close_min` minutes without a follow-up, default 30, `0` = never) |
|
|
244
268
|
| `orq instructions claude\|agents` | Writes the `/issue` playbook as `SKILL.md` (Claude Code) or into `AGENTS.md` (Codex, OpenCode…) |
|
|
269
|
+
| `orq notice [--list] [-n N]` | The delivery log of notices to conductors: each attempt, retry and failure (`<state>/notices.jsonl`) |
|
|
245
270
|
| `orq wait <prefix>...` | Blocks until those agents finish; prints `status=` and the answer file (any conductor, any terminal) |
|
|
246
271
|
| `orq verify ...` (`herdr-verify`) | Tests related to the diff, queued and memory-capped; failures that also fail on the base count as pre-existing |
|
|
247
272
|
| `orq board` (`herdr-board`) | Live board: queue, agents, conductors, quota, blocks, scoreboard |
|
|
248
|
-
| `herdr-conductor` | Opens the conductor in the current
|
|
249
|
-
| `herdr-claim` | Owner of each issue among conductors |
|
|
250
|
-
| `herdr-deps` | Links the worktree's dependencies to the main repo's (no reinstall) |
|
|
273
|
+
| `orq conductor [account] [model] [-r <id>]` (`herdr-conductor`) | Opens the conductor (Claude) in the current terminal with its instructions, account and model; `-r` resumes a session |
|
|
274
|
+
| `orq claim` (`herdr-claim`) | Owner of each issue among conductors |
|
|
275
|
+
| `orq deps` (`herdr-deps`) | Links the worktree's dependencies to the main repo's (no reinstall) |
|
|
251
276
|
| `orq baseline ...` (`herdr-baseline`) | Manual snapshot of the tests failing on the base (outside the flow) |
|
|
252
277
|
| `orq gc [-w <workspace>] [--yes] [--days N] [--json]` | Lists issue worktrees that are safe to remove (PR merged, or content already in the base, squash merges included); `--yes` removes them. Never touches uncommitted work, unpushed commits, a live claim or a running agent. Optional daily `orq-gc.timer` |
|
|
253
278
|
| `orq ci [-w <workspace>] [--json]` | CI/CD status per claimed issue with a PR: queued, running, passed, failed or none, collected live via `gh` right then (the cache it fills is what `orq board`'s CI column reads, never blocking on the network). A run turning red or green pops a herdr notification, and a failure also pings the owning conductor |
|
|
254
|
-
| `orq rounds <ID> [-w <workspace>] [--json]` | Watchdog
|
|
279
|
+
| `orq rounds <ID> [-w <workspace>] [--json] [--diagnose]` | Watchdog: `--diagnose` (warn/stop only) has a cheap read only agent of another vendor (pick role `watchdog`, falls back to `opinion`, then `review`) diagnose why rounds don't converge → `.orquestra/<ID>/diagnosis-<n>.md`, advisory; `orq agent -R -F` past `max_rounds` needs it (`-F -F` bypasses). Without it, no LLM: fix rounds vs `policy.max_rounds`, time per round, reviewer findings repeated across rounds, alert ok / warn / stop. The board marks each issue (`r2/2 ⚠`) |
|
|
255
280
|
| `orq quota --line` | One line of quota for a status bar (`work 64 · home 94! · codex 81`), from the board's cache, never the network |
|
|
256
281
|
| `orq setup` | First configuration and install: environment, skills for Claude, config, conductor workspace |
|
|
257
282
|
| `orq completion bash\|zsh\|fish\|powershell` | Prints the shell completion script (see Install) |
|
package/README.pt-BR.md
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
<p align="center"><img src="docs/img/orq-logo.svg" alt="orq — um orc de fraque erguendo a batuta de maestro" width="304"></p>
|
|
4
4
|
|
|
5
|
-
# orq — orquestrando agentes de código
|
|
5
|
+
# orq — orquestrando agentes de código
|
|
6
6
|
|
|
7
7
|
Você descreve o trabalho numa issue do Plane. Um **conductor** (Claude, de preferência Opus) lê a issue, escolhe o
|
|
8
|
-
agente certo para cada etapa, despacha o **implementador**, os **testes** e uma **review cross-vendor**
|
|
9
|
-
[herdr](https://herdr.dev)
|
|
8
|
+
agente certo para cada etapa, despacha o **implementador**, os **testes** e uma **review cross-vendor** (cada um
|
|
9
|
+
em sua própria aba ou janela no [herdr](https://herdr.dev) ou no tmux, ou em segundo plano), e devolve a issue
|
|
10
|
+
*In Review* com um resumo no Plane. Merge, PR e deploy continuam com você.
|
|
10
11
|
|
|
11
12
|
O que o orq **não** decide por você: quais agentes você tem, quanto cada um pode gastar e como você gosta de
|
|
12
13
|
trabalhar. Tudo isso fica na sua config.
|
|
@@ -19,17 +20,18 @@ trabalhar. Tudo isso fica na sua config.
|
|
|
19
20
|
## Como funciona
|
|
20
21
|
|
|
21
22
|
```
|
|
22
|
-
You ── "/issue DEMO-123" ──► conductor (Claude in
|
|
23
|
-
│ orq
|
|
24
|
-
├─► implementer
|
|
25
|
-
├─► tests
|
|
26
|
-
│ orq
|
|
27
|
-
├─► reviewer
|
|
23
|
+
You ── "/issue DEMO-123" ──► conductor (Claude, in any terminal)
|
|
24
|
+
│ orq pick impl ──► which agent/model implements (config + history + quota)
|
|
25
|
+
├─► implementer orq agent own tab/window or background · worktree from origin/<base> · memory cap
|
|
26
|
+
├─► tests orq verify only the diff's tests · queue of one suite at a time
|
|
27
|
+
│ orq pick review ─► a reviewer from ANOTHER vendor
|
|
28
|
+
├─► reviewer orq agent -r read only · diff + criteria + test results attached
|
|
28
29
|
└─► Plane comment, state, labels
|
|
29
|
-
◄── "[HERDR-AGENT DONE] ..."
|
|
30
|
+
◄── "[HERDR-AGENT DONE] ..." typed into the conductor's herdr pane, or `orq wait` printing "[ORQ AGENT DONE] ..."
|
|
30
31
|
```
|
|
31
32
|
|
|
32
|
-
- **Cada etapa
|
|
33
|
+
- **Cada etapa na sua própria aba ou janela.** No herdr ou no tmux você acompanha ao vivo e a aba fecha quando
|
|
34
|
+
termina; sem eles a etapa roda em segundo plano (o `orq board` mostra). Os resultados ficam em
|
|
33
35
|
`.orquestra/<ID>/` (`.out.md`, `.log`, `.done`).
|
|
34
36
|
- **Ordem fixa em toda rodada:** implementador ok → testes sem falha nova → review. Só um `[blocker]` com
|
|
35
37
|
`arquivo:linha` e uma falha concreta vira rodada de correção; o resto vai para o comentário no Plane (com máximo
|
|
@@ -181,13 +183,12 @@ orq pick fix --same .orquestra/<ID>/impl-<repo>.pick # a fix round: the implem
|
|
|
181
183
|
```
|
|
182
184
|
|
|
183
185
|
### Idioma e tema
|
|
184
|
-
O orq fala inglês e português: mensagens da CLI, `
|
|
186
|
+
O orq fala inglês e português: mensagens da CLI, `orq board`, avisos e `install.sh`. Ele segue `[ui] lang` na sua
|
|
185
187
|
config (`"auto"` = idioma do sistema, `"en"`, `"pt"`) ou a variável de ambiente `ORQ_LANG`. Para trocar a qualquer
|
|
186
188
|
momento:
|
|
187
189
|
- `orq-lang pt` / `orq-lang en` / `orq-lang toggle` (`orq-lang` sozinho mostra o atual);
|
|
188
190
|
- a tecla `l` dentro do `orq board`;
|
|
189
|
-
- uma tecla
|
|
190
|
-
`herdr-plugin/herdr-plugin.toml`) — por exemplo, `prefix+shift+l` — e a `orq.board` para abrir o painel por cima.
|
|
191
|
+
- no herdr, uma tecla para isso: veja [Com o herdr](#com-o-herdr).
|
|
191
192
|
|
|
192
193
|
O `orq board` tem visual próprio, inspirado no portfólio [SYNTH.DECK](https://github.com/irythill/synth-deck-portfolio):
|
|
193
194
|
`[ui] theme = "gunmetal"` (padrão, grafite escuro), `"chrome"` (prata claro), `"lcd"` (verde fósforo) ou `"terminal"`
|
|
@@ -197,27 +198,51 @@ O que já está rodando continua no idioma em que começou. Os conductors sempre
|
|
|
197
198
|
|
|
198
199
|
## Uso diário
|
|
199
200
|
|
|
201
|
+
Abra o conductor em qualquer terminal, na pasta do seu workspace (a que o `orq setup` preparou):
|
|
200
202
|
```bash
|
|
201
|
-
|
|
202
|
-
cd ~/Code/<workspace> && herdr-conductor # dentro de um pane do herdr: abre o conductor (conta e modelo opcionais)
|
|
203
|
+
cd ~/Code/<workspace> && orq conductor [conta] [modelo] # qualquer terminal: carrega as instruções do conductor, o CLAUDE.md do workspace e a skill /issue
|
|
203
204
|
```
|
|
204
|
-
|
|
205
|
+
Com vários conductors, dê a cada um um nome fixo (`export ORQ_CONDUCTOR_ID=<nome>`) para o `orq claim` distingui-los.
|
|
206
|
+
Variantes:
|
|
207
|
+
- **herdr:** rode `herdr` (o servidor roda como serviço) e, num pane, o mesmo `orq conductor` (o `herdr-conductor` continua funcionando).
|
|
208
|
+
- **tmux:** rode `orq conductor` num pane; os filhos abrem como janelas do tmux.
|
|
209
|
+
- **Nenhum dos dois:** os filhos rodam em segundo plano e o conductor espera com `orq wait`.
|
|
210
|
+
|
|
211
|
+
No conductor: **`/issue DEMO-123`**. Ele responde numa linha e segue sozinho a cada sinal de conclusão
|
|
212
|
+
(`[HERDR-AGENT DONE]` num pane do herdr; fora dele, a linha `[ORQ AGENT DONE]` impressa pelo `orq wait`). Você só volta
|
|
205
213
|
quando ele pede uma decisão ou avisa que terminou.
|
|
206
214
|
|
|
207
215
|
Para ver tudo de uma vez, deixe o **`orq board`** aberto numa aba ou janela (qualquer terminal, qualquer SO; o
|
|
208
216
|
`herdr-board` o chama): fila de testes, agentes rodando (modelo, memória contra o limite, última ação), conductors e
|
|
209
217
|
suas issues, memória, quota, CI/CD de cada issue reivindicada, bloqueios e o placar de 7 dias. `--once` imprime uma
|
|
210
|
-
vez, `--json` para scripts.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
`
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
218
|
+
vez, `--json` para scripts.
|
|
219
|
+
Uma falha (testes vermelhos, agente `status=fail`, CI vermelho) também é **barulhenta**: além da linha digitada no pane
|
|
220
|
+
do conductor (entregue pelo orq com novas tentativas e log, `orq notice`), você recebe um título `✗` no pane do
|
|
221
|
+
conductor (herdr) e, no Linux, uma notificação de desktop (`[ui] desktop_notify = false` desliga essa; precisa do
|
|
222
|
+
`notify-send`). Sucessos ficam quietos. A linha vermelha no topo do board lista as falhas da última hora cujo aviso não
|
|
223
|
+
foi entregue ou que o conductor ainda não tratou (some quando ele roda `orq wait`, `orq verify` ou `orq agent` para a
|
|
224
|
+
issue).
|
|
225
|
+
O `orq quota --line` imprime a cota numa linha para qualquer barra de status. O `orq ci` mostra os checks do PR de cada
|
|
226
|
+
issue reivindicada (na fila, rodando, passou, falhou ou nenhum, lido via `gh` na hora — é uma consulta que o usuário
|
|
227
|
+
pediu agora, então, diferente da coluna de CI do board, não lê só o cache); uma falha também avisa o conductor dono num
|
|
228
|
+
aviso só por commit. Depois dos merges, o `orq gc` lista e remove as worktrees de issues que ficaram para trás.
|
|
229
|
+
|
|
230
|
+
Várias issues ao mesmo tempo: um conductor por issue (de preferência em contas diferentes). O `orq claim`
|
|
231
|
+
(`herdr-claim`) impede que dois conductors peguem a mesma issue.
|
|
232
|
+
|
|
233
|
+
## Com o herdr
|
|
234
|
+
|
|
235
|
+
O herdr é opcional, mas é com ele que o orq fica mais redondo: filhos em abas próprias, avisos digitados no pane do
|
|
236
|
+
conductor e alguns extras:
|
|
237
|
+
- `orq conductor` (ou `herdr-conductor`) num pane do herdr também dá o nome "conductor" ao pane.
|
|
238
|
+
- `ui.toast.delivery = "system"` na config do herdr faz cada etapa concluída gerar uma notificação nativa do sistema;
|
|
239
|
+
falhas também geram uma notificação do herdr com som, e um CI que fica verde ou vermelho também gera uma.
|
|
240
|
+
- O `orq quota --line` cabe na barra de abas do herdr (uma entrada `command` no `tab_bar_right`,
|
|
241
|
+
[docs/pt-BR/herdr.md](docs/pt-BR/herdr.md#cota-na-barra-de-abas)).
|
|
242
|
+
- Uma tecla para o idioma: o `install.sh` liga o plugin `orq` do herdr; associe a ação `orq.lang-toggle` (trecho pronto
|
|
243
|
+
em `herdr-plugin/herdr-plugin.toml`) — por exemplo, `prefix+shift+l` — e a `orq.board` para abrir o painel por cima.
|
|
244
|
+
|
|
245
|
+
Dia a dia, atalhos e várias issues ao mesmo tempo: [docs/pt-BR/herdr.md](docs/pt-BR/herdr.md).
|
|
221
246
|
|
|
222
247
|
## Skills
|
|
223
248
|
|
|
@@ -233,18 +258,19 @@ dois conductors peguem a mesma issue. Detalhes, atalhos e cenários: [docs/pt-BR
|
|
|
233
258
|
|
|
234
259
|
| Comando | O que faz |
|
|
235
260
|
|---|---|
|
|
236
|
-
| `orq agent -a <agent> ...` (`herdr-agent`) | Roda um agente com limite de memória numa aba do herdr, numa janela do tmux ou em segundo plano; `-r` só leitura, `-R <id>` continua a sessão, `-i` anexa um arquivo, `-b <base>` anexa o diff, `-T` a tela do próprio agente (herdr ou tmux; `-R` com ela aberta digita o follow-up nela) |
|
|
261
|
+
| `orq agent -a <agent> ...` (`herdr-agent`) | Roda um agente com limite de memória numa aba do herdr, numa janela do tmux ou em segundo plano; `-r` só leitura, `-R <id>` continua a sessão, `-i` anexa um arquivo, `-b <base>` anexa o diff, `-T` a tela do próprio agente (herdr ou tmux; `-R` com ela aberta digita o follow-up nela; a tela que terminou fecha após `[machine] tui_idle_close_min` minutos sem follow-up, padrão 30, `0` = nunca) |
|
|
237
262
|
| `orq instructions claude\|agents` | Escreve o playbook do `/issue` como `SKILL.md` (Claude Code) ou dentro do `AGENTS.md` (Codex, OpenCode…) |
|
|
263
|
+
| `orq notice [--list] [-n N]` | O log de entrega dos avisos aos conductors: cada tentativa, nova tentativa e falha (`<state>/notices.jsonl`) |
|
|
238
264
|
| `orq wait <prefixo>...` | Bloqueia até esses agentes terminarem; imprime `status=` e o arquivo da resposta (qualquer conductor, qualquer terminal) |
|
|
239
265
|
| `orq verify ...` (`herdr-verify`) | Testes relacionados ao diff, em fila e com limite de memória; falhas que também falham na base contam como pré-existentes |
|
|
240
266
|
| `orq board` (`herdr-board`) | Painel ao vivo: fila, agentes, conductors, cota, bloqueios, placar |
|
|
241
|
-
| `herdr-conductor` | Abre o conductor no
|
|
242
|
-
| `herdr-claim` | Dono de cada issue entre os conductors |
|
|
243
|
-
| `herdr-deps` | Liga as dependências do worktree às do repo principal (sem reinstalar) |
|
|
267
|
+
| `orq conductor [conta] [modelo] [-r <id>]` (`herdr-conductor`) | Abre o conductor (Claude) no terminal atual com as instruções, conta e modelo; `-r` retoma uma sessão |
|
|
268
|
+
| `orq claim` (`herdr-claim`) | Dono de cada issue entre os conductors |
|
|
269
|
+
| `orq deps` (`herdr-deps`) | Liga as dependências do worktree às do repo principal (sem reinstalar) |
|
|
244
270
|
| `orq baseline ...` (`herdr-baseline`) | Snapshot manual dos testes que falham na base (fora do fluxo) |
|
|
245
271
|
| `orq gc [-w <workspace>] [--yes] [--days N] [--json]` | Lista worktrees de issues que podem ser removidas (PR mergeado, ou conteúdo já na base, inclusive squash merge); `--yes` as remove. Nunca mexe em trabalho não commitado, commit fora do remote, claim ativo ou agente rodando. `orq-gc.timer` diário opcional |
|
|
246
272
|
| `orq ci [-w <workspace>] [--json]` | Status de CI/CD de cada issue reivindicada com PR: na fila, rodando, passou, falhou ou nenhum, coletado na hora via `gh` (o cache que ele preenche é o que a coluna de CI do `orq board` lê, sem nunca travar na rede). Quando vira verde ou vermelho sai uma notificação do herdr, e uma falha também avisa o conductor dono |
|
|
247
|
-
| `orq rounds <ID> [-w <workspace>] [--json]` | Watchdog sem LLM: rodadas de fix vs `policy.max_rounds`, tempo por rodada, achados do revisor repetidos entre rodadas, alerta ok / warn / stop. O board marca cada issue (`r2/2 ⚠`) |
|
|
273
|
+
| `orq rounds <ID> [-w <workspace>] [--json] [--diagnose]` | Watchdog: `--diagnose` (só warn/stop) pede a um agente barato, somente leitura e de outro fornecedor (papel de pick `watchdog`, cai para `opinion`, depois `review`) o diagnóstico de por que as rodadas não convergem → `.orquestra/<ID>/diagnosis-<n>.md`, consultivo; `orq agent -R -F` além de `max_rounds` exige (`-F -F` ignora). Sem ele, sem LLM: rodadas de fix vs `policy.max_rounds`, tempo por rodada, achados do revisor repetidos entre rodadas, alerta ok / warn / stop. O board marca cada issue (`r2/2 ⚠`) |
|
|
248
274
|
| `orq quota --line` | Uma linha de cota para barra de status (`work 64 · home 94! · codex 81`), do cache do board, nunca da rede |
|
|
249
275
|
| `orq setup` | Primeira configuração e instalação: ambiente, skills do Claude, config, workspace do conductor |
|
|
250
276
|
| `orq completion bash\|zsh\|fish\|powershell` | Imprime o script de autocompletar do shell (veja Instalação) |
|
package/dist/agents.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { m } from "./i18n.js";
|
|
2
|
+
/** Does the agent's command take the prompt (stdin, a file in its folder or a {prompt*} placeholder)? A review tool like revtool does not. */
|
|
3
|
+
export const usesPrompt = (a) => Boolean(a.stdin || a.prompt_in_dir || /\{prompt(_text|_hint)?\}/.test(a.run ?? ""));
|
|
4
|
+
/** Read only runs of a `throwaway` agent get a worktree copy of HEAD, but only where there is a git repo to copy. */
|
|
5
|
+
export const useThrowaway = (def, ro, resume, inGit) => Boolean(def.throwaway && ro && !resume && inGit);
|
|
2
6
|
const NOMCP_CODEX = "-c mcp_servers.plane.enabled=false -c mcp_servers.shadcn.enabled=false";
|
|
3
7
|
const CLAUDE = "claude -p --strict-mcp-config --output-format stream-json --verbose [--model {model}] --effort {effort:low}";
|
|
4
8
|
const CLAUDE_TUI = "claude --strict-mcp-config [--model {model}] --effort {effort:low}";
|
|
@@ -43,8 +47,8 @@ export const BUILTIN_AGENTS = {
|
|
|
43
47
|
turn_hook: "opencode",
|
|
44
48
|
},
|
|
45
49
|
antigravity: {
|
|
46
|
-
// --sandbox + accept-edits (no skip-permissions); headless denies commands outside agy's allowlist
|
|
47
|
-
//
|
|
50
|
+
// --sandbox + accept-edits (no skip-permissions); headless denies commands outside agy's allowlist (see agy-impl.json);
|
|
51
|
+
// a run that only had commands denied still counts when the worktree changed (see the antigravity format). The prompt goes in a file in its folder (excluded from git) and -p only says "read it".
|
|
48
52
|
run: `${AGY} {mode} -p {prompt_hint}`, resume: `${AGY} --conversation {session} {mode} -p {prompt_hint}`,
|
|
49
53
|
readonly: "--mode plan", write: "--mode accept-edits --add-dir {gitdir}",
|
|
50
54
|
format: "antigravity", throwaway: true, prompt_in_dir: true,
|
|
@@ -202,13 +206,63 @@ export const FORMATS = {
|
|
|
202
206
|
return s.step_type === "tool" && s.state === "DONE" ? "\n· tool\n" : undefined;
|
|
203
207
|
},
|
|
204
208
|
finish(log) {
|
|
205
|
-
const
|
|
209
|
+
const evs = jsonLines(log);
|
|
210
|
+
const res = evs.filter((j) => j.event === "result").map((j) => j.result ?? {});
|
|
206
211
|
let answer = lastOf(res.map((r) => String(r.response ?? ""))) ?? "";
|
|
207
|
-
// An agy error (e.g. a denied command) is a failure, even with an answer.
|
|
208
212
|
const errs = log.split(/\r?\n/).filter((l) => l.startsWith("jetski: "));
|
|
213
|
+
// Denied commands: ERROR steps with the command line, plus denied_actions on the result.
|
|
214
|
+
const denied = [];
|
|
215
|
+
let text = "", textId, lastCmd = "", sawResult = false; // lastCmd: last CommandLine streamed before the result
|
|
216
|
+
const hinted = res.some((r) => Array.isArray(r.denied_actions) && r.denied_actions.length) || errs.some((l) => /permission/.test(l));
|
|
217
|
+
for (const e of evs) {
|
|
218
|
+
if (e.event === "result")
|
|
219
|
+
sawResult = true;
|
|
220
|
+
const s = e.event === "step_update" ? e.step_update : undefined;
|
|
221
|
+
if (!s)
|
|
222
|
+
continue;
|
|
223
|
+
const seen = (s.tool_info ?? e.tool_info)?.parameters?.CommandLine;
|
|
224
|
+
if (!sawResult && typeof seen === "string" && seen.trim())
|
|
225
|
+
lastCmd = seen.trim();
|
|
226
|
+
if (s.step_type === "agent_response") {
|
|
227
|
+
const id = s.step_id ?? s.step_index ?? s.id;
|
|
228
|
+
if (id !== textId) {
|
|
229
|
+
textId = id;
|
|
230
|
+
if (s.text_delta)
|
|
231
|
+
text = "";
|
|
232
|
+
}
|
|
233
|
+
text += String(s.text_delta ?? "");
|
|
234
|
+
}
|
|
235
|
+
if (s.state === "ERROR") {
|
|
236
|
+
const ti = s.tool_info ?? e.tool_info, cmd = ti?.parameters?.CommandLine, msg = String(s.error?.message ?? "");
|
|
237
|
+
if (/permission check failed|not allowed|denied/i.test(msg) || (cmd && !msg && hinted)) {
|
|
238
|
+
const d = `${cmd ? `\`${cmd}\`` : "(command)"}${msg ? ` — ${msg}` : ""}`;
|
|
239
|
+
if (!denied.includes(d))
|
|
240
|
+
denied.push(d);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const acts = res.flatMap((r) => (Array.isArray(r.denied_actions) ? r.denied_actions : []));
|
|
245
|
+
const wasDenied = denied.length > 0 || acts.length > 0 || errs.some((l) => /permission/.test(l));
|
|
246
|
+
// denied_actions only says "RunCommand": the command is the last one the stream showed before the result.
|
|
247
|
+
if (!denied.length && lastCmd && acts.length && acts.every((a) => a.display_name === "RunCommand"))
|
|
248
|
+
denied.push(`denied: ${lastCmd}`);
|
|
249
|
+
if (wasDenied && !answer.trim())
|
|
250
|
+
answer = text.trim();
|
|
251
|
+
if (wasDenied) {
|
|
252
|
+
answer += `${answer ? "\n\n" : ""}## Denied commands\n` +
|
|
253
|
+
"agy denied commands outside its allowlist (headless, nobody to approve). Retry with a different command, or add a glob rule such as command(/usr/bin/*) to agy's allowlist (~/.config/orq/agy-impl.json, see examples/agy-impl.json) -- usually that is the fix.\n" +
|
|
254
|
+
(denied.length ? denied.map((d) => `- ${d}`).join("\n") : acts.map((a) => `- ${a.action ?? "command"} (${a.display_name ?? "?"})`).join("\n")) + "\n";
|
|
255
|
+
}
|
|
209
256
|
if (errs.length)
|
|
210
257
|
answer += (answer ? "\n" : "") + errs.join("\n") + "\n";
|
|
211
|
-
return { session: lastOf(res.map((r) => r.conversation_id).filter(Boolean)), answer, rc: errs.length ? 3 : undefined
|
|
258
|
+
return { session: lastOf(res.map((r) => r.conversation_id).filter(Boolean)), answer, rc: errs.length || wasDenied ? 3 : undefined,
|
|
259
|
+
denied: wasDenied ? (denied.length ? denied : ["(command)"]) : undefined };
|
|
212
260
|
},
|
|
213
261
|
},
|
|
214
262
|
};
|
|
263
|
+
/** The model in an agent's argv (-m / --model / --model=x), without the provider prefix. */
|
|
264
|
+
export function argvModel(a) {
|
|
265
|
+
const i = a.findIndex((x) => x === "-m" || x === "--model");
|
|
266
|
+
const v = i >= 0 ? a[i + 1] : a.find((x) => x.startsWith("--model="))?.slice(8);
|
|
267
|
+
return v?.split("/").pop();
|
|
268
|
+
}
|
package/dist/ci.js
CHANGED
|
@@ -203,7 +203,7 @@ function notifyDesktop(issue, repo, state) {
|
|
|
203
203
|
*/
|
|
204
204
|
export function collectCi(ws, hooks = {}) {
|
|
205
205
|
// Detached: collectCi() must never block on a conductor stuck in a dialog (herdr-notify waits up to 30 min).
|
|
206
|
-
const desktop = hooks.desktop ?? notifyDesktop, toOwner = hooks.owner ?? ((pane, line) => notify(pane, line
|
|
206
|
+
const desktop = hooks.desktop ?? notifyDesktop, toOwner = hooks.owner ?? ((pane, line) => notify(pane, line)), notice = hooks.notice ?? ((l) => console.log(l));
|
|
207
207
|
const now = Date.now(), worktrees = listWorktrees(ws);
|
|
208
208
|
const found = claimedIssues(ws).flatMap(({ id, owner, kind }) => issueBranches(ws, id, worktrees).map(({ repo, branch }) => ({ id, owner, kind, repo, branch, ...prStatus(join(ws, repo), branch) })));
|
|
209
209
|
const toNotify = [];
|
|
@@ -225,7 +225,9 @@ export function collectCi(ws, hooks = {}) {
|
|
|
225
225
|
return mine;
|
|
226
226
|
});
|
|
227
227
|
for (const { owner, kind, id, repo, state, sha } of toNotify) {
|
|
228
|
-
|
|
228
|
+
// A failure the owner is told about already pops up (src/notice.ts signals it loudly): no second popup.
|
|
229
|
+
if (!(state === "failed" && owner && kind === "herdr"))
|
|
230
|
+
desktop(id, repo, state);
|
|
229
231
|
if (state === "failed" && owner) {
|
|
230
232
|
const line = `[ORQ CI] ${id} ${repo} failed (${sha.slice(0, 7)})`;
|
|
231
233
|
if (kind === "herdr")
|
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ import { block, USAGE as BLOCK } from "./commands/block.js";
|
|
|
11
11
|
import { claim, USAGE as CLAIM } from "./commands/claim.js";
|
|
12
12
|
import { ci, USAGE as CI } from "./commands/ci.js";
|
|
13
13
|
import { completion, USAGE as COMPLETION } from "./commands/completion.js";
|
|
14
|
+
import { conductor, USAGE as CONDUCTOR } from "./commands/conductor.js";
|
|
14
15
|
import { config, USAGE as CONFIG } from "./commands/config.js";
|
|
15
16
|
import { deps, USAGE as DEPS } from "./commands/deps.js";
|
|
16
17
|
import { gc, USAGE as GC } from "./commands/gc.js";
|
|
@@ -18,6 +19,7 @@ import { handoff, USAGE as HANDOFF } from "./commands/handoff.js";
|
|
|
18
19
|
import { instructions, USAGE as INSTRUCTIONS } from "./commands/instructions.js";
|
|
19
20
|
import { lang, USAGE as LANG } from "./commands/lang.js";
|
|
20
21
|
import { lock, USAGE as LOCK } from "./commands/lock.js";
|
|
22
|
+
import { noticeCmd, USAGE as NOTICE } from "./notice.js";
|
|
21
23
|
import { pick, USAGE as PICK } from "./commands/pick.js";
|
|
22
24
|
import { quota, USAGE as QUOTA } from "./commands/quota.js";
|
|
23
25
|
import { rounds, USAGE as ROUNDS } from "./commands/rounds.js";
|
|
@@ -27,7 +29,7 @@ import { setup, USAGE as SETUP } from "./commands/setup.js";
|
|
|
27
29
|
import { stats, USAGE as STATS } from "./commands/stats.js";
|
|
28
30
|
import { verify, USAGE as VERIFY } from "./commands/verify.js";
|
|
29
31
|
import { wait, USAGE as WAIT } from "./commands/wait.js";
|
|
30
|
-
const COMMANDS = { config, set, board, lang, block, quota, pick, stats, rounds, setup, lock, claim, deps, gc, ci, handoff, run, agent, wait, instructions, verify, baseline,
|
|
32
|
+
const COMMANDS = { config, conductor, set, board, lang, block, quota, pick, stats, rounds, setup, lock, claim, deps, gc, ci, handoff, run, agent, wait, instructions, verify, baseline, notice: noticeCmd,
|
|
31
33
|
completion: (a) => completion(a, Object.keys(COMMANDS)) };
|
|
32
34
|
const usage = () => `orq <command> [args]
|
|
33
35
|
|
|
@@ -48,6 +50,8 @@ ${HANDOFF}
|
|
|
48
50
|
${VERIFY}
|
|
49
51
|
${BASELINE}
|
|
50
52
|
${INSTRUCTIONS}
|
|
53
|
+
${NOTICE}
|
|
54
|
+
${CONDUCTOR}
|
|
51
55
|
${CLAIM}
|
|
52
56
|
${DEPS}
|
|
53
57
|
${GC}
|