@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.
Files changed (41) hide show
  1. package/README.md +6 -4
  2. package/dist/bin/cli.js +13 -6
  3. package/dist/bin/cli.js.map +1 -1
  4. package/dist/src/autoloop/dispatcher.js +50 -9
  5. package/dist/src/autoloop/dispatcher.js.map +1 -1
  6. package/dist/src/claude-goal-session.d.ts +147 -0
  7. package/dist/src/claude-goal-session.js +355 -0
  8. package/dist/src/claude-goal-session.js.map +1 -0
  9. package/dist/src/council.js +2 -1
  10. package/dist/src/council.js.map +1 -1
  11. package/dist/src/index.js +20 -4
  12. package/dist/src/index.js.map +1 -1
  13. package/dist/src/kernel/agent-step.d.ts +6 -0
  14. package/dist/src/kernel/agent-step.js.map +1 -1
  15. package/dist/src/kernel/nodes/goal.d.ts +11 -4
  16. package/dist/src/kernel/nodes/goal.js +41 -15
  17. package/dist/src/kernel/nodes/goal.js.map +1 -1
  18. package/dist/src/kernel/templates/index.d.ts +10 -8
  19. package/dist/src/kernel/templates/index.js +6 -5
  20. package/dist/src/kernel/templates/index.js.map +1 -1
  21. package/dist/src/kernel/types.d.ts +7 -3
  22. package/dist/src/kernel/types.js.map +1 -1
  23. package/dist/src/models.js +8 -0
  24. package/dist/src/models.js.map +1 -1
  25. package/dist/src/persistent-agy-session.js +4 -0
  26. package/dist/src/persistent-agy-session.js.map +1 -1
  27. package/dist/src/persistent-session.d.ts +9 -0
  28. package/dist/src/persistent-session.js +23 -0
  29. package/dist/src/persistent-session.js.map +1 -1
  30. package/dist/src/session-manager.d.ts +11 -0
  31. package/dist/src/session-manager.js +39 -4
  32. package/dist/src/session-manager.js.map +1 -1
  33. package/package.json +1 -1
  34. package/skills/references/autoloop.md +7 -3
  35. package/skills/references/claude-cli-tracking.md +3 -1
  36. package/skills/references/cli.md +22 -20
  37. package/skills/references/council.md +11 -0
  38. package/skills/references/multi-engine.md +6 -5
  39. package/skills/references/tools.md +20 -12
  40. package/skills/references/verification.md +0 -2
  41. package/skills/references/workflow.md +60 -16
@@ -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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"}
@@ -420,7 +420,8 @@ export class Council extends EventEmitter {
420
420
  // ─── Single Agent Execution ───────────────────────────────────────────
421
421
  async runSingleAgent(agent, prompt, systemPrompt, workDir, round, sessionId) {
422
422
  this.emitEvent({ type: 'agent-start', sessionId, round, agent: agent.name });
423
- const sessionName = `council-${sessionId.slice(0, 8)}-${agent.name}-r${round}`;
423
+ // Full run id — truncating to 8 chars made every manager id share `council-`.
424
+ const sessionName = `${sessionId}-${agent.name}-r${round}`;
424
425
  this._activeSessions.add(sessionName);
425
426
  let content = '';
426
427
  try {