@aragon-agent/cli 0.6.21 → 0.6.22

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.
@@ -1,33 +1,56 @@
1
1
  /**
2
- * The dispatch supervisor (team-overseer).
2
+ * The dispatch supervisor (team-overseer, upgraded by subagent-overseer-v2).
3
3
  *
4
4
  * ASCII ONLY: `src/team/**` is inside the glyph scanner's scope
5
5
  * (`glyphs.test.ts`), so no literal in this tree may hold a non-ASCII byte.
6
6
  *
7
7
  * A TIME CEILING ON A CHILD IS AN INSPECTION TRIGGER, NOT A DEATH SENTENCE.
8
- * When a child stalls (event silence) or simply runs long (the wall clock),
9
- * the supervisor looks at it through ONE bounded fast-tier call and decides:
8
+ * When a child stalls (event silence) or a cadence tick comes due, the
9
+ * supervisor looks at it through ONE bounded fast-tier call and decides:
10
10
  * keep waiting, steer a nudge in to help it recover, rebuild it with an
11
11
  * amended brief, or abandon it with a recorded reason. Only the supervisor
12
12
  * "decides"; the RUNTIME applies (see `runtime.ts`), because every child
13
13
  * lifecycle change must funnel through the worker loop that awaits it
14
14
  * (I-OV1).
15
15
  *
16
+ * THE SUPERVISOR IS A NO-LOOP, BOUNDED, REMEMBERED CALLEE - NOT AN AGENT
17
+ * (subagent-overseer-v2 D-1). The requirement says "a dedicated supervising
18
+ * subagent on the fast model"; it is satisfied by a per-dispatch, remembered,
19
+ * cadence-woken caller on the fast tier rather than a real `Agent.prompt()`
20
+ * loop, because a supervisor that can itself wedge needs a second supervisor.
21
+ *
22
+ * TWO INSPECTION SHAPES (D-3). Event silence triggers a SINGLE-child look
23
+ * (fast reaction to a suspected stall, unchanged from round 1); the cadence
24
+ * ladder triggers a BATCH look that carries every live child in one digest
25
+ * and returns one JSON array of per-child decisions. The batch call carries
26
+ * its own output budget (`overseerBatchOutputTokens`, R-P0-1): a full
27
+ * ten-child reply does not physically fit in the single-inspection 512
28
+ * tokens, and a truncated reply would parse to nothing - all wait, exactly
29
+ * when help is most needed.
30
+ *
16
31
  * THE TRANSPORT IS THE REVIEWER'S, DELIBERATELY. One `complete` call, no
17
- * tools, thinking off, temperature 0, output capped at
18
- * `FAST_LIMITS.reviewOutputTokens` and wall clock at
19
- * `FAST_LIMITS.reviewTimeoutMs` — a supervision call that could itself hang
20
- * would need a second supervisor, which is the regress this design refuses.
32
+ * tools, thinking off, temperature 0, output capped (512 single /
33
+ * 2048 batch) and wall clock at `FAST_LIMITS.reviewTimeoutMs` — a
34
+ * supervision call that could itself hang would need a second supervisor,
35
+ * which is the regress this design refuses.
21
36
  *
22
37
  * REPAIR, NEVER REJECT (the `normalizeSubagentSpecs` rule). An unparseable
23
38
  * or out-of-budget decision becomes `wait` with the default interval: the
24
39
  * failure mode of a supervisor must be "looked and let it run", never
25
- * "looked and killed it" (I-OV2).
40
+ * "looked and killed it" (I-OV2). In a batch, one bad ENTRY degrades only
41
+ * that entry; a wholly unparseable reply degrades the whole batch to wait
42
+ * with zero action side effects (R-P0-1 / AC-13).
26
43
  */
27
- import type { AssistantMessage, LLMRequest, Message } from '@aragon-agent/core';
44
+ import type { AssistantMessage, LLMRequest, Message, TokenUsage } from '@aragon-agent/core';
28
45
  import type { ModelRole } from '../config/model-profiles.js';
29
46
  import type { CliConfig } from '../config/schema.js';
30
47
  import type { OverseerAction, OverseerDecision, SubagentRun, SubagentSpec } from './types.js';
48
+ /**
49
+ * Bumped whenever either supervisor protocol prompt changes (D-9), so a
50
+ * behaviour report can be tied to a prompt revision with one grep.
51
+ * `TEAM_BLOCK_VERSION` covers only the LEAD's `<team>` block, not these.
52
+ */
53
+ export declare const OVERSEER_PROMPT_VERSION = "v2-2026-10";
31
54
  /** One remembered decision, so the second look knows the first happened. */
32
55
  export interface OverseerMemoryEntry {
33
56
  /** Seconds into the dispatch. */
@@ -57,6 +80,38 @@ export interface ChildDigestInput {
57
80
  * is worse than one missing the fifth message back.
58
81
  */
59
82
  export declare function buildChildDigest(input: ChildDigestInput): string;
83
+ /**
84
+ * The per-child sections of one batch payload (D-3).
85
+ *
86
+ * SORTED BY LABEL so the same roster produces the byte-identical payload -
87
+ * the batch is the one place where ordering is observable to the model and
88
+ * to every test that asserts on it. Each child's digest is clamped to
89
+ * `overseerPerChildDigestBytes` (facts first, history tail last - R-P2-5).
90
+ * The whole-batch ceiling is applied by the joiner in the provider request.
91
+ */
92
+ export declare function buildBatchSections(children: readonly ChildDigestInput[]): Array<{
93
+ label: string;
94
+ goal: string;
95
+ digest: string;
96
+ }>;
97
+ /**
98
+ * The FIRST cadence check, from the D-8 priority: `overseerIntervalMs` when
99
+ * the user named one; otherwise a positive `subagentTimeoutMs` (compat with
100
+ * users who already treated it as a trigger); otherwise the structural
101
+ * default. Read-only derivation - the user's stored config is never
102
+ * rewritten to "resolve" this.
103
+ */
104
+ export declare function resolveOverseerFirstCheckMs(team: {
105
+ overseerIntervalMs: number;
106
+ subagentTimeoutMs: number;
107
+ }): number;
108
+ /**
109
+ * The next ladder step after one that produced no action: grow by
110
+ * `overseerCadenceRatio`, clamped to the structural range. With the shipped
111
+ * 300 s base the checks land at 300 / 780 / 1548 / 2448 / ... seconds - a
112
+ * healthy slow child is looked at logarithmically in its run time (AC-11).
113
+ */
114
+ export declare function nextOverseerLadderStepMs(previousMs: number): number;
60
115
  /** Clamp a model-chosen next check into the structural range. */
61
116
  export declare function clampNextCheckMs(ms: unknown): number | undefined;
62
117
  /**
@@ -66,6 +121,10 @@ export declare function clampNextCheckMs(ms: unknown): number | undefined;
66
121
  * replaced or abandoned, never waited on or nudged, so those normalize to
67
122
  * `abandon` rather than being rejected — a post-mortem answer the protocol
68
123
  * cannot honour must still produce a decision the runtime can apply.
124
+ *
125
+ * The single-inspection char limits (200/1200) are the defaults here; the
126
+ * batch path calls `normalizeWithLimits` directly with the tighter protocol
127
+ * limits (R-P0-1).
69
128
  */
70
129
  export declare function normalizeOverseerDecision(raw: unknown, childAlive: boolean): OverseerDecision;
71
130
  /**
@@ -76,16 +135,47 @@ export declare function normalizeOverseerDecision(raw: unknown, childAlive: bool
76
135
  * `wait` — the caller never sees a throw from parsing.
77
136
  */
78
137
  export declare function parseOverseerDecisionText(text: string, childAlive: boolean): OverseerDecision;
79
- /** The slice the runtime needs: "can you look?" and "decide". */
138
+ /**
139
+ * Parse the model's answer text as a JSON ARRAY of per-child decisions (D-3).
140
+ *
141
+ * Same forgiving span rule as the single path - first `[` to last `]` - and
142
+ * the same failure semantics: a reply that is not an array (prose, a single
143
+ * object, or TRUNCATED output with no closing `]`) is `[]`, which the caller
144
+ * turns into all-wait with zero action side effects (R-P0-1 / AC-13). Never
145
+ * throws.
146
+ */
147
+ export declare function parseOverseerBatchText(text: string): unknown[];
148
+ /**
149
+ * The slice the runtime needs: "can you look?", "decide", "what did looking
150
+ * cost?". The provider is the CALL boundary; `TeamOverseer` owns budgets,
151
+ * memory and normalization, so a stub in a test scripts decisions by
152
+ * returning objects or arrays and nothing else.
153
+ */
80
154
  export interface OverseerProvider {
81
- /** Live predicate, re-read per dispatch AND per inspection. */
155
+ /** Live predicate, re-read per tick: this, not the dispatch-time value, decides assisted vs unassisted (R-P0-2). */
82
156
  active(): boolean;
83
- /** One bounded decision call. Implementations must not throw. */
157
+ /** One bounded SINGLE-child decision call (silence path). Must not throw. */
84
158
  inspect(req: {
85
159
  label: string;
86
160
  goal: string;
87
161
  digest: string;
88
162
  }): Promise<OverseerDecision>;
163
+ /**
164
+ * One bounded BATCH call (cadence path, D-3). Returns the RAW reply - the
165
+ * fast provider answers the assistant TEXT - for `TeamOverseer` to parse
166
+ * and normalize. Must not throw.
167
+ */
168
+ inspectBatch(req: ReadonlyArray<{
169
+ label: string;
170
+ goal: string;
171
+ digest: string;
172
+ }>): Promise<unknown>;
173
+ /**
174
+ * Everything this provider has spent on inspection calls (D-7, honest
175
+ * accounting). Read once by the runtime at dispatch end; there is exactly
176
+ * one accounting of it and no second aggregation path.
177
+ */
178
+ usage(): TokenUsage;
89
179
  }
90
180
  /** Everything the fast-tier-backed provider needs from the session. */
91
181
  export interface FastOverseerDeps {
@@ -102,6 +192,11 @@ export interface FastOverseerDeps {
102
192
  * The fast-tier-backed provider, mirroring `createChildReviewer`'s shape so
103
193
  * the controller wires it the same way: shared transport, live predicates,
104
194
  * fail-soft (any failure resolves to `wait` — I-OV2).
195
+ *
196
+ * USAGE IS ACCUMULATED HERE (D-7), off every `AssistantMessage` the shared
197
+ * transport returns, along the same `usageOf` / `accumulateUsage` path the
198
+ * fast reviewer already proved. A reply without a usage block contributes
199
+ * nothing rather than a fabricated zero-cost total.
105
200
  */
106
201
  export declare function createFastOverseerProvider(deps: FastOverseerDeps): OverseerProvider;
107
202
  /** One inspection request, as the runtime builds it. */
@@ -123,27 +218,70 @@ export declare const OVERSEER_DEFAULT_NEXT_CHECK_MS: 300000;
123
218
  * THE CLASS NEVER TOUCHES A CHILD (I-OV1). It looks and decides; `runtime.ts`
124
219
  * steers, flags, aborts and rebuilds, because only the worker loop can apply
125
220
  * a lifecycle change without orphaning the replacement.
221
+ *
222
+ * LOOKS AND ACTIONS ARE SEPARATE LEDGERS (D-5). A LOOK is cost: every
223
+ * inspection of a child spends one, including a call that failed softly -
224
+ * which is what closes G-6 (a flaky transport used to burn the budget the
225
+ * same as a decision, and the supervisor went quiet exactly when the team
226
+ * was hardest to see). An ACTION is a mutation (nudge / replace / abandon)
227
+ * and is counted only when the runtime APPLIES it, through the `note*`
228
+ * methods below. A label skipped because an inspection is already in flight
229
+ * spends NOTHING (R-P1-4).
126
230
  */
127
231
  export declare class TeamOverseer {
128
232
  private readonly provider;
129
233
  private readonly options;
130
234
  private readonly memory;
131
- private readonly inspections;
235
+ private readonly looks;
236
+ private readonly nudges;
132
237
  private readonly replacements;
238
+ private readonly abandons;
133
239
  private readonly inFlight;
240
+ private looksTotal;
241
+ private callCount;
134
242
  constructor(provider: OverseerProvider, options: TeamOverseerOptions);
135
243
  /** Never throws: a provider bug must not take the dispatch down. */
136
244
  isActive(): boolean;
137
- inspectionsExhausted(label: string): boolean;
245
+ /** Whether ANY inspection of `label` is in flight (single or batch). */
246
+ isInFlight(label: string): boolean;
247
+ /** Per-child look budget spent (D-5). */
248
+ looksExhausted(label: string): boolean;
249
+ /** The fool-proof dispatch-wide total (R-P1-6). */
250
+ dispatchLooksExhausted(): boolean;
251
+ nudgesLeft(label: string): boolean;
138
252
  replacementsLeft(label: string): boolean;
253
+ abandonsLeft(label: string): boolean;
254
+ /** Called by the runtime when it APPLIES a nudge, not when it merely reads one. */
255
+ noteNudge(label: string): void;
139
256
  /** Called by the runtime when it APPLIES a replace, not when it merely reads one. */
140
257
  noteReplacement(label: string): void;
258
+ /** Called by the runtime when it APPLIES an abandon, not when it merely reads one. */
259
+ noteAbandon(label: string): void;
260
+ /** The provider's own accumulated inspection spend (D-7), zero when unreadable. */
261
+ usage(): TokenUsage;
262
+ /** Provider invocations, including ones that failed softly (D-7). */
263
+ calls(): number;
141
264
  /**
142
- * ONE inspection. `null` means QUIET — not active, no budget left, or one
143
- * already in flight for this child — and the caller then does nothing,
265
+ * ONE single-child inspection (the silence-triggered path, round-1
266
+ * behaviour preserved). `null` means QUIET — not active, no budget left, or
267
+ * one already in flight for this child — and the caller then does nothing,
144
268
  * which is exactly what quiet should do.
145
269
  */
146
270
  inspect(req: OverseerInspectRequest): Promise<OverseerDecision | null>;
271
+ /**
272
+ * ONE batch inspection over every requested child (the cadence path, D-3):
273
+ * a single fast-tier call, a JSON array back, one decision per child.
274
+ *
275
+ * SKIPS FIRST, CALLS SECOND (R-P1-4): a label whose single inspection is
276
+ * still in flight, or whose look budget is spent, simply gets NO entry -
277
+ * no decision, no look charged, ladder untouched by the caller. A label
278
+ * that IS carried but whose reply entry is missing or garbage gets `wait`
279
+ * (repair, never reject). A wholly unparseable or truncated reply is ALL
280
+ * wait with zero action side effects (R-P0-1 / AC-13).
281
+ */
282
+ inspectBatch(reqs: readonly OverseerInspectRequest[]): Promise<Map<string, OverseerDecision>>;
283
+ private spendLook;
284
+ private remember;
147
285
  }
148
286
  /**
149
287
  * Prepend the supervisor's note to a spec's prompt, bounding the TOTAL to