@yagni-app/code-staging 1.2.2-staging.1563.1 → 1.2.3-staging.1575.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/dist/extension/askAdvisorTool.d.ts +6 -1
- package/dist/extension/askAdvisorTool.js +6 -1
- package/dist/extension/pipeline/budget.d.ts +32 -0
- package/dist/extension/pipeline/budget.js +29 -0
- package/dist/extension/pipeline/orchestrator.d.ts +16 -1
- package/dist/extension/pipeline/orchestrator.js +26 -4
- package/dist/extension/pipeline/resilience.d.ts +18 -0
- package/dist/extension/pipeline/resilience.js +6 -2
- package/dist/extension/pipeline/types.d.ts +9 -6
- package/dist/extension/pipeline/types.js +8 -5
- package/dist/extension/subagents.d.ts +3 -2
- package/dist/extension/subagents.js +3 -2
- package/package.json +2 -2
|
@@ -32,13 +32,18 @@ import { type AdvisorLimits, type AdvisorStateHandle } from "./advisor.js";
|
|
|
32
32
|
import type { ChildUsageHandle } from "./childUsage.js";
|
|
33
33
|
import type { WorkingLineHandle } from "./workingLine.js";
|
|
34
34
|
import { runStage as defaultRunStage } from "./pipeline/runner.js";
|
|
35
|
-
import { type PipelineStage } from "./pipeline/types.js";
|
|
35
|
+
import { type PipelineStage, type ResiliencePolicy } from "./pipeline/types.js";
|
|
36
36
|
import { type RenderTheme, type SubagentTaskProgress } from "./subagentRender.js";
|
|
37
37
|
/**
|
|
38
38
|
* Read-only recon plus grounding. Mirrors the `plan` stage's allowlist for the
|
|
39
39
|
* reason documented there: enough tools to navigate instead of flailing on a
|
|
40
40
|
* single `read`. No `bash`.
|
|
41
41
|
*/
|
|
42
|
+
/**
|
|
43
|
+
* A consult is one read-only question, so it keeps the 20-minute wall clock
|
|
44
|
+
* the /go stages had before their default grew to an hour.
|
|
45
|
+
*/
|
|
46
|
+
export declare const ADVISOR_RESILIENCE_POLICY: ResiliencePolicy;
|
|
42
47
|
export declare const ADVISOR_TOOLS: string[];
|
|
43
48
|
/** The consult's tool list under `grounding: false` — grounding read
|
|
44
49
|
* stripped via the canonical filter (grounding.ts). */
|
|
@@ -40,6 +40,11 @@ import { applyChildEvent, finalizeTask, formatWorkingMessage, newTaskProgress, p
|
|
|
40
40
|
* reason documented there: enough tools to navigate instead of flailing on a
|
|
41
41
|
* single `read`. No `bash`.
|
|
42
42
|
*/
|
|
43
|
+
/**
|
|
44
|
+
* A consult is one read-only question, so it keeps the 20-minute wall clock
|
|
45
|
+
* the /go stages had before their default grew to an hour.
|
|
46
|
+
*/
|
|
47
|
+
export const ADVISOR_RESILIENCE_POLICY = { ...DEFAULT_RESILIENCE_POLICY, wallTimeoutMs: 20 * 60_000 };
|
|
43
48
|
export const ADVISOR_TOOLS = ["read", "grep", "find", "ls", "ask_yagni"];
|
|
44
49
|
/** The consult's tool list under `grounding: false` — grounding read
|
|
45
50
|
* stripped via the canonical filter (grounding.ts). */
|
|
@@ -144,7 +149,7 @@ export function makeAskAdvisorTool(opts) {
|
|
|
144
149
|
// driver's tool call until the user presses Esc. The synthetic stage id is
|
|
145
150
|
// "plan" (read-only tools, no bash), so the wrapper's write-gate never
|
|
146
151
|
// blocks a retry — re-running a consult cannot double-apply anything.
|
|
147
|
-
const runStage = opts.runStage ?? withResilience(defaultRunStage,
|
|
152
|
+
const runStage = opts.runStage ?? withResilience(defaultRunStage, ADVISOR_RESILIENCE_POLICY);
|
|
148
153
|
return {
|
|
149
154
|
name: "ask_advisor",
|
|
150
155
|
label: "Ask the advisor",
|
|
@@ -78,4 +78,36 @@ export declare const DEFAULT_STAGE_ESTIMATE_MS: Record<TimedStageKind, number>;
|
|
|
78
78
|
* so the only safe place to stop is before it begins.
|
|
79
79
|
*/
|
|
80
80
|
export declare function stageWontFit(budget: RunBudget, kind: TimedStageKind, expectedMs: number, nowMs?: number): string | null;
|
|
81
|
+
/**
|
|
82
|
+
* The shortest wall clock any /go stage gets: the old fixed limit. A run close
|
|
83
|
+
* to its deadline keeps this much rather than a stage being cut off sooner than
|
|
84
|
+
* it ever was.
|
|
85
|
+
*/
|
|
86
|
+
export declare const STAGE_WALL_FLOOR_MS: number;
|
|
87
|
+
/** Time the verify gate is allowed after the last write, on top of the stage estimates. */
|
|
88
|
+
export declare const VERIFY_ALLOWANCE_MS: number;
|
|
89
|
+
/**
|
|
90
|
+
* What must still run after a stage stops: a review round, one fix, and the
|
|
91
|
+
* verify gate. Held back from the stage's wall clock so a long stage still
|
|
92
|
+
* leaves the run time to review what it wrote.
|
|
93
|
+
*/
|
|
94
|
+
export declare const STAGE_WALL_RESERVE_MS: number;
|
|
95
|
+
/**
|
|
96
|
+
* Where a stage's wall clock came from: the build's remaining time, the
|
|
97
|
+
* 20-minute floor because the deadline was close, or the no-deadline default.
|
|
98
|
+
*/
|
|
99
|
+
export type StageWallSource = "deadline" | "floor" | "default";
|
|
100
|
+
/**
|
|
101
|
+
* The wall clock for a stage spawning at `nowMs`. With a deadline (sandbox and
|
|
102
|
+
* mission runs) a working stage gets the build's remaining time less
|
|
103
|
+
* {@link STAGE_WALL_RESERVE_MS}, never under {@link STAGE_WALL_FLOOR_MS}: the
|
|
104
|
+
* idle timer is the check for a stuck model, and stopping a live stage at a
|
|
105
|
+
* fixed limit throws away work the run had time for. Without a deadline
|
|
106
|
+
* (interactive /go, where a person can abort) `fallbackMs` applies. The
|
|
107
|
+
* source rides the stage's attempt record.
|
|
108
|
+
*/
|
|
109
|
+
export declare function stageWall(budget: RunBudget, fallbackMs: number, nowMs?: number): {
|
|
110
|
+
ms: number;
|
|
111
|
+
source: StageWallSource;
|
|
112
|
+
};
|
|
81
113
|
//# sourceMappingURL=budget.d.ts.map
|
|
@@ -107,4 +107,33 @@ export function stageWontFit(budget, kind, expectedMs, nowMs = Date.now()) {
|
|
|
107
107
|
return null;
|
|
108
108
|
return `not enough time left for a ${kind} stage (${Math.max(0, Math.round(leftMs / 1000))}s left, expected ${Math.round(expectedMs / 1000)}s)`;
|
|
109
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* The shortest wall clock any /go stage gets: the old fixed limit. A run close
|
|
112
|
+
* to its deadline keeps this much rather than a stage being cut off sooner than
|
|
113
|
+
* it ever was.
|
|
114
|
+
*/
|
|
115
|
+
export const STAGE_WALL_FLOOR_MS = 20 * 60_000;
|
|
116
|
+
/** Time the verify gate is allowed after the last write, on top of the stage estimates. */
|
|
117
|
+
export const VERIFY_ALLOWANCE_MS = 5 * 60_000;
|
|
118
|
+
/**
|
|
119
|
+
* What must still run after a stage stops: a review round, one fix, and the
|
|
120
|
+
* verify gate. Held back from the stage's wall clock so a long stage still
|
|
121
|
+
* leaves the run time to review what it wrote.
|
|
122
|
+
*/
|
|
123
|
+
export const STAGE_WALL_RESERVE_MS = DEFAULT_STAGE_ESTIMATE_MS.review + DEFAULT_STAGE_ESTIMATE_MS.fix + VERIFY_ALLOWANCE_MS;
|
|
124
|
+
/**
|
|
125
|
+
* The wall clock for a stage spawning at `nowMs`. With a deadline (sandbox and
|
|
126
|
+
* mission runs) a working stage gets the build's remaining time less
|
|
127
|
+
* {@link STAGE_WALL_RESERVE_MS}, never under {@link STAGE_WALL_FLOOR_MS}: the
|
|
128
|
+
* idle timer is the check for a stuck model, and stopping a live stage at a
|
|
129
|
+
* fixed limit throws away work the run had time for. Without a deadline
|
|
130
|
+
* (interactive /go, where a person can abort) `fallbackMs` applies. The
|
|
131
|
+
* source rides the stage's attempt record.
|
|
132
|
+
*/
|
|
133
|
+
export function stageWall(budget, fallbackMs, nowMs = Date.now()) {
|
|
134
|
+
if (budget.deadlineMs === undefined)
|
|
135
|
+
return { ms: fallbackMs, source: "default" };
|
|
136
|
+
const leftMs = budget.deadlineMs - nowMs - STAGE_WALL_RESERVE_MS;
|
|
137
|
+
return leftMs > STAGE_WALL_FLOOR_MS ? { ms: leftMs, source: "deadline" } : { ms: STAGE_WALL_FLOOR_MS, source: "floor" };
|
|
138
|
+
}
|
|
110
139
|
//# sourceMappingURL=budget.js.map
|
|
@@ -26,10 +26,11 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import { type RunBudget } from "./budget.js";
|
|
28
28
|
import { type MissionInputs } from "./mission.js";
|
|
29
|
+
import { type ResilienceAttemptRecord, type RunStageFn } from "./resilience.js";
|
|
29
30
|
import { runStage as defaultRunStage } from "./runner.js";
|
|
30
31
|
import { type VerifyOutcome, type WorkstreamCheckResult, type WorkstreamCheckTarget } from "./verify.js";
|
|
31
32
|
import { snapshotWorkspace as defaultSnapshotWorkspace } from "./workspace.js";
|
|
32
|
-
import { type CheckpointStore, type FanoutBudgetVerdict, type FanoutMode, type PipelineStage, type JsonEvent, type PipelineProgress, type PipelineResult, type ResumePlan, type StageId, type StageResult, type StageTag } from "./types.js";
|
|
33
|
+
import { type CheckpointStore, type FanoutBudgetVerdict, type FanoutMode, type PipelineStage, type JsonEvent, type PipelineProgress, type PipelineResult, type ResiliencePolicy, type ResumePlan, type StageId, type StageResult, type StageTag } from "./types.js";
|
|
33
34
|
export interface RunPipelineDeps {
|
|
34
35
|
cwd: string;
|
|
35
36
|
signal?: AbortSignal;
|
|
@@ -174,5 +175,19 @@ export declare class PipelineStageError extends Error {
|
|
|
174
175
|
readonly partial: StageResult[];
|
|
175
176
|
constructor(stageId: string, message: string, partial: StageResult[]);
|
|
176
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* The resilience policy for a run's stages. With a deadline, a stage that
|
|
180
|
+
* spent its wall clock spent the build's time: a retry would only get the
|
|
181
|
+
* floor and run past the deadline, so it fails instead of retrying.
|
|
182
|
+
*/
|
|
183
|
+
export declare function stageRunnerPolicy(budget: RunBudget): ResiliencePolicy;
|
|
184
|
+
/**
|
|
185
|
+
* The pipeline's default stage runner: `base` under the R1 resilience wrapper
|
|
186
|
+
* with {@link stageRunnerPolicy}, each stage's wall clock taken from the run's
|
|
187
|
+
* deadline when it spawns (budget.ts#stageWall). A run with no deadline keeps
|
|
188
|
+
* the policy's fixed wall clock. Exported so a test can pin the wall a stage
|
|
189
|
+
* actually gets.
|
|
190
|
+
*/
|
|
191
|
+
export declare function resilientStageRunner(base: RunStageFn, budget: RunBudget, clock: () => number, telemetry: (rec: ResilienceAttemptRecord) => void): RunStageFn;
|
|
177
192
|
export declare function runPipeline(ticket: string, deps: RunPipelineDeps): Promise<PipelineResult>;
|
|
178
193
|
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* (an aborted/crashed child has empty output, which otherwise parses to zero
|
|
25
25
|
* findings — i.e. a false "reviewed and clean").
|
|
26
26
|
*/
|
|
27
|
-
import { addRunUsage, aggregateRunUsage, DEFAULT_RUN_BUDGET, DEFAULT_STAGE_ESTIMATE_MS, EMPTY_RUN_USAGE, exceedsBudget, stageWontFit, } from "./budget.js";
|
|
27
|
+
import { addRunUsage, aggregateRunUsage, DEFAULT_RUN_BUDGET, DEFAULT_STAGE_ESTIMATE_MS, EMPTY_RUN_USAGE, exceedsBudget, stageWall, stageWontFit, } from "./budget.js";
|
|
28
28
|
import { attributeFindings, checkerFindings, composeFixNote, composeResidue, composeSynthesizerInput, mergeFindings, parseOpenFindings, renderFindings, stripOpenFindings, } from "./checker.js";
|
|
29
29
|
import { auditClaims, parsePartition } from "./fanout.js";
|
|
30
30
|
import { extractFindingsBlock, hasBlockingFindings, parseFindings, shouldStop, unionFindings } from "./findings.js";
|
|
@@ -188,6 +188,27 @@ async function mapWithConcurrencyLimit(items, concurrency, fn) {
|
|
|
188
188
|
await Promise.all(workers);
|
|
189
189
|
return results;
|
|
190
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* The resilience policy for a run's stages. With a deadline, a stage that
|
|
193
|
+
* spent its wall clock spent the build's time: a retry would only get the
|
|
194
|
+
* floor and run past the deadline, so it fails instead of retrying.
|
|
195
|
+
*/
|
|
196
|
+
export function stageRunnerPolicy(budget) {
|
|
197
|
+
return budget.deadlineMs === undefined ? DEFAULT_RESILIENCE_POLICY : { ...DEFAULT_RESILIENCE_POLICY, retryWallTimeout: false };
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* The pipeline's default stage runner: `base` under the R1 resilience wrapper
|
|
201
|
+
* with {@link stageRunnerPolicy}, each stage's wall clock taken from the run's
|
|
202
|
+
* deadline when it spawns (budget.ts#stageWall). A run with no deadline keeps
|
|
203
|
+
* the policy's fixed wall clock. Exported so a test can pin the wall a stage
|
|
204
|
+
* actually gets.
|
|
205
|
+
*/
|
|
206
|
+
export function resilientStageRunner(base, budget, clock, telemetry) {
|
|
207
|
+
return withResilience(base, stageRunnerPolicy(budget), {
|
|
208
|
+
telemetry,
|
|
209
|
+
wallFor: () => stageWall(budget, DEFAULT_RESILIENCE_POLICY.wallTimeoutMs, clock()),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
191
212
|
export async function runPipeline(ticket, deps) {
|
|
192
213
|
const log = (event, data) => deps.logger?.(event, data);
|
|
193
214
|
// R1: wrap the real child runner with in-loop resilience (idle/wall timeout +
|
|
@@ -195,10 +216,11 @@ export async function runPipeline(ticket, deps) {
|
|
|
195
216
|
// across its up-to-8 spawns. A caller that injects its own `runStage` (the unit
|
|
196
217
|
// tests, a custom lane) bypasses the wrapper untouched. Per-attempt telemetry
|
|
197
218
|
// rides the existing logger seam, so resume + the checkpoint journal are unaffected.
|
|
219
|
+
// With a deadline (sandbox / mission runs) each stage's wall clock is the
|
|
220
|
+
// time left less a reserve for review, a fix and verify, so a live stage is
|
|
221
|
+
// not killed at a fixed limit the run had room to exceed.
|
|
198
222
|
const runStageFn = deps.runStage ??
|
|
199
|
-
|
|
200
|
-
telemetry: (rec) => log("resilience_attempt", rec),
|
|
201
|
-
});
|
|
223
|
+
resilientStageRunner(defaultRunStage, deps.budget ?? DEFAULT_RUN_BUDGET, deps.now ?? Date.now, (rec) => log("resilience_attempt", rec));
|
|
202
224
|
const snapshotFn = deps.snapshotWorkspace ?? defaultSnapshotWorkspace;
|
|
203
225
|
const runVerifyFn = deps.runVerify ?? makeRunVerify();
|
|
204
226
|
const runWorkstreamCheckFn = deps.runWorkstreamCheck ?? makeWorkstreamCheck();
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
* Pure-ish: all impurity (timers, sleep, clock, randomness) sits behind injectable
|
|
28
28
|
* seams so the wrapper is unit-tested without real waits.
|
|
29
29
|
*/
|
|
30
|
+
import type { StageWallSource } from "./budget.js";
|
|
30
31
|
import type { RunStageDeps } from "./runner.js";
|
|
31
32
|
import { type PipelineStage, type ResiliencePolicy, type ReviewLens, type StageResult } from "./types.js";
|
|
32
33
|
export type { ResiliencePolicy } from "./types.js";
|
|
@@ -54,6 +55,13 @@ export interface ResilienceAttemptRecord {
|
|
|
54
55
|
/** 1-based attempt number. */
|
|
55
56
|
attempt: number;
|
|
56
57
|
outcome: "ok" | "transient" | "fatal" | "timeout" | "aborted";
|
|
58
|
+
/** The wall clock this attempt was given (ms). */
|
|
59
|
+
wallTimeoutMs?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Where that wall clock came from, when the caller said: the build's time
|
|
62
|
+
* left, the floor because the deadline was close, or the no-deadline default.
|
|
63
|
+
*/
|
|
64
|
+
wallSource?: StageWallSource;
|
|
57
65
|
/** Which timer fired, when the attempt timed out. */
|
|
58
66
|
timeoutKind?: "idle" | "wall";
|
|
59
67
|
/** On a timeout: ms the attempt spent with a tool running (the rest went to the model). */
|
|
@@ -76,6 +84,16 @@ export interface ResilienceSeams {
|
|
|
76
84
|
}
|
|
77
85
|
export interface WithResilienceOpts {
|
|
78
86
|
telemetry?: (rec: ResilienceAttemptRecord) => void;
|
|
87
|
+
/**
|
|
88
|
+
* The wall clock for one attempt, asked when the attempt spawns so a later
|
|
89
|
+
* stage (or a retry) gets the time actually left. Absent, every attempt gets
|
|
90
|
+
* `policy.wallTimeoutMs`. The idle window always comes from the policy.
|
|
91
|
+
* `source` rides the attempt record as `wallSource`.
|
|
92
|
+
*/
|
|
93
|
+
wallFor?: (stage: PipelineStage) => {
|
|
94
|
+
ms: number;
|
|
95
|
+
source?: StageWallSource;
|
|
96
|
+
};
|
|
79
97
|
seams?: ResilienceSeams;
|
|
80
98
|
}
|
|
81
99
|
/**
|
|
@@ -163,7 +163,9 @@ export function withResilience(base, policy, opts = {}) {
|
|
|
163
163
|
}
|
|
164
164
|
fireTimeout("idle");
|
|
165
165
|
};
|
|
166
|
-
const
|
|
166
|
+
const wall = opts.wallFor?.(stage);
|
|
167
|
+
const wallTimeoutMs = wall?.ms ?? policy.wallTimeoutMs;
|
|
168
|
+
const wallTimer = setTimeout(() => fireTimeout("wall"), wallTimeoutMs);
|
|
167
169
|
wallTimer.unref?.();
|
|
168
170
|
armIdle();
|
|
169
171
|
const originalOnEvent = deps.onEvent;
|
|
@@ -207,6 +209,8 @@ export function withResilience(base, policy, opts = {}) {
|
|
|
207
209
|
...(deps.taskIndex !== undefined ? { taskIndex: deps.taskIndex } : {}),
|
|
208
210
|
attempt,
|
|
209
211
|
outcome,
|
|
212
|
+
wallTimeoutMs,
|
|
213
|
+
...(wall?.source ? { wallSource: wall.source } : {}),
|
|
210
214
|
...(timedOut && timeoutKind ? { timeoutKind } : {}),
|
|
211
215
|
...(timedOut ? { toolMs, modelBound } : {}),
|
|
212
216
|
exitCode: last.exitCode,
|
|
@@ -229,7 +233,7 @@ export function withResilience(base, policy, opts = {}) {
|
|
|
229
233
|
const transient = classifyTransient(last, timedOut);
|
|
230
234
|
// A wall-clock exhaustion is a "task too big" signal, not a stall: a
|
|
231
235
|
// lane that opts out (subagents) fails honestly instead of re-burning
|
|
232
|
-
// the same
|
|
236
|
+
// the same wall clock per attempt. Idle stalls stay retryable.
|
|
233
237
|
const wallNotRetryable = timedOut && timeoutKind === "wall" && policy.retryWallTimeout === false;
|
|
234
238
|
// No double-apply: a write stage that already started working is never re-run.
|
|
235
239
|
const blockedByWriteGate = isWriteStage && sawAnyEvent;
|
|
@@ -527,18 +527,21 @@ export interface ResiliencePolicy {
|
|
|
527
527
|
/**
|
|
528
528
|
* Whether a WALL-clock exhaustion is retryable. Default true (the /go
|
|
529
529
|
* doctrine: a wedged stage is worth another attempt). A lane whose children
|
|
530
|
-
* run read-only, fast work (subagents) sets false: a
|
|
531
|
-
* the task is too big, and re-running it just multiplies the spend before
|
|
530
|
+
* run read-only, fast work (subagents) sets false: a full wall-clock burn
|
|
531
|
+
* means the task is too big, and re-running it just multiplies the spend before
|
|
532
532
|
* the same honest fail. Idle-stall timeouts stay retryable either way.
|
|
533
533
|
*/
|
|
534
534
|
retryWallTimeout?: boolean;
|
|
535
535
|
}
|
|
536
536
|
/**
|
|
537
537
|
* Default resilience policy. Generous timeouts so a legitimately long but live
|
|
538
|
-
* stage is never killed
|
|
539
|
-
* and the wall window bounds a
|
|
540
|
-
*
|
|
541
|
-
*
|
|
538
|
+
* stage is never killed: the idle window (well under the 5-min run heartbeat) is
|
|
539
|
+
* the check for a stuck model, and the wall window only bounds a runaway that
|
|
540
|
+
* keeps emitting events. The wall is 60 minutes for an interactive /go, where a
|
|
541
|
+
* person can abort; a run with a deadline replaces it per stage with the time
|
|
542
|
+
* left (budget.ts#stageWall). Three attempts with short, jittered
|
|
543
|
+
* backoff so a single transient blip across the up-to-8 child spawns no longer
|
|
544
|
+
* terminates the whole run.
|
|
542
545
|
*/
|
|
543
546
|
export declare const DEFAULT_RESILIENCE_POLICY: ResiliencePolicy;
|
|
544
547
|
/**
|
|
@@ -17,14 +17,17 @@ export const MAX_REVIEW_ROUNDS = 3;
|
|
|
17
17
|
export const MAX_FIX_TURNS = 3;
|
|
18
18
|
/**
|
|
19
19
|
* Default resilience policy. Generous timeouts so a legitimately long but live
|
|
20
|
-
* stage is never killed
|
|
21
|
-
* and the wall window bounds a
|
|
22
|
-
*
|
|
23
|
-
*
|
|
20
|
+
* stage is never killed: the idle window (well under the 5-min run heartbeat) is
|
|
21
|
+
* the check for a stuck model, and the wall window only bounds a runaway that
|
|
22
|
+
* keeps emitting events. The wall is 60 minutes for an interactive /go, where a
|
|
23
|
+
* person can abort; a run with a deadline replaces it per stage with the time
|
|
24
|
+
* left (budget.ts#stageWall). Three attempts with short, jittered
|
|
25
|
+
* backoff so a single transient blip across the up-to-8 child spawns no longer
|
|
26
|
+
* terminates the whole run.
|
|
24
27
|
*/
|
|
25
28
|
export const DEFAULT_RESILIENCE_POLICY = {
|
|
26
29
|
idleTimeoutMs: 4 * 60_000,
|
|
27
|
-
wallTimeoutMs:
|
|
30
|
+
wallTimeoutMs: 60 * 60_000,
|
|
28
31
|
maxAttempts: 3,
|
|
29
32
|
backoffBaseMs: 1_000,
|
|
30
33
|
backoffMaxMs: 30_000,
|
|
@@ -134,8 +134,9 @@ export interface MakeSubagentToolDeps {
|
|
|
134
134
|
/**
|
|
135
135
|
* The subagent lane's wall-clock ceiling: two hours per child.
|
|
136
136
|
*
|
|
137
|
-
* The /go stage default (20 minutes
|
|
138
|
-
*
|
|
137
|
+
* The /go stage default (20 minutes when this was set, an hour since) is
|
|
138
|
+
* sized for one pipeline step; a chat subagent is routinely handed a whole
|
|
139
|
+
* review, and at 20 minutes the runner
|
|
139
140
|
* killed three parallel reviewers mid-report and threw their findings away
|
|
140
141
|
* as "PARTIAL output". The wall clock is not the stall guard — the idle timer
|
|
141
142
|
* (4 minutes, deferred while a tool is in flight) is what catches a hung
|
|
@@ -465,8 +465,9 @@ const parameters = Type.Object({
|
|
|
465
465
|
/**
|
|
466
466
|
* The subagent lane's wall-clock ceiling: two hours per child.
|
|
467
467
|
*
|
|
468
|
-
* The /go stage default (20 minutes
|
|
469
|
-
*
|
|
468
|
+
* The /go stage default (20 minutes when this was set, an hour since) is
|
|
469
|
+
* sized for one pipeline step; a chat subagent is routinely handed a whole
|
|
470
|
+
* review, and at 20 minutes the runner
|
|
470
471
|
* killed three parallel reviewers mid-report and threw their findings away
|
|
471
472
|
* as "PARTIAL output". The wall clock is not the stall guard — the idle timer
|
|
472
473
|
* (4 minutes, deferred while a tool is in flight) is what catches a hung
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yagni-app/code-staging",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3-staging.1575.1",
|
|
4
4
|
"description": "YAGNI Code: a terminal coding agent that already knows your company. One YAGNI login routes the model and grounds the agent in your team's context.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"author": "YAGNI, Inc. <jack@yagni.app> (https://yagni.app)",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"turndown": "^7.2.4",
|
|
59
59
|
"typebox": "^1.3.15"
|
|
60
60
|
},
|
|
61
|
-
"yagniSourceSha": "
|
|
61
|
+
"yagniSourceSha": "ce56b0f74cd9190953e1fc22901d340ff765793a"
|
|
62
62
|
}
|