@enderfga/claw-orchestrator 7.15.0 → 7.16.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.
@@ -0,0 +1,147 @@
1
+ /**
2
+ * A Claude Code `/goal` behind the `GoalSession` surface the kernel's `goal`
3
+ * node drives, so one node runs a goal on either engine.
4
+ *
5
+ * Codex's app-server owns a goal: it has RPCs to set, pause and read it, and
6
+ * notifies every status change. Claude Code has none of that. What it has,
7
+ * measured on CLI 2.1.312 in stream-json mode:
8
+ *
9
+ * - `/goal <condition>` sets the goal and starts working. A Stop hook judges
10
+ * the condition after every turn and feeds the turn back while it does not
11
+ * hold, all inside the one send; a single `result` arrives when the goal is
12
+ * met, and the goal clears itself.
13
+ * - A bare `/goal` answers at once, without a model turn: `Goal active: …` or
14
+ * `No goal set. …`. That is the only way to read the goal.
15
+ * - The goal is part of the transcript. A process that dies and is resumed
16
+ * with `--resume` still has it, but nothing drives it until a message comes.
17
+ * - The `interrupt` control request ends the running turn with an
18
+ * `error_during_execution` result and leaves the goal set.
19
+ * - A turn that fails (an auth error, a usage limit) ends with an `is_error`
20
+ * result, and the CLI clears the goal then too ("Goal cleared after an
21
+ * unrecoverable error"). "No goal set" alone does not mean the goal was met.
22
+ * - The condition is judged by a separate model reading the transcript, not by
23
+ * the agent. When it blocks the agent's stop 9 times running, the CLI ends
24
+ * the turn anyway and says so in an `informational` system event; the goal
25
+ * stays set.
26
+ *
27
+ * So the status here is partly the adapter's own bookkeeping. `active` while a
28
+ * goal turn runs. `complete` only when a turn that started with the goal set
29
+ * ended without an error and the goal is gone: the Stop hook let it end. A
30
+ * goal still set with nothing driving it, a failed turn, and a reopened thread
31
+ * whose goal is gone are all `paused`, which the node resumes within its bound;
32
+ * resuming re-arms the goal (`/goal <objective>` again) when the CLI dropped
33
+ * it, so a goal already met costs one turn to confirm. A failed login is
34
+ * `blocked`: resuming cannot fix it. So is a turn the CLI had to end over the
35
+ * Stop hook: the agent asked to stop again and again, and continuing it only
36
+ * repeats that. The node goes on to its verifier either way, and the contract,
37
+ * not the agent or the hook, decides.
38
+ *
39
+ * Tokens are the session's input, output and cache-read tokens; the CLI reports
40
+ * no goal-level count. A reopened process starts its counters at zero, so the
41
+ * node hands over what the thread had already spent.
42
+ */
43
+ import { EventEmitter } from 'node:events';
44
+ import type { GoalSession, GoalSnapshot } from './kernel/nodes/goal.js';
45
+ /** What the adapter needs from a `claude` session. `PersistentClaudeSession` provides it. */
46
+ export interface ClaudeGoalHost {
47
+ readonly sessionId?: string;
48
+ send(message: string, options?: {
49
+ waitForComplete?: boolean;
50
+ timeout?: number;
51
+ }): Promise<unknown>;
52
+ interruptTurn(): boolean;
53
+ getStats(): {
54
+ tokensIn: number;
55
+ tokensOut: number;
56
+ cachedTokens: number;
57
+ };
58
+ on(event: string, listener: (...args: unknown[]) => void): unknown;
59
+ off(event: string, listener: (...args: unknown[]) => void): unknown;
60
+ }
61
+ /** What the thread had already spent when this process opened it. */
62
+ export interface ClaudeGoalOpen {
63
+ /** The session id the process was started with (`--session-id` or `--resume`). */
64
+ threadId?: string;
65
+ /** The process resumed an existing thread: a goal set on it is not new. */
66
+ resumed?: boolean;
67
+ /** The objective the thread was last given, as the node checkpointed it. */
68
+ objective?: string;
69
+ tokensUsed?: number;
70
+ timeUsedSeconds?: number;
71
+ }
72
+ type GoalError = {
73
+ message: string;
74
+ code: string | null;
75
+ willRetry: boolean;
76
+ at: string;
77
+ };
78
+ /** Sent to pick a goal back up: the Stop hook keeps it going from there. */
79
+ export declare const CLAUDE_GOAL_CONTINUE = "Continue working toward the active goal. Pick up from where the work stands now.";
80
+ /** Map a failed turn's text onto the codex error codes the node treats as transient. */
81
+ export declare function classifyClaudeError(text: string, apiStatus?: unknown): string | null;
82
+ /** Read a bare `/goal` answer. */
83
+ export declare function parseGoalProbe(text: string): {
84
+ active: true;
85
+ objective: string;
86
+ } | {
87
+ active: false;
88
+ } | undefined;
89
+ export declare class ClaudeGoalSession extends EventEmitter implements GoalSession {
90
+ readonly host: ClaudeGoalHost;
91
+ private readonly open;
92
+ private _goal;
93
+ private _lastError;
94
+ private _turnActive;
95
+ private _interrupting;
96
+ /** The CLI held the goal when the running (or last) turn started. */
97
+ private _armed;
98
+ /** The CLI's notice that it ended the running turn over the Stop hook. */
99
+ private _hookOverride;
100
+ private readonly _tokensAtOpen;
101
+ private _budgetFrom;
102
+ private _turnStartedAt;
103
+ private _timeUsed;
104
+ private readonly _seedTokens;
105
+ private readonly _onText;
106
+ private readonly _onClose;
107
+ /** `_settle` reading why the last turn ended; nothing else may probe meanwhile. */
108
+ private _settling;
109
+ private readonly _onResult;
110
+ private readonly _onSystem;
111
+ constructor(host: ClaudeGoalHost, open?: ClaudeGoalOpen);
112
+ /** Stop listening to the host. The session itself is the manager's to stop. */
113
+ detach(): void;
114
+ /** The Claude session id. Named for the interface, which Codex defined. */
115
+ get codexThreadId(): string | undefined;
116
+ get goal(): GoalSnapshot | null;
117
+ get lastError(): GoalError | null;
118
+ get turnActive(): boolean;
119
+ setGoal(p: {
120
+ objective?: string;
121
+ status?: 'active' | 'paused';
122
+ tokenBudget?: number | null;
123
+ }): Promise<GoalSnapshot>;
124
+ getGoal(): Promise<GoalSnapshot | null>;
125
+ clearGoal(): Promise<void>;
126
+ steer(text: string): Promise<{
127
+ steered: boolean;
128
+ }>;
129
+ interrupt(): Promise<{
130
+ interrupted: boolean;
131
+ }>;
132
+ private _sessionTokens;
133
+ private _tokensUsed;
134
+ private _seconds;
135
+ private _snapshot;
136
+ private _setStatus;
137
+ private _startTurn;
138
+ private _endTurn;
139
+ private _interrupt;
140
+ private _fail;
141
+ /** Past its budget the goal stops, as Codex's does: `budgetLimited` is terminal. */
142
+ private _enforceBudget;
143
+ private _probe;
144
+ /** A goal turn ended: read why, and what the goal is now. */
145
+ private _settle;
146
+ }
147
+ export {};
@@ -0,0 +1,355 @@
1
+ /**
2
+ * A Claude Code `/goal` behind the `GoalSession` surface the kernel's `goal`
3
+ * node drives, so one node runs a goal on either engine.
4
+ *
5
+ * Codex's app-server owns a goal: it has RPCs to set, pause and read it, and
6
+ * notifies every status change. Claude Code has none of that. What it has,
7
+ * measured on CLI 2.1.312 in stream-json mode:
8
+ *
9
+ * - `/goal <condition>` sets the goal and starts working. A Stop hook judges
10
+ * the condition after every turn and feeds the turn back while it does not
11
+ * hold, all inside the one send; a single `result` arrives when the goal is
12
+ * met, and the goal clears itself.
13
+ * - A bare `/goal` answers at once, without a model turn: `Goal active: …` or
14
+ * `No goal set. …`. That is the only way to read the goal.
15
+ * - The goal is part of the transcript. A process that dies and is resumed
16
+ * with `--resume` still has it, but nothing drives it until a message comes.
17
+ * - The `interrupt` control request ends the running turn with an
18
+ * `error_during_execution` result and leaves the goal set.
19
+ * - A turn that fails (an auth error, a usage limit) ends with an `is_error`
20
+ * result, and the CLI clears the goal then too ("Goal cleared after an
21
+ * unrecoverable error"). "No goal set" alone does not mean the goal was met.
22
+ * - The condition is judged by a separate model reading the transcript, not by
23
+ * the agent. When it blocks the agent's stop 9 times running, the CLI ends
24
+ * the turn anyway and says so in an `informational` system event; the goal
25
+ * stays set.
26
+ *
27
+ * So the status here is partly the adapter's own bookkeeping. `active` while a
28
+ * goal turn runs. `complete` only when a turn that started with the goal set
29
+ * ended without an error and the goal is gone: the Stop hook let it end. A
30
+ * goal still set with nothing driving it, a failed turn, and a reopened thread
31
+ * whose goal is gone are all `paused`, which the node resumes within its bound;
32
+ * resuming re-arms the goal (`/goal <objective>` again) when the CLI dropped
33
+ * it, so a goal already met costs one turn to confirm. A failed login is
34
+ * `blocked`: resuming cannot fix it. So is a turn the CLI had to end over the
35
+ * Stop hook: the agent asked to stop again and again, and continuing it only
36
+ * repeats that. The node goes on to its verifier either way, and the contract,
37
+ * not the agent or the hook, decides.
38
+ *
39
+ * Tokens are the session's input, output and cache-read tokens; the CLI reports
40
+ * no goal-level count. A reopened process starts its counters at zero, so the
41
+ * node hands over what the thread had already spent.
42
+ */
43
+ import { EventEmitter } from 'node:events';
44
+ import { SESSION_EVENT } from './constants.js';
45
+ /** Sent to pick a goal back up: the Stop hook keeps it going from there. */
46
+ export const CLAUDE_GOAL_CONTINUE = 'Continue working toward the active goal. Pick up from where the work stands now.';
47
+ const PROBE_TIMEOUT_MS = 60_000;
48
+ /** Map a failed turn's text onto the codex error codes the node treats as transient. */
49
+ export function classifyClaudeError(text, apiStatus) {
50
+ const status = typeof apiStatus === 'number' ? apiStatus : Number.NaN;
51
+ if (status === 401 ||
52
+ status === 403 ||
53
+ /not logged in|\/login|invalid api key|authentication|unauthorized/i.test(text)) {
54
+ return 'unauthorized';
55
+ }
56
+ if (status === 429 || /usage limit|rate limit|limit reached|hit your limit|\b429\b/i.test(text)) {
57
+ return 'usageLimitExceeded';
58
+ }
59
+ if (status === 529 || /overloaded|\b529\b/i.test(text))
60
+ return 'serverOverloaded';
61
+ if ((status >= 500 && status < 600) ||
62
+ /\b5\d\d\b|internal server error|api error|ECONNRESET|ETIMEDOUT|socket hang up|fetch failed|network/i.test(text)) {
63
+ return 'internalServerError';
64
+ }
65
+ return null;
66
+ }
67
+ /** Read a bare `/goal` answer. */
68
+ export function parseGoalProbe(text) {
69
+ const t = text.trim();
70
+ if (/^no goal set/i.test(t))
71
+ return { active: false };
72
+ const m = /^goal active:\s*([\s\S]*?)(?:\s*\((?:not yet evaluated|[^()]*)\))?\s*$/i.exec(t);
73
+ if (m)
74
+ return { active: true, objective: m[1].trim() };
75
+ return undefined;
76
+ }
77
+ export class ClaudeGoalSession extends EventEmitter {
78
+ host;
79
+ open;
80
+ _goal = null;
81
+ _lastError = null;
82
+ _turnActive = false;
83
+ _interrupting = false;
84
+ /** The CLI held the goal when the running (or last) turn started. */
85
+ _armed = false;
86
+ /** The CLI's notice that it ended the running turn over the Stop hook. */
87
+ _hookOverride = null;
88
+ _tokensAtOpen;
89
+ _budgetFrom = 0;
90
+ _turnStartedAt = null;
91
+ _timeUsed;
92
+ _seedTokens;
93
+ _onText = (...args) => this.emit(SESSION_EVENT.TEXT, ...args);
94
+ _onClose = (...args) => {
95
+ this._endTurn();
96
+ // What the dead process spent, so the node hands it to the one it reopens.
97
+ if (this._goal)
98
+ this.emit('goal:updated', this._snapshot());
99
+ this.emit(SESSION_EVENT.CLOSE, ...args);
100
+ };
101
+ /** `_settle` reading why the last turn ended; nothing else may probe meanwhile. */
102
+ _settling = null;
103
+ _onResult = (...args) => {
104
+ const settling = this._settle(args[0]).finally(() => {
105
+ if (this._settling === settling)
106
+ this._settling = null;
107
+ });
108
+ this._settling = settling;
109
+ };
110
+ _onSystem = (...args) => {
111
+ const e = args[0];
112
+ if (!this._turnActive || e?.subtype !== 'informational' || typeof e.content !== 'string')
113
+ return;
114
+ if (/blocked the turn from ending \d+ consecutive times/i.test(e.content))
115
+ this._hookOverride = e.content;
116
+ };
117
+ constructor(host, open = {}) {
118
+ super();
119
+ this.host = host;
120
+ this.open = open;
121
+ this._tokensAtOpen = this._sessionTokens();
122
+ this._seedTokens = open.tokensUsed ?? 0;
123
+ this._timeUsed = open.timeUsedSeconds ?? 0;
124
+ host.on(SESSION_EVENT.TEXT, this._onText);
125
+ host.on(SESSION_EVENT.CLOSE, this._onClose);
126
+ host.on(SESSION_EVENT.RESULT, this._onResult);
127
+ host.on(SESSION_EVENT.SYSTEM, this._onSystem);
128
+ }
129
+ /** Stop listening to the host. The session itself is the manager's to stop. */
130
+ detach() {
131
+ this.host.off(SESSION_EVENT.TEXT, this._onText);
132
+ this.host.off(SESSION_EVENT.CLOSE, this._onClose);
133
+ this.host.off(SESSION_EVENT.RESULT, this._onResult);
134
+ this.host.off(SESSION_EVENT.SYSTEM, this._onSystem);
135
+ }
136
+ /** The Claude session id. Named for the interface, which Codex defined. */
137
+ get codexThreadId() {
138
+ return this.host.sessionId || this.open.threadId;
139
+ }
140
+ get goal() {
141
+ return this._goal ? this._snapshot() : null;
142
+ }
143
+ get lastError() {
144
+ return this._lastError;
145
+ }
146
+ get turnActive() {
147
+ return this._turnActive;
148
+ }
149
+ async setGoal(p) {
150
+ if (p.objective !== undefined) {
151
+ this._goal = {
152
+ objective: p.objective,
153
+ status: 'active',
154
+ tokenBudget: p.tokenBudget ?? null,
155
+ tokensUsed: this._tokensUsed(),
156
+ timeUsedSeconds: this._seconds(),
157
+ };
158
+ this._budgetFrom = this._tokensUsed();
159
+ await this._startTurn(`/goal ${p.objective}`, true);
160
+ }
161
+ else if (p.status === 'paused') {
162
+ if (this._turnActive)
163
+ this._interrupt();
164
+ this._setStatus('paused');
165
+ }
166
+ else if (p.status === 'active') {
167
+ await this._settling;
168
+ if (!this._goal)
169
+ throw new Error('no goal to resume: set an objective first');
170
+ this._setStatus('active');
171
+ if (!this._turnActive) {
172
+ // A failed turn or a restart may have cost the CLI its goal: set it again rather than chat.
173
+ const probe = await this._probe();
174
+ if (probe?.active)
175
+ await this._startTurn(CLAUDE_GOAL_CONTINUE, true);
176
+ else
177
+ await this._startTurn(`/goal ${this._goal.objective}`, true);
178
+ }
179
+ }
180
+ return this._snapshot();
181
+ }
182
+ async getGoal() {
183
+ if (this._settling) {
184
+ // A turn just ended and its own probe decides the status: a second `/goal` would race it.
185
+ await this._settling;
186
+ return this._goal ? this._snapshot() : null;
187
+ }
188
+ if (this._turnActive) {
189
+ this._enforceBudget();
190
+ return this._snapshot();
191
+ }
192
+ const status = this._goal?.status;
193
+ if (status === 'complete' || status === 'budgetLimited' || status === 'blocked')
194
+ return this._snapshot();
195
+ const probe = await this._probe();
196
+ if (probe?.active) {
197
+ // Set, and nothing is working on it: a node that sees `paused` resumes it.
198
+ const keep = this._goal?.status === 'usageLimited' ? 'usageLimited' : 'paused';
199
+ this._goal = this._goal
200
+ ? { ...this._goal, status: keep }
201
+ : {
202
+ objective: this.open.objective || probe.objective,
203
+ status: keep,
204
+ tokenBudget: null,
205
+ tokensUsed: 0,
206
+ timeUsedSeconds: 0,
207
+ };
208
+ this._budgetFrom = this._budgetFrom || this._tokensUsed();
209
+ }
210
+ else if (probe && !probe.active) {
211
+ // Gone, but not seen to be met (that is `_settle`'s call): met, or dropped by a failed turn.
212
+ // Paused, so resuming re-arms it; a goal already met then ends in one turn.
213
+ if (this._goal?.status === 'active') {
214
+ this._goal = { ...this._goal, status: 'paused' };
215
+ }
216
+ else if (!this._goal && this.open.resumed && this.open.objective) {
217
+ const objective = this.open.objective;
218
+ this._goal = { objective, status: 'paused', tokenBudget: null, tokensUsed: 0, timeUsedSeconds: 0 };
219
+ }
220
+ }
221
+ return this._goal ? this._snapshot() : null;
222
+ }
223
+ async clearGoal() {
224
+ if (this._turnActive)
225
+ this._interrupt();
226
+ await this.host.send('/goal clear', { waitForComplete: true, timeout: PROBE_TIMEOUT_MS }).catch(() => undefined);
227
+ this._goal = null;
228
+ }
229
+ async steer(text) {
230
+ if (!this._turnActive)
231
+ return { steered: false };
232
+ // A message written during a turn is folded into it by the CLI.
233
+ await this.host.send(text, { waitForComplete: false });
234
+ return { steered: true };
235
+ }
236
+ async interrupt() {
237
+ if (!this._turnActive)
238
+ return { interrupted: false };
239
+ return { interrupted: this._interrupt() };
240
+ }
241
+ // ─── Internals ─────────────────────────────────────────────────────────
242
+ _sessionTokens() {
243
+ try {
244
+ const s = this.host.getStats();
245
+ return (s.tokensIn || 0) + (s.tokensOut || 0) + (s.cachedTokens || 0);
246
+ }
247
+ catch {
248
+ return 0;
249
+ }
250
+ }
251
+ _tokensUsed() {
252
+ return this._seedTokens + Math.max(0, this._sessionTokens() - this._tokensAtOpen);
253
+ }
254
+ _seconds() {
255
+ const running = this._turnStartedAt === null ? 0 : (Date.now() - this._turnStartedAt) / 1000;
256
+ return Math.round(this._timeUsed + running);
257
+ }
258
+ _snapshot() {
259
+ const g = this._goal;
260
+ return { ...g, tokensUsed: this._tokensUsed(), timeUsedSeconds: this._seconds() };
261
+ }
262
+ _setStatus(status) {
263
+ if (!this._goal || this._goal.status === status)
264
+ return;
265
+ this._goal = { ...this._goal, status };
266
+ this.emit('goal:updated', this._snapshot());
267
+ }
268
+ async _startTurn(text, armed) {
269
+ this._turnActive = true;
270
+ this._interrupting = false;
271
+ this._armed = armed;
272
+ this._hookOverride = null;
273
+ this._turnStartedAt = Date.now();
274
+ try {
275
+ await this.host.send(text, { waitForComplete: false });
276
+ }
277
+ catch (err) {
278
+ this._endTurn();
279
+ this._fail(err.message, null);
280
+ }
281
+ }
282
+ _endTurn() {
283
+ if (this._turnStartedAt !== null)
284
+ this._timeUsed += (Date.now() - this._turnStartedAt) / 1000;
285
+ this._turnStartedAt = null;
286
+ this._turnActive = false;
287
+ }
288
+ _interrupt() {
289
+ this._interrupting = true;
290
+ return this.host.interruptTurn();
291
+ }
292
+ _fail(message, code) {
293
+ this._lastError = { message, code, willRetry: false, at: new Date().toISOString() };
294
+ this.emit('codex:error', this._lastError);
295
+ }
296
+ /** Past its budget the goal stops, as Codex's does: `budgetLimited` is terminal. */
297
+ _enforceBudget() {
298
+ const budget = this._goal?.tokenBudget;
299
+ if (!budget || this._goal?.status !== 'active')
300
+ return;
301
+ if (this._tokensUsed() - this._budgetFrom < budget)
302
+ return;
303
+ if (this._turnActive)
304
+ this._interrupt();
305
+ this._setStatus('budgetLimited');
306
+ }
307
+ async _probe() {
308
+ try {
309
+ const r = (await this.host.send('/goal', { waitForComplete: true, timeout: PROBE_TIMEOUT_MS }));
310
+ return typeof r?.text === 'string' ? parseGoalProbe(r.text) : undefined;
311
+ }
312
+ catch {
313
+ return undefined;
314
+ }
315
+ }
316
+ /** A goal turn ended: read why, and what the goal is now. */
317
+ async _settle(event) {
318
+ if (!this._turnActive || !event)
319
+ return;
320
+ this._endTurn();
321
+ this.emit(SESSION_EVENT.RESULT, event);
322
+ const text = typeof event.result === 'string' ? event.result : '';
323
+ const failed = !!event.is_error || event.stop_reason === 'error' || String(event.subtype ?? '').startsWith('error');
324
+ if (this._interrupting) {
325
+ this._interrupting = false;
326
+ // A stop we asked for: pause and budget already set the status.
327
+ if (this._goal?.status === 'active')
328
+ this._setStatus('paused');
329
+ return;
330
+ }
331
+ if (failed) {
332
+ // The CLI drops the goal with a failed turn; resuming re-arms it.
333
+ this._armed = false;
334
+ const code = classifyClaudeError(text, event.api_error_status);
335
+ this._fail(text || String(event.subtype ?? 'the turn failed'), code);
336
+ this._setStatus(code === 'usageLimitExceeded' ? 'usageLimited' : code === 'unauthorized' ? 'blocked' : 'paused');
337
+ return;
338
+ }
339
+ const armed = this._armed;
340
+ const probe = await this._probe();
341
+ this._enforceBudget();
342
+ if (this._goal?.status !== 'active')
343
+ return;
344
+ // Met: the goal was set when the turn started, the turn ended cleanly, and the CLI cleared it.
345
+ if (armed && probe && !probe.active)
346
+ this._setStatus('complete');
347
+ else if (probe?.active && this._hookOverride) {
348
+ this._fail(this._hookOverride, null);
349
+ this._setStatus('blocked');
350
+ }
351
+ else
352
+ this._setStatus('paused');
353
+ }
354
+ }
355
+ //# sourceMappingURL=claude-goal-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-goal-session.js","sourceRoot":"","sources":["../../src/claude-goal-session.ts"],"names":[],"mappings":"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"}
package/dist/src/index.js CHANGED
@@ -1025,7 +1025,7 @@ const plugin = {
1025
1025
  agents: {
1026
1026
  type: 'array',
1027
1027
  maxItems: 16,
1028
- description: 'Agent specs: { name, engine?, model?, effort?, prompt?, persona?, baseUrl?, permissionMode?, customEngine?, acpAgent? }.',
1028
+ description: "Agent specs: { name, engine?, model?, effort?, prompt?, persona?, baseUrl?, permissionMode?, sandboxMode?, customEngine?, acpAgent? }. permissionMode uses each engine's own permission handling as in session_start; workers that must not write should set sandboxMode to read-only. sandboxMode uses the same values and per-engine behavior as session_start.",
1029
1029
  items: {
1030
1030
  type: 'object',
1031
1031
  properties: {
@@ -1045,6 +1045,16 @@ const plugin = {
1045
1045
  description: 'Per-agent role instructions prepended to the shared task when no non-empty prompt is supplied.',
1046
1046
  },
1047
1047
  baseUrl: { type: 'string' },
1048
+ permissionMode: {
1049
+ type: 'string',
1050
+ enum: ['acceptEdits', 'bypassPermissions', 'default', 'manual', 'dontAsk', 'plan', 'auto'],
1051
+ description: "Per-agent permission mode (same values as session_start). Passed through to that engine's own permission handling; see session_start for per-engine mapping.",
1052
+ },
1053
+ sandboxMode: {
1054
+ type: 'string',
1055
+ enum: ['read-only', 'workspace-write', 'danger-full-access'],
1056
+ description: 'Same values and per-engine behavior as session_start. Use read-only for workers that must not write.',
1057
+ },
1048
1058
  acpAgent: ACP_AGENT_ID_SCHEMA,
1049
1059
  },
1050
1060
  required: ['name'],
@@ -1123,7 +1133,7 @@ const plugin = {
1123
1133
  template: {
1124
1134
  type: 'string',
1125
1135
  enum: ['solve', 'council', 'fanout', 'goal'],
1126
- description: 'Build a built-in workflow instead of supplying `spec`. `solve` = triage → implement → review → verify → repair-until-green. `goal` = a Codex /goal on one codex-app thread (`task` is the objective) → verify → repair on the same thread.',
1136
+ description: 'Build a built-in workflow instead of supplying `spec`. `solve` = triage → implement → review → verify → repair-until-green. `goal` = a /goal on one Codex thread or Claude Code session (`task` is the objective) → verify → repair on the same thread.',
1127
1137
  },
1128
1138
  task: { type: 'string', description: 'Task text, when using `template`.' },
1129
1139
  agents: {
@@ -1175,12 +1185,17 @@ const plugin = {
1175
1185
  type: 'number',
1176
1186
  description: '`solve` / `goal`: repair attempts allowed (default 3 for solve, 1 for goal).',
1177
1187
  },
1178
- model: { type: 'string', description: "`goal` only: Codex model (default: codex's own)." },
1188
+ engine: {
1189
+ type: 'string',
1190
+ enum: ['codex', 'claude'],
1191
+ description: '`goal` only: who runs the goal (default codex).',
1192
+ },
1193
+ model: { type: 'string', description: "`goal` only: model (default: the engine's own)." },
1179
1194
  tokenBudget: { type: 'number', description: '`goal` only: tokens the goal may spend.' },
1180
1195
  launcher: {
1181
1196
  type: 'array',
1182
1197
  items: { type: 'string' },
1183
- description: '`goal` only: argv prefix codex runs under, e.g. a sandbox wrapper. It runs with your authority, like a contract command check.',
1198
+ description: '`goal` only: argv prefix the engine runs under, e.g. a sandbox wrapper. It runs with your authority, like a contract command check.',
1184
1199
  },
1185
1200
  cwd: { type: 'string', description: 'Working directory for the run.' },
1186
1201
  runId: { type: 'string', description: 'Explicit run id (defaults to a generated one).' },
@@ -1273,6 +1288,7 @@ const plugin = {
1273
1288
  task,
1274
1289
  cwd,
1275
1290
  contract: args.contract,
1291
+ engine: args.engine,
1276
1292
  model: args.model,
1277
1293
  tokenBudget: args.tokenBudget,
1278
1294
  launcher: args.launcher,