@enderfga/claw-orchestrator 7.15.0 → 7.16.1
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 +6 -4
- package/dist/bin/cli.js +13 -6
- package/dist/bin/cli.js.map +1 -1
- package/dist/src/autoloop/dispatcher.js +50 -9
- package/dist/src/autoloop/dispatcher.js.map +1 -1
- package/dist/src/claude-goal-session.d.ts +147 -0
- package/dist/src/claude-goal-session.js +355 -0
- package/dist/src/claude-goal-session.js.map +1 -0
- package/dist/src/council.js +2 -1
- package/dist/src/council.js.map +1 -1
- package/dist/src/index.js +20 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/kernel/agent-step.d.ts +6 -0
- package/dist/src/kernel/agent-step.js.map +1 -1
- package/dist/src/kernel/nodes/goal.d.ts +11 -4
- package/dist/src/kernel/nodes/goal.js +41 -15
- package/dist/src/kernel/nodes/goal.js.map +1 -1
- package/dist/src/kernel/templates/index.d.ts +10 -8
- package/dist/src/kernel/templates/index.js +6 -5
- package/dist/src/kernel/templates/index.js.map +1 -1
- package/dist/src/kernel/types.d.ts +7 -3
- package/dist/src/kernel/types.js.map +1 -1
- package/dist/src/models.js +8 -0
- package/dist/src/models.js.map +1 -1
- package/dist/src/persistent-agy-session.js +4 -0
- package/dist/src/persistent-agy-session.js.map +1 -1
- package/dist/src/persistent-session.d.ts +9 -0
- package/dist/src/persistent-session.js +23 -0
- package/dist/src/persistent-session.js.map +1 -1
- package/dist/src/session-manager.d.ts +11 -0
- package/dist/src/session-manager.js +39 -4
- package/dist/src/session-manager.js.map +1 -1
- package/package.json +1 -1
- package/skills/references/autoloop.md +7 -3
- package/skills/references/claude-cli-tracking.md +3 -1
- package/skills/references/cli.md +22 -20
- package/skills/references/council.md +11 -0
- package/skills/references/multi-engine.md +6 -5
- package/skills/references/tools.md +20 -12
- package/skills/references/verification.md +0 -2
- package/skills/references/workflow.md +60 -16
|
@@ -348,9 +348,13 @@ compact, through the app-server's own thread compaction.
|
|
|
348
348
|
Subprocess deaths (Claude session lost), failed `git commit` in an iter, and
|
|
349
349
|
other phase-bound failures surface as `phase_error` messages instead of
|
|
350
350
|
silently masquerading as a "clarification request". An empty or whitespace-only
|
|
351
|
-
Coder reply is also a phase error.
|
|
352
|
-
`iter_complete`
|
|
353
|
-
|
|
351
|
+
Coder reply is also a phase error. A non-empty Coder reply without a valid
|
|
352
|
+
`iter_complete` returns `directive_ack` (`understood: false`) without review or
|
|
353
|
+
iteration advance. Structured `request_clarification` keeps a short
|
|
354
|
+
`clarification` question. Any other incomplete turn puts fixed status/decision
|
|
355
|
+
wording, a labelled sanitized truncated reply tail, and a write-time persisted
|
|
356
|
+
path (`iter/<n>/coder_reply_<dispatch_id>.txt`) or generic not-persisted result
|
|
357
|
+
into `clarification`. The runner counts consecutive `phase_error`s and:
|
|
354
358
|
|
|
355
359
|
1. Fires `on_phase_error` on each one (defaults to error / both channels).
|
|
356
360
|
2. After `phaseErrorCircuit` consecutive errors (default **3**) emits a
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
This document tracks which Claude Code CLI version Claw Orchestrator is currently synced to, and which features have been integrated. Recent rows also record the other engines' versions checked in the same sync.
|
|
4
4
|
|
|
5
|
-
## Currently tracked: **Claude Code CLI 2.1.
|
|
5
|
+
## Currently tracked: **Claude Code CLI 2.1.316** (as of 2026-10-31, plugin v7.16.1)
|
|
6
6
|
|
|
7
7
|
## Sync history
|
|
8
8
|
|
|
9
9
|
| Plugin Version | Claude CLI Version | Date | Notable integrations |
|
|
10
10
|
| ------------------- | ------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
+
| v7.16.1 | 2.1.316 | 2026-10-31 | CC 2.1.310→2.1.316, Codex 0.164.0→0.166.0, agy 1.4.6→1.4.12, OpenCode 1.19.4→1.19.5; grok 1.0.70 unchanged. One live turn per engine through its wrapper ok; 27 models checked against published prices, 0 drift. Integrated: agy `--settings` (1.4.12, inline JSON or a path; agy validates the keys); GPT-6.1 Terra (Codex 0.165.0). Read, no change needed: CC `CLAUDE_CODE_SUBAGENT_EFFORT`, `permissions.blockWritesOutsideWorkingDirectories`; Codex 0.165 effort changes mid-conversation on by default (codex-app already sends effort per turn); dsh 0.2.1-rc.4 keeps diagnostics off stdout in ACP mode. |
|
|
12
|
+
| v7.16.0 | 2.1.310 | 2026-10-28 | Pins as tracked in v7.15.0; not re-run live this release (installed: CC 2.1.312, Codex 0.165.0, agy 1.4.9). Integrated: `/goal` on Claude Code behind the `goal` node — measured on CC 2.1.312 in stream-json mode (bare `/goal` probe, Stop-hook turns, `interrupt` control request). |
|
|
11
13
|
| v7.15.0 | 2.1.310 | 2026-10-26 | Engine versions as tracked in v7.14.0 (agy 1.4.7 is installed but not yet run live; the pin stays 1.4.6). Integrated: `codex-app` passes reasoning effort — `turn/start` `effort` and `model_reasoning_effort` in the thread `config` on `thread/start` / `thread/resume` (Codex 0.164.0). |
|
|
12
14
|
| v7.14.0 | 2.1.310 | 2026-10-25 | CC 2.1.307→2.1.310, agy 1.4.4→1.4.6, grok 1.0.67→1.0.70, OpenCode 1.19.3→1.19.4; Codex 0.164.0 unchanged. No flag the wrappers pass changed; one live turn per engine ok. Integrated: the `acp` engine (an ACP client over `@agentclientprotocol/sdk` 1.3.0), run against Kimi Code 2.3.1 (`kimi acp`, model from `KIMI_MODEL_*`), dsh 0.2.1-rc.2 (`dsh --profile acp`, `--patch` honoured) and OpenCode 1.19.4 (`opencode acp`, recall across a resumed session). Kimi Code and dsh report no usage over ACP. |
|
|
13
15
|
| v7.13.0 | 2.1.307 | 2026-10-24 | Codex 0.163.0→0.164.0; the other engines as tracked in v7.12.1. Integrated: Codex 0.164 app-server goal RPCs (`thread/goal/set` / `get` / `clear`, six goal states, `tokenBudget`, `thread/goal/updated`), structured `error` notifications (`codexErrorInfo`, `willRetry`), `turn/steer` during goal turns, and `approvalPolicy` on `thread/start` / `thread/resume`; the `goal` workflow node is built on them. Measured: a goal objective is capped at 4,000 characters, and a thread can be resumed only after its first turn. |
|
package/skills/references/cli.md
CHANGED
|
@@ -263,34 +263,36 @@ clawo fanout "<task>" [--engines <list>] [--synthesize] [--check "<command>"]...
|
|
|
263
263
|
|
|
264
264
|
## `clawo goal`
|
|
265
265
|
|
|
266
|
-
Run a
|
|
267
|
-
|
|
266
|
+
Run a `/goal` on one thread — a Codex `codex-app` thread, or a Claude Code
|
|
267
|
+
session with `--engine claude` — then have the runtime check the result: goal →
|
|
268
|
+
verify → repair on the same thread. See [workflow.md](./workflow.md#goal).
|
|
268
269
|
|
|
269
270
|
```bash
|
|
270
271
|
clawo goal "<objective>" | --objective-file <file>
|
|
271
272
|
[--check "<command>"]... [--contract <file>] [--check-timeout <minutes>]
|
|
272
|
-
[--launcher <arg>]... [--model <model>] [--effort <level>] [--sandbox <mode>] [--thread <id>]
|
|
273
|
+
[--engine codex|claude] [--launcher <arg>]... [--model <model>] [--effort <level>] [--sandbox <mode>] [--thread <id>]
|
|
273
274
|
[--token-budget N] [--goal-timeout <minutes>] [--max-repairs N]
|
|
274
275
|
[--cwd <dir>] [--wait] [--json]
|
|
275
276
|
```
|
|
276
277
|
|
|
277
|
-
| Option | Default | Notes
|
|
278
|
-
| ------------------ | ----------------- |
|
|
279
|
-
| `--objective-file` | — | Read the objective from a file instead of the argument.
|
|
280
|
-
| `-
|
|
281
|
-
|
|
|
282
|
-
| `--
|
|
283
|
-
| `--
|
|
284
|
-
|
|
|
285
|
-
|
|
|
286
|
-
| `--
|
|
287
|
-
| `--
|
|
288
|
-
| `--
|
|
289
|
-
| `--
|
|
290
|
-
| `--
|
|
291
|
-
| `--
|
|
292
|
-
|
|
|
293
|
-
|
|
|
278
|
+
| Option | Default | Notes |
|
|
279
|
+
| ------------------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
280
|
+
| `--objective-file` | — | Read the objective from a file instead of the argument. A goal accepts at most 4,000 characters |
|
|
281
|
+
| `-e, --engine` | `codex` | Who runs the goal: `codex` (a `codex-app` thread) or `claude` (a Claude Code session) |
|
|
282
|
+
| `-c, --check` | — | A command check, repeatable, run after the goal. Split on whitespace; quote-needing commands go in `--contract` |
|
|
283
|
+
| `--contract` | — | A contract JSON file; `--check` entries are appended to it |
|
|
284
|
+
| `--check-timeout` | 10 | Minutes for each `--check` (at least 1). The verifier's node timeout is sized from the checks |
|
|
285
|
+
| `--launcher` | — | Run the engine under this command, one argv element per flag: `--launcher ./sandbox.sh --launcher task --launcher "0 1"` |
|
|
286
|
+
| `-m, --model` | the engine's own | Model |
|
|
287
|
+
| `--effort` | the engine's own | Reasoning effort |
|
|
288
|
+
| `--sandbox` | `workspace-write` | Codex's own sandbox mode (claude has none). With an outer sandbox as the boundary, `danger-full-access` |
|
|
289
|
+
| `--thread` | — | Start on this existing codex thread or claude session: its goal is replaced, its history kept |
|
|
290
|
+
| `--token-budget` | — | The goal stops as `budgetLimited` past this |
|
|
291
|
+
| `--goal-timeout` | none | Wall-clock minutes for one goal pass |
|
|
292
|
+
| `--max-repairs` | `1` | Times a red verdict sends the goal back to the same thread |
|
|
293
|
+
| `--cwd` | current directory | Project directory |
|
|
294
|
+
| `-w, --wait` | off | Follow the run; exit `0` only if it completes |
|
|
295
|
+
| `--json` | off | Print `{ runId, state }`, or with `--wait` the final run record |
|
|
294
296
|
|
|
295
297
|
`clawo workflow show <runId>` prints the goal's status, tokens, time, resume
|
|
296
298
|
attempts and thread id while it runs; `clawo workflow steer <runId> "<text>"`
|
|
@@ -229,6 +229,17 @@ The charter is each seat's only instruction channel, and it reaches every engine
|
|
|
229
229
|
natively on Claude Code and Grok, as the top of the seat's first message on Codex, Antigravity and OpenCode.
|
|
230
230
|
Nothing is written into the worktrees.
|
|
231
231
|
|
|
232
|
+
## Member session names
|
|
233
|
+
|
|
234
|
+
Each council member starts an internal `SessionManager` session named
|
|
235
|
+
`{councilRunId}-{memberName}-r{round}` (for example
|
|
236
|
+
`council-m1abc2de-9f3c1a2b-Architect-r1`). The name carries the complete council
|
|
237
|
+
run id so two concurrent councils that share a member name and round do not
|
|
238
|
+
reuse one engine session, working directory, or cleanup target. `sessionKey` on
|
|
239
|
+
each agent response is that opaque name; callers should treat it as an opaque
|
|
240
|
+
handle, not parse it. `parentRunId` on ledger turns remains the full council run
|
|
241
|
+
id.
|
|
242
|
+
|
|
232
243
|
## Transcript Logging
|
|
233
244
|
|
|
234
245
|
All council sessions save transcripts to `~/.openclaw/council-logs/council-<timestamp>.md`. Transcripts are for humans to read; nothing parses them. Completed councils stay queryable via `council_status` indefinitely — the run record is on disk.
|
|
@@ -45,7 +45,7 @@ as options (see the notes under [Antigravity](#google-antigravity-engine-agy) an
|
|
|
45
45
|
|
|
46
46
|
### Claude Code (`engine: 'claude'`)
|
|
47
47
|
|
|
48
|
-
Default engine. Long-running subprocess with streaming JSON I/O. Tested with Claude Code CLI **2.1.
|
|
48
|
+
Default engine. Long-running subprocess with streaming JSON I/O. Tested with Claude Code CLI **2.1.316**.
|
|
49
49
|
|
|
50
50
|
- Persistent multi-turn conversations
|
|
51
51
|
- Real-time streaming (text, tool_use, tool_result, system events)
|
|
@@ -82,7 +82,7 @@ await manager.startSession({
|
|
|
82
82
|
|
|
83
83
|
### OpenAI Codex (`engine: 'codex'`)
|
|
84
84
|
|
|
85
|
-
Wraps the `codex exec` subcommand. Each `send()` spawns a new process. Tested with `codex` CLI **0.
|
|
85
|
+
Wraps the `codex exec` subcommand. Each `send()` spawns a new process. Tested with `codex` CLI **0.166.0**.
|
|
86
86
|
|
|
87
87
|
- Non-interactive execution via `codex exec --sandbox workspace-write --skip-git-repo-check --json`
|
|
88
88
|
- Real `usage` from the `turn.completed` JSON event (input, output, cached, reasoning tokens). **These are cumulative over the thread, not per turn**, so they replace the session totals rather than being added to them; subtracting consecutive values gives one turn's prompt
|
|
@@ -120,7 +120,7 @@ await manager.startSession({
|
|
|
120
120
|
|
|
121
121
|
### OpenAI Codex App-Server (`engine: 'codex-app'`)
|
|
122
122
|
|
|
123
|
-
Wraps `codex app-server --listen stdio:// --enable goals` as a long-running JSON-RPC subprocess. **Required for `/goal` long-horizon objective support** — Codex's exec subcommand has no goal surface. Tested with `codex` CLI **0.
|
|
123
|
+
Wraps `codex app-server --listen stdio:// --enable goals` as a long-running JSON-RPC subprocess. **Required for `/goal` long-horizon objective support** — Codex's exec subcommand has no goal surface. Tested with `codex` CLI **0.166.0**.
|
|
124
124
|
|
|
125
125
|
- Long-running subprocess; one `codex app-server` per session
|
|
126
126
|
- JSON-RPC 2.0 over stdio with v2 protocol method names (`initialize`, `thread/start`, `turn/start`, ...)
|
|
@@ -152,7 +152,7 @@ await manager.codexGoal('codex-goal-task', { action: 'set', objective: 'build a
|
|
|
152
152
|
|
|
153
153
|
Wraps Google's **Antigravity CLI** (`agy`) — the successor to Gemini CLI (consumer
|
|
154
154
|
Gemini CLI tiers stopped serving 2026-06-18). Each `send()` spawns a new process
|
|
155
|
-
in print mode, with the message as the `-p` argument. Tested with `agy` **1.4.
|
|
155
|
+
in print mode, with the message as the `-p` argument. Tested with `agy` **1.4.12**.
|
|
156
156
|
|
|
157
157
|
- One-shot execution per message (no persistent subprocess)
|
|
158
158
|
- **Structured output and real usage** — `--output-format stream-json` emits an
|
|
@@ -196,6 +196,7 @@ in print mode, with the message as the `-p` argument. Tested with `agy` **1.4.6*
|
|
|
196
196
|
must explicitly choose `bypassPermissions` for a write-enabled session; it is
|
|
197
197
|
not a recovery mechanism. In particular, an Autoloop Planner stays on
|
|
198
198
|
`--mode plan` when its preserved conversation is resumed.
|
|
199
|
+
- `settings` is passed as `--settings`: settings.json keys as inline JSON or a file path, for this run only. agy refuses a key it does not know.
|
|
199
200
|
- The engine always passes `--print-timeout`, set just inside the send timeout
|
|
200
201
|
(10% earlier, at most 10s). Since agy 1.2.9 a headless run whose agent started a
|
|
201
202
|
background task (a dev server, a watcher) stays open until that deadline and
|
|
@@ -304,7 +305,7 @@ await manager.startSession({
|
|
|
304
305
|
|
|
305
306
|
### OpenCode (`engine: 'opencode'`)
|
|
306
307
|
|
|
307
|
-
Wraps the [OpenCode](https://github.com/anomalyco/opencode) CLI with `run --format json`. Each `send()` spawns a new process. Tested with `opencode` **1.19.
|
|
308
|
+
Wraps the [OpenCode](https://github.com/anomalyco/opencode) CLI with `run --format json`. Each `send()` spawns a new process. Tested with `opencode` **1.19.5**.
|
|
308
309
|
|
|
309
310
|
- Conversation continuity: the session id from the event envelope is captured and passed back as `--session <id>` on later sends, so the model sees prior turns. `--continue` is deliberately not used: it means "the last session on this machine", which collides between concurrent sessions.
|
|
310
311
|
- NDJSON event stream with envelope `{ type, timestamp, sessionID, ... }`
|
|
@@ -35,7 +35,7 @@ else the value applies.
|
|
|
35
35
|
| `resumeSessionId` | string | Resume an earlier conversation by the engine's own id: a Claude Code session id, a Codex or `codex-app` thread id, an Antigravity conversation id, a Grok or OpenCode session id, an ACP agent's session id, or a custom engine's id when its config maps a resume flag |
|
|
36
36
|
| `jsonSchema` | string | JSON Schema for structured output. Claude and Grok: `--json-schema` (inline). Codex: `--output-schema` (written to a temp file, requires Codex 0.132+). Other engines ignore it. |
|
|
37
37
|
| `mcpConfig` | string \| string[] | MCP server config file(s) |
|
|
38
|
-
| `settings` | string | Settings.json path or inline JSON
|
|
38
|
+
| `settings` | string | Settings.json path or inline JSON, for this session only. Claude Code and Antigravity (`agy --settings`, which validates its keys) take it |
|
|
39
39
|
| `pluginUrl` | string \| string[] | Claude only. Plugin `.zip` URL(s) fetched for this session only (`--plugin-url`) |
|
|
40
40
|
| `ultracode` | boolean | Claude only. Enable "ultracode" / dynamic workflows — Claude plans a JS orchestration script per substantive task and fans out to subagents. Injected as the `ultracode:true` settings key (merged into `settings`). The workflow runs in the background: `session_send` returns at launch, and the completion turn is not returned by a later send (see [sessions.md](./sessions.md#ultracode-claude-dynamic-workflows)). |
|
|
41
41
|
| `noSessionPersistence` | boolean | Do not save session to disk — both the engine's own transcript and this orchestrator's resume registry, so a later start under the same name does not reattach |
|
|
@@ -370,23 +370,31 @@ Run one task across N engine/model agents **in parallel** and collect their answ
|
|
|
370
370
|
|
|
371
371
|
### `fanout_start`
|
|
372
372
|
|
|
373
|
-
| Parameter | Type | Required | Description
|
|
374
|
-
| ------------------------------------ | ------- | -------- |
|
|
375
|
-
| `task` | string | yes | Shared task sent to every agent, optionally after its `persona`.
|
|
376
|
-
| `projectDir` | string | yes | Working directory all agents run in.
|
|
377
|
-
| `agents` | array | yes | Up to 16 specs: `{ name, engine?, model?, effort?, prompt?, persona?, baseUrl?, permissionMode?, customEngine?, acpAgent? }`. Names must be unique (each forms a session name); `permissionMode` defaults to `bypassPermissions`. |
|
|
378
|
-
| `synthesize` | boolean | | Run a final synthesis pass over the successful results (needs ≥2).
|
|
379
|
-
| `synthesisModel` / `synthesisEngine` | string | | Model/engine for the synthesis pass (default engine `claude`).
|
|
380
|
-
| `synthesisAcpAgent` | string | | With `synthesisEngine: 'acp'`: the ACP agent preset the synthesis pass starts.
|
|
381
|
-
| `agentTimeoutMs` | number | | Per-agent timeout (default 600000).
|
|
382
|
-
| `maxTurnsPerAgent` | number | | Max agent loop turns (default 30).
|
|
383
|
-
| `maxBudgetUsd` | number | | Per-agent spend cap.
|
|
373
|
+
| Parameter | Type | Required | Description |
|
|
374
|
+
| ------------------------------------ | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
375
|
+
| `task` | string | yes | Shared task sent to every agent, optionally after its `persona`. |
|
|
376
|
+
| `projectDir` | string | yes | Working directory all agents run in. |
|
|
377
|
+
| `agents` | array | yes | Up to 16 specs: `{ name, engine?, model?, effort?, prompt?, persona?, baseUrl?, permissionMode?, sandboxMode?, customEngine?, acpAgent? }`. Names must be unique (each forms a session name); `permissionMode` defaults to `bypassPermissions`. |
|
|
378
|
+
| `synthesize` | boolean | | Run a final synthesis pass over the successful results (needs ≥2). |
|
|
379
|
+
| `synthesisModel` / `synthesisEngine` | string | | Model/engine for the synthesis pass (default engine `claude`). |
|
|
380
|
+
| `synthesisAcpAgent` | string | | With `synthesisEngine: 'acp'`: the ACP agent preset the synthesis pass starts. |
|
|
381
|
+
| `agentTimeoutMs` | number | | Per-agent timeout (default 600000). |
|
|
382
|
+
| `maxTurnsPerAgent` | number | | Max agent loop turns (default 30). |
|
|
383
|
+
| `maxBudgetUsd` | number | | Per-agent spend cap. |
|
|
384
384
|
|
|
385
385
|
Runs in the background; returns `{ ok, id, status, ... }`. Poll with `fanout_status`.
|
|
386
386
|
Each agent's optional `effort` accepts `low`, `medium`, `high`, `xhigh`, `max`,
|
|
387
387
|
`ultra`, or `auto`. Omit it to keep the session default. The engine applies or
|
|
388
388
|
clamps the value as documented for `session_start`.
|
|
389
389
|
|
|
390
|
+
Per-agent `permissionMode` uses the same enum and each engine's own permission
|
|
391
|
+
handling as `session_start`. Workers that must not write should set
|
|
392
|
+
`sandboxMode` to `read-only`. Per-agent `sandboxMode` (`read-only` \|
|
|
393
|
+
`workspace-write` \| `danger-full-access`) uses the same values and per-engine
|
|
394
|
+
behavior as `session_start` (omit to keep the session default). These worker
|
|
395
|
+
fields do not constrain optional synthesis, and `fanout_start` does not expose a
|
|
396
|
+
synthesis permission override.
|
|
397
|
+
|
|
390
398
|
Per-agent `persona` provides role instructions without replacing the shared
|
|
391
399
|
task. Fan-out sends `<persona>\n\n## Shared task\n\n<task>`. A non-empty
|
|
392
400
|
per-agent `prompt` keeps its original full-override semantics: it is sent by
|
|
@@ -20,8 +20,6 @@ goes through `normalizeContract()`, which drops anything it does not recognise,
|
|
|
20
20
|
it carries no fields the executor did not model; one with no recognised check is
|
|
21
21
|
refused before the run starts. That argument takes each check bare,
|
|
22
22
|
`{ "type": "command", … }`, or wrapped, `{ "id"?, "spec": { … }, "required"? }`.
|
|
23
|
-
A contract written inside a spec — `spec.contract`, or a verifier's inline
|
|
24
|
-
`contract` — is used as written, so its checks must be in the wrapped form.
|
|
25
23
|
|
|
26
24
|
A workflow start normalises every contract the run carries the same way: the
|
|
27
25
|
`contract` start option, the spec's own `contract`, and each verifier node's
|
|
@@ -157,12 +157,12 @@ is unrecoverable and reads back as "not found".
|
|
|
157
157
|
| `agent` | One session, one turn. A new session per attempt unless `sessionName` pins one |
|
|
158
158
|
| `fanout` | N agents in parallel on a shared prompt, optional synthesis pass. Succeeds when at least one agent does |
|
|
159
159
|
| `council` | The council engine; its votes are recorded as advisory. Fails only when the council itself errors |
|
|
160
|
-
| `verifier` | Runs an acceptance contract, writes evidence — see [`verification.md`](./verification.md). `"contract": "run"` with no run-level contract passes through and verifies nothing; an inline contract with no recognised check is refused at start
|
|
160
|
+
| `verifier` | Runs an acceptance contract, writes evidence — see [`verification.md`](./verification.md). `"contract": "run"` with no run-level contract passes through and verifies nothing; an inline contract with no recognised check is refused at start |
|
|
161
161
|
| `human_gate` | Parks the run until a person answers; a rejection fails the run |
|
|
162
162
|
| `router` | Picks the next node from declarative conditions; a backwards route is the loop |
|
|
163
163
|
| `subflow` | Runs another workflow as a child run and adopts its verdict, with the tree digest the verdict was taken against; a child that ends `unverified` hands up no verdict |
|
|
164
164
|
| `autoloop` | A long-lived Planner / Coder / Reviewer loop; its executor is injected. On the node's first visit (`visits === 1`) the shared fresh-start boundary applies (dirty-worktree refusal + run-local `tasks/<config.runId>/.gitignore`); resume and later visits skip it. |
|
|
165
|
-
| `goal` | A
|
|
165
|
+
| `goal` | A `/goal` on one Codex `codex-app` thread or Claude Code session, run until the goal finishes — see [below](#goal) |
|
|
166
166
|
| `ultraapp_synth`, `ultraapp_deploy` | UltraApp's synth and deploy stages; their executors are injected too |
|
|
167
167
|
|
|
168
168
|
### Spec and node fields
|
|
@@ -194,12 +194,12 @@ The kind-specific fields:
|
|
|
194
194
|
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
195
195
|
| `agent` | `prompt` (required); `engine`, `model`, `effort`, `acpAgent` (a bundled ACP preset id, for `engine: "acp"`); `cwd` (default: the run's); `sessionName`, to reuse one named session across nodes; `permissionMode` (default `bypassPermissions`); `appendSystemPrompt`, standing instructions for the session |
|
|
196
196
|
| `fanout` | `prompt` (required, the shared task) and `agents` (required); `synthesize`, `synthesisEngine` (default `claude`), `synthesisModel`, `synthesisAcpAgent`, `synthesisPermissionMode` (default `bypassPermissions`); `maxTurnsPerAgent` and `maxBudgetUsd`, per agent; `cwd`; `agentTimeoutMs` |
|
|
197
|
-
| `council` | `task` (required) and `agents` (required); `projectDir` (default: the run's cwd); `maxRounds` (default 15, as for `council_start`); `maxTurnsPerAgent` and `maxBudgetUsd`, per agent; `defaultPermissionMode`; `agentTimeoutMs`
|
|
197
|
+
| `council` | `task` (required) and `agents` (required); `projectDir` (default: the run's cwd); `maxRounds` (default 15, as for `council_start`); `maxTurnsPerAgent` and `maxBudgetUsd`, per agent; `defaultPermissionMode`; `agentTimeoutMs` |
|
|
198
198
|
| `verifier` | `contract` (required): an inline contract, or `"run"` for the run-level one; `cwd` (default: the run's) |
|
|
199
199
|
| `human_gate` | `prompt` (required) |
|
|
200
200
|
| `router` | `routes` (required): `[{ "when": <condition>, "to": <node id> }]`, first match wins; `default`, taken when nothing matches (omitted: fall through to the next node) |
|
|
201
201
|
| `subflow` | `workflow` (required): an inline `WorkflowSpec`, or the id of an existing run, whose stored spec runs again as a new child run. Template names do not resolve here |
|
|
202
|
-
| `goal` | `objective` (required); `cwd`, `model`, `effort`, `sandboxMode`, `launcher`, `threadId`, `tokenBudget`, `capacityRetry`, `stallMs` — see [Goal](#goal)
|
|
202
|
+
| `goal` | `objective` (required); `engine`, `cwd`, `model`, `effort`, `sandboxMode`, `launcher`, `threadId`, `tokenBudget`, `capacityRetry`, `stallMs` — see [Goal](#goal) |
|
|
203
203
|
| `autoloop` | `workspace` and `config` (the `autoloop_start` options). Started by `autoloop_start` |
|
|
204
204
|
| `ultraapp_synth`, `ultraapp_deploy` | `appRunId`, `runDir`, `slug`; the deploy stage adds `version` and `codebasePath`. Started by UltraApp builds |
|
|
205
205
|
|
|
@@ -306,11 +306,11 @@ with `visits_lt`.
|
|
|
306
306
|
}
|
|
307
307
|
```
|
|
308
308
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
309
|
+
Every contract a run carries — the run-level `contract`, a verifier's inline one,
|
|
310
|
+
and the `contract` argument of `workflow_start` and `POST /workflow/new` — is
|
|
311
|
+
normalized at start, so a check may be written bare (`{ "type": "command", … }`) or
|
|
312
|
+
in the `{ "spec": { … } }` wrapper shown here, with `id` and `required` beside
|
|
313
|
+
`spec`. The `contract` argument, when given, replaces the spec's own.
|
|
314
314
|
See [`verification.md`](./verification.md#the-one-rule-about-where-contracts-come-from).
|
|
315
315
|
|
|
316
316
|
When the router sends control back to `implement`, the agent is told what the
|
|
@@ -333,7 +333,7 @@ specs and post them.
|
|
|
333
333
|
| `solve` | `triage` (fan-out) → `approve` (human gate, only with `humanGate`) → `implement` (agent) → `review` (fan-out, only with `reviewers`) → `verify` → `repair-gate` (router) | `agents` (the triage scouts; default one agent on the default engine), `implementer` (`engine`, `model`), `reviewers`, `humanGate`, `maxRepairs` (default 3), `contract` |
|
|
334
334
|
| `council` | `council`, then `__verify` when a contract is declared | `agents`, `maxRounds` (default 15), `contract` |
|
|
335
335
|
| `fanout` | `fanout`, then `__verify` when a contract is declared | `agents`, `contract` |
|
|
336
|
-
| `goal` | `goal` → `verify` → `repair-gate` (router); `task` is the objective. See [below](#goal) | `model`, `tokenBudget`, `launcher`, `maxRepairs` (default 1), `contract`
|
|
336
|
+
| `goal` | `goal` → `verify` → `repair-gate` (router); `task` is the objective. See [below](#goal) | `engine` (`codex` default, or `claude`), `model`, `tokenBudget`, `launcher`, `maxRepairs` (default 1), `contract` |
|
|
337
337
|
|
|
338
338
|
`solve` is the shape above: the triage and review fan-outs add a synthesis pass
|
|
339
339
|
when they have two or more agents, `implement` and `review` continue on failure so
|
|
@@ -349,16 +349,19 @@ somewhere to deploy to), which only UltraApp starts.
|
|
|
349
349
|
|
|
350
350
|
## Goal
|
|
351
351
|
|
|
352
|
-
A `goal` node runs one
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
352
|
+
A `goal` node runs one `/goal` on one thread: a Codex `codex-app` thread by
|
|
353
|
+
default, or a Claude Code session with `"engine": "claude"` (see
|
|
354
|
+
[On Claude Code](#on-claude-code)). Codex's app-server runs the goal itself:
|
|
355
|
+
`thread/goal/set` starts its turn loop, which keeps going until the goal is
|
|
356
|
+
`complete`, out of budget, `blocked`, or stopped by a usage limit. The node adds
|
|
357
|
+
what an unattended run needs around that loop.
|
|
356
358
|
|
|
357
359
|
```jsonc
|
|
358
360
|
{
|
|
359
361
|
"id": "goal",
|
|
360
362
|
"kind": "goal",
|
|
361
363
|
"objective": "Reach the goal described in GOAL.md …",
|
|
364
|
+
"engine": "codex", // default; or "claude"
|
|
362
365
|
"cwd": "/work/task/ws",
|
|
363
366
|
"model": "gpt-6.1-sol", // optional; codex's own default otherwise
|
|
364
367
|
"effort": "high", // optional reasoning effort
|
|
@@ -417,6 +420,47 @@ by a usage limit. The node adds what an unattended run needs around that loop.
|
|
|
417
420
|
reason. Cancel interrupts the running turn and pauses the goal, and so does a
|
|
418
421
|
`timeoutMs` that runs out. Like `autoloop`, the node has no default timeout.
|
|
419
422
|
|
|
423
|
+
### On Claude Code
|
|
424
|
+
|
|
425
|
+
With `"engine": "claude"` the same node drives Claude Code's `/goal` (CLI
|
|
426
|
+
2.1.139 or later) through `ClaudeGoalSession`. Claude Code has no goal RPCs or
|
|
427
|
+
goal notifications, so the adapter reads the goal from what the CLI does in
|
|
428
|
+
stream-json mode:
|
|
429
|
+
|
|
430
|
+
- `/goal <objective>` sets the goal and starts working. A Stop hook — a separate
|
|
431
|
+
model judging the condition against the session — runs after every turn and
|
|
432
|
+
feeds the turn back while the condition does not hold, all inside one send;
|
|
433
|
+
one `result` arrives when the goal is met, and the goal clears itself.
|
|
434
|
+
- A bare `/goal` answers at once, without a model turn — `Goal active: …` or
|
|
435
|
+
`No goal set.` A failed turn clears the goal too, so a gone goal is not proof:
|
|
436
|
+
the goal is `complete` only when a turn that started with it set ended without
|
|
437
|
+
an error and it is gone after. A goal still set with nothing driving it, a
|
|
438
|
+
failed turn, and a reopened session whose goal is gone are `paused`, which the
|
|
439
|
+
node resumes within its bound. Resuming sends a short "continue" message when
|
|
440
|
+
the goal is still set and sets it again (`/goal <objective>`) when it is not,
|
|
441
|
+
so a goal that was already met costs one turn to confirm.
|
|
442
|
+
- A failed turn is read from its text: usage limits become `usageLimited`,
|
|
443
|
+
overloaded and 5xx errors the matching transient codes, so the node backs off
|
|
444
|
+
and resumes as it does for Codex. A failed login is `blocked` at once.
|
|
445
|
+
- When the Stop hook blocks the agent's stop nine times running, the CLI ends
|
|
446
|
+
the turn anyway and says so; the goal is then `blocked` (the agent keeps
|
|
447
|
+
asking to stop, and continuing only repeats that). The template's verifier
|
|
448
|
+
still judges the tree. Write the objective as a condition the agent can show
|
|
449
|
+
it met from inside the session; one that depends on something after the
|
|
450
|
+
agent stops can never be met.
|
|
451
|
+
- The session id is the thread id. A new session is started with
|
|
452
|
+
`--session-id` so it is known before the goal is set, and the session is kept
|
|
453
|
+
out of the registry with `skipPersistence` (not `noSessionPersistence`, which
|
|
454
|
+
would stop the CLI writing the transcript `--resume` needs). A reopened
|
|
455
|
+
process resumes it with `--resume`; the goal is still set there, so the node
|
|
456
|
+
continues it at once.
|
|
457
|
+
- Steers are written into the running turn, which the CLI folds in. Cancel and
|
|
458
|
+
pause send stream-json's `interrupt` control request; the goal stays set.
|
|
459
|
+
- `tokensUsed` counts the session's input, output and cache-read tokens, and is
|
|
460
|
+
carried across reopened processes. `tokenBudget` counts from when the current
|
|
461
|
+
objective was set; past it the turn is interrupted and the goal ends
|
|
462
|
+
`budgetLimited`. `sandboxMode` does not apply; put the boundary in `launcher`.
|
|
463
|
+
|
|
420
464
|
The `goal` template wraps this in `goal → verify → repair-gate`. The goal node
|
|
421
465
|
continues on failure, so a goal that ran out of budget is still judged. The
|
|
422
466
|
verifier's node timeout is sized from the contract — the sum of every check's
|
|
@@ -472,8 +516,8 @@ which is not the same as success.
|
|
|
472
516
|
The implicit `__verify` is the last node, and a run only ends `completed` after
|
|
473
517
|
its last node has run, so every such path is checked. A spec that places its own
|
|
474
518
|
`"contract": "run"` verifier gets no `__verify`, and must route every path through
|
|
475
|
-
that node: a run whose path skips it ends `
|
|
476
|
-
|
|
519
|
+
that node: a run whose path skips it ends `failed` / `unverified`, with no check
|
|
520
|
+
run (see below).
|
|
477
521
|
|
|
478
522
|
A run whose spec declares a run-level `contract` cannot complete without having
|
|
479
523
|
run it. The kernel appends a terminal verifier unless the spec places its own
|