@ordewell/core 0.11.3 → 0.12.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/AUTHORS.md +3 -1
- package/dist/{ModeResolver-DyXeZ9ib.d.ts → ModeResolver-B64aUZXJ.d.ts} +1 -1
- package/dist/{ModeResolver-BDAgouuE.d.mts → ModeResolver-CA2fUU9h.d.mts} +1 -1
- package/dist/{Task-BL4Idm9r.d.mts → Task-CxGgN6I0.d.mts} +801 -39
- package/dist/{Task-BL4Idm9r.d.ts → Task-CxGgN6I0.d.ts} +801 -39
- package/dist/{chunk-YAFNYNFX.mjs → chunk-2IFKPYPO.mjs} +453 -17
- package/dist/chunk-2IFKPYPO.mjs.map +1 -0
- package/dist/{chunk-MYXMIVWA.mjs → chunk-FX33UKAD.mjs} +8 -6
- package/dist/chunk-FX33UKAD.mjs.map +1 -0
- package/dist/{chunk-QTZ5XTBY.mjs → chunk-PKJTN2PD.mjs} +458 -13
- package/dist/chunk-PKJTN2PD.mjs.map +1 -0
- package/dist/{chunk-7WNLN63J.mjs → chunk-RZ23BMVR.mjs} +599 -124
- package/dist/chunk-RZ23BMVR.mjs.map +1 -0
- package/dist/chunk-UDUATSCJ.mjs +48 -0
- package/dist/chunk-UDUATSCJ.mjs.map +1 -0
- package/dist/{IRunner-DOMtDTVt.d.ts → eventStore-CTCSKS9E.d.ts} +976 -145
- package/dist/{IRunner-ihalYfTo.d.mts → eventStore-CcB8yELZ.d.mts} +976 -145
- package/dist/index.d.mts +905 -164
- package/dist/index.d.ts +905 -164
- package/dist/index.js +12496 -3308
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10830 -2919
- package/dist/index.mjs.map +1 -1
- package/dist/parsing.d.mts +2 -2
- package/dist/parsing.d.ts +2 -2
- package/dist/parsing.js +277 -21
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +3 -3
- package/dist/plan-utils.d.mts +8 -5
- package/dist/plan-utils.d.ts +8 -5
- package/dist/plan-utils.js +262 -33
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +39 -3
- package/dist/{runSettingsText-DVOd7vKC.d.ts → runSettingsText-DFVpe6aU.d.mts} +1996 -895
- package/dist/{runSettingsText-BuLVBlXS.d.mts → runSettingsText-lKLDsyli.d.ts} +1996 -895
- package/dist/testing.d.mts +99 -4
- package/dist/testing.d.ts +99 -4
- package/dist/testing.js +213 -8
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +193 -8
- package/dist/testing.mjs.map +1 -1
- package/docker/task.Dockerfile +22 -0
- package/package.json +3 -1
- package/skills/diagnose/SKILL.md +2 -2
- package/skills/explore/SKILL.md +1 -1
- package/dist/chunk-7WNLN63J.mjs.map +0 -1
- package/dist/chunk-MYXMIVWA.mjs.map +0 -1
- package/dist/chunk-QTZ5XTBY.mjs.map +0 -1
- package/dist/chunk-YAFNYNFX.mjs.map +0 -1
|
@@ -1,357 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { q as ApprovalRequest, r as ApprovalSource,
|
|
3
|
-
import { R as RunnerModeInfo } from './ModeResolver-
|
|
1
|
+
import { b3 as RunnerId, bp as Task, p as DiscoveredModel, bl as StoredHandoff, bA as TaskSnapshot, b as AwaitingReason, bG as UsageRecord, b4 as RunnerSessionCost, J as HandoffCommit, bI as Verdict, aj as LegacyPlanState, bx as TaskReportTo, bz as TaskSkillSnapshot, by as TaskSkillNotice, bm as SubagentOutcome, c as BelowPlan, C as CheckWord, am as Mandate, aq as MandateRequest, ap as MandateRefusal, ad as IsolationTaskRef, a$ as RevertCommand, aa as IsolationRevertTask, h as ConversationMessage, bh as SkillLoadNotice, aw as PendingPlanTurn, K as HandoffDigest, a as AttemptUsage, bv as TaskLoop, bt as TaskIsolation, o as DelegatedRow, b2 as RunSettings, X as IsolationHandoff, aA as PlanUsage, a2 as IsolationMergeResult, aR as ReplyRun, ba as SessionBilling, ar as ModelUsage, bH as UsageTotals, g as ContextFill, aC as PlannerCompaction, s as ExecutionRecord, aY as ResearchStep, ay as PlanState, ab as IsolationRun, T as IWorktreeIsolation, aQ as RepairWait, ag as IsolationView, a9 as IsolationRevertResult, bB as TaskStatus, q as ExecutionActor, w as GuardTrip, at as NodeAuthority, v as GuardTarget, b7 as ScriptBody, r as ExecutionCommandName, aX as ResearchProgress, aW as ResearchLogEntry, bf as SkillInfo, bg as SkillLoad, bk as SkillsService, aE as PlannerContextPause, a0 as IsolationMergeBlock, _ as IsolationLandedTask, a4 as IsolationPreview, a_ as ResearchToolType, bo as SupervisorLevel, ak as LoopSubject, aZ as ResearchStepOutcome, aD as PlannerCompactionOutcome, aG as PlannerUsage, t as FindingSeverity, bC as TaskType, bn as SubtreeReport, av as PatchView, bu as TaskIsolationState, bD as TaskUsageSummary } from './Task-CxGgN6I0.mjs';
|
|
2
|
+
import { q as ApprovalRequest, r as ApprovalSource, U as IApproval, bO as ToolOutcome, _ as IRunnerSession, a1 as IsolationRunController, V as IConfig, bR as UsageLimitSignal, bA as TaskMessageFrom, b4 as RunnerModelRef, aX as RunnerCommand, b1 as RunnerMcpServer, bs as StructuredTurnEnd, k as ApprovalDecision, bg as ScriptRun, bh as ScriptStatus, br as StructuredEvent, aj as NodePath, u as BoardDraft, v as BoardEntry, w as BoardPost, t as BoardAuthor, af as McpToolReply, J as EventStore, j as ApprovalAnswer, aK as QueuedTaskMessage, l as ApprovalKind, Y as INotification, Z as IRunner, b6 as RunnerRegistry, bo as SkillLookup, bJ as TaskShellSite, bI as TaskShell, K as ExecutionBackend, aR as ReservedLease, d as AgentProcessDeps, a as AgentAdapter, ar as OrdewellMcpServer, ap as OpenLease, W as IFileSystem, ay as PlannerModes, a0 as IsolatedExecution, aE as PlannerToolHandler, bG as TaskRunnerConfig, b0 as RunnerManifest, f as AiProvider, ax as PlannerBackendId, aq as OrchestratorOption, bl as SessionMeta } from './eventStore-CcB8yELZ.mjs';
|
|
3
|
+
import { R as RunnerModeInfo } from './ModeResolver-CA2fUU9h.mjs';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
warn(msg: string): void;
|
|
12
|
-
error(msg: string): void;
|
|
13
|
-
confirm(msg: string, options: string[]): Promise<string | undefined>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* The SSRF guard for anything that leaves the machine on the planner's behalf.
|
|
18
|
-
* An unguarded `http://169.254.169.254/` would hand a prompt-injected planner
|
|
19
|
-
* the cloud metadata credentials, so every outbound host is vetted here: IP
|
|
20
|
-
* literals by range, names by every address DNS answers with.
|
|
21
|
-
*/
|
|
22
|
-
type ResolveAll = (host: string) => Promise<string[]>;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* The one decision every planner web read goes through, whichever runner
|
|
26
|
-
* plans and whichever path carries the bytes (ADR-0027). A fetch names the
|
|
27
|
-
* URL it reads; a search names its query and the provider that receives it.
|
|
28
|
-
*/
|
|
29
|
-
type WebRead = {
|
|
30
|
-
kind: 'fetch';
|
|
31
|
-
url: string;
|
|
32
|
-
}
|
|
33
|
-
/** `provider` keys the grant; `providerLabel`, when given, names it to the person asked. */
|
|
34
|
-
| {
|
|
35
|
-
kind: 'search';
|
|
36
|
-
query: string;
|
|
37
|
-
provider: string;
|
|
38
|
-
providerLabel?: string;
|
|
39
|
-
note?: string;
|
|
40
|
-
};
|
|
41
|
-
/** A refusal's `reason` is written for the planner: it says what to do next. */
|
|
42
|
-
type WebReadDecision = {
|
|
43
|
-
allowed: true;
|
|
44
|
-
} | {
|
|
45
|
-
allowed: false;
|
|
46
|
-
reason: string;
|
|
47
|
-
};
|
|
48
|
-
interface DecideOptions {
|
|
49
|
-
/**
|
|
50
|
-
* Research subagents run in the background where nothing can prompt
|
|
51
|
-
* (ADR-0008, T6). When false, a read that would ask is refused with the gap
|
|
52
|
-
* to report, rather than raising a prompt nobody can answer.
|
|
53
|
-
*/
|
|
54
|
-
prompting?: boolean;
|
|
55
|
-
/**
|
|
56
|
-
* Where this read's decisions go, the first URL's and any redirect hop's,
|
|
57
|
-
* in place of the session's approval record. A read-only task's are its
|
|
58
|
-
* attempt's, never the planner's (ADR-0046), so its policy records nothing
|
|
59
|
-
* without one.
|
|
60
|
-
*/
|
|
61
|
-
record?: DecisionRecord;
|
|
62
|
-
}
|
|
63
|
-
type DecisionRecord = (req: ApprovalRequest, granted: boolean, source: ApprovalSource) => void;
|
|
64
|
-
interface WebReadPolicyOptions {
|
|
65
|
-
approval: IApproval;
|
|
66
|
-
/** The secrets Ordewell holds — provider keys, MCP tokens — read per request. */
|
|
67
|
-
secrets?: () => Iterable<string>;
|
|
68
|
-
/** Defaults to `process.env`; its credential-named values are secrets too. */
|
|
69
|
-
env?: () => Record<string, string | undefined>;
|
|
70
|
-
/** How many web reads one planner turn may make; read per request, so a settings change applies at once. */
|
|
71
|
-
budget?: () => number;
|
|
72
|
-
/** The planner turn in progress; a new one starts a new budget. */
|
|
73
|
-
turn?: () => string | undefined;
|
|
74
|
-
/** Override DNS resolution (every answer for a name) in tests. */
|
|
75
|
-
resolveHost?: ResolveAll;
|
|
76
|
-
/**
|
|
77
|
-
* The read-only task whose attempt reads (ADR-0046), by title, set by
|
|
78
|
-
* {@link WebReadPolicy.forTask}: named in approvals and refusals, and its
|
|
79
|
-
* budget is the policy's own for its whole life, whatever `turn` says.
|
|
80
|
-
*/
|
|
81
|
-
task?: string;
|
|
82
|
-
}
|
|
83
|
-
declare const DEFAULT_WEB_READ_BUDGET = 40;
|
|
84
|
-
declare class WebReadPolicy {
|
|
85
|
-
private readonly options;
|
|
86
|
-
private readonly reader;
|
|
87
|
-
private readonly approval;
|
|
88
|
-
private readonly resolveHost;
|
|
89
|
-
private readonly secrets;
|
|
90
|
-
private readonly env;
|
|
91
|
-
private readonly budget;
|
|
92
|
-
private readonly turn;
|
|
93
|
-
private spent;
|
|
94
|
-
constructor(opts: WebReadPolicyOptions);
|
|
95
|
-
/**
|
|
96
|
-
* The same policy for one read-only task attempt (ADR-0046): the same
|
|
97
|
-
* approval, allowlist, live secrets and budget setting, with a count of its
|
|
98
|
-
* own that no planner turn resets and no other attempt spends. One per
|
|
99
|
-
* attempt, so a retry or a continue starts a fresh count.
|
|
100
|
-
*/
|
|
101
|
-
forTask(task: string): WebReadPolicy;
|
|
102
|
-
/**
|
|
103
|
-
* Every check that needs no network runs first, then the budget and the
|
|
104
|
-
* approval, and only then is a fetch's host resolved: a lookup is itself a
|
|
105
|
-
* request, so `<data>.attacker.example` would leave through DNS even for a
|
|
106
|
-
* read that is then excluded, over budget or declined.
|
|
107
|
-
*/
|
|
108
|
-
decide(read: WebRead, opts?: DecideOptions): Promise<WebReadDecision>;
|
|
109
|
-
private subagentRefusal;
|
|
110
|
-
/**
|
|
111
|
-
* Whether a search through `provider` would run without asking anyone, for
|
|
112
|
-
* a runner whose own search raises no request and is set on or off when
|
|
113
|
-
* its session starts (ADR-0027). A zero budget disables it; no query is
|
|
114
|
-
* known yet, so secrets and individual reads cannot be checked or counted.
|
|
115
|
-
*/
|
|
116
|
-
searchesUnasked(provider: string): boolean;
|
|
117
|
-
/** The last check, the one that leaves the machine: every DNS answer for the host must be public. */
|
|
118
|
-
private resolved;
|
|
119
|
-
private refuse;
|
|
120
|
-
/**
|
|
121
|
-
* A planner's decisions reach the session's record, the conversation's
|
|
122
|
-
* approval cards; a task attempt's go only where its read says, since they
|
|
123
|
-
* are not the planner's (ADR-0046).
|
|
124
|
-
*/
|
|
125
|
-
private recordFor;
|
|
126
|
-
private vetFetch;
|
|
127
|
-
private vetSearch;
|
|
128
|
-
/** Reads the current planner turn, or the task attempt, may still make, for the reader to see. */
|
|
129
|
-
remaining(): number;
|
|
130
|
-
private spend;
|
|
131
|
-
private refund;
|
|
132
|
-
private carriesSecret;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/** What a caller that can go away hands a read: once `signal` aborts, nothing more leaves for it. */
|
|
136
|
-
interface WebReadOptions {
|
|
137
|
-
signal?: AbortSignal;
|
|
138
|
-
/** Where the read's decisions go instead of the session's record; see `DecideOptions.record`. */
|
|
139
|
-
record?: DecisionRecord;
|
|
140
|
-
}
|
|
141
|
-
interface IWebFetcher {
|
|
142
|
-
/**
|
|
143
|
-
* The web-read policy's decision (ADR-0027), for a read this fetcher will
|
|
144
|
-
* carry or one a runner carries natively, such as Claude's `WebFetch`.
|
|
145
|
-
* `fetch` and `search` decide for themselves; never call both.
|
|
146
|
-
*/
|
|
147
|
-
decide(read: WebRead): Promise<WebReadDecision>;
|
|
148
|
-
/** Whether a runner's own search through `provider` would run unasked; see `WebReadPolicy.searchesUnasked`. */
|
|
149
|
-
searchesUnasked?(provider: string): boolean;
|
|
150
|
-
fetch(url: string, opts?: WebReadOptions): Promise<ToolOutcome>;
|
|
151
|
-
/**
|
|
152
|
-
* Optional web search. A fetcher without it makes the `web_search` tool
|
|
153
|
-
* report itself unavailable rather than failing the turn — the same
|
|
154
|
-
* degradation `fetch` already uses when no fetcher is wired at all.
|
|
155
|
-
*/
|
|
156
|
-
search?(query: string, opts?: WebReadOptions): Promise<ToolOutcome>;
|
|
157
|
-
/**
|
|
158
|
-
* A variant of this fetcher for a research subagent: same policy, cache,
|
|
159
|
-
* transport and budget, but a read that would ask a person is refused
|
|
160
|
-
* instead (ADR-0027, ADR-0008 T6). Absent means subagents get no web tools
|
|
161
|
-
* and the `fetch`/`web_search` tools report themselves unavailable.
|
|
162
|
-
*/
|
|
163
|
-
forSubagent?(): IWebFetcher;
|
|
164
|
-
/**
|
|
165
|
-
* A variant for one read-only task attempt, `task` naming it (ADR-0046):
|
|
166
|
-
* a subagent's in never prompting, with a web-read budget of its own that
|
|
167
|
-
* no planner turn and no other attempt spends or resets. Absent, or
|
|
168
|
-
* undefined, means read-only tasks get no web reads, and their `fetch` and
|
|
169
|
-
* `web_search` report themselves unavailable.
|
|
170
|
-
*/
|
|
171
|
-
forTask?(task: string): IWebFetcher | undefined;
|
|
172
|
-
/** Reads the current budget still allows, where this fetcher's policy counts them. */
|
|
173
|
-
remaining?(): number | undefined;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
interface LiveTailOptions {
|
|
177
|
-
maxLines: number;
|
|
178
|
-
/** A previous {@link LiveTail.nextOffset}: only output after it is rendered. */
|
|
179
|
-
sinceOffset?: number;
|
|
180
|
-
}
|
|
181
|
-
interface LiveTail {
|
|
182
|
-
/** Plain text, escapes and control characters removed. */
|
|
183
|
-
text: string;
|
|
184
|
-
/** Total output received so far; pass it back as `sinceOffset` to read only what follows. */
|
|
185
|
-
nextOffset: number;
|
|
186
|
-
running: boolean;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* The one owner of a task attempt's output: what it printed while running
|
|
190
|
-
* and what it answered once it ended.
|
|
191
|
-
*/
|
|
192
|
-
interface TaskOutputSource {
|
|
193
|
-
/** Start capturing a session; replaces any earlier capture of the task. */
|
|
194
|
-
attach(taskId: string, session: IRunnerSession): void;
|
|
195
|
-
/** Stop capturing the task's session; what was captured stays readable. */
|
|
196
|
-
detach(taskId: string): void;
|
|
197
|
-
/** Drop every capture (a new plan reuses task ids). */
|
|
198
|
-
reset(): void;
|
|
199
|
-
/** The task's final answer: the summary its runner reported through `task_complete`, else what its last turn said. */
|
|
200
|
-
finalText(taskId: string): string;
|
|
201
|
-
/** The summary the runner reported through `task_complete` in its latest turn, if it made that call. */
|
|
202
|
-
report(taskId: string): string | undefined;
|
|
203
|
-
/** The handoff of that call, findings numbered (ADR-0047); undefined when the turn made none, or it handed nothing over. */
|
|
204
|
-
handoff(taskId: string): StoredHandoff | undefined;
|
|
205
|
-
/** Recent output of the task's latest capture, or null if it never had one. */
|
|
206
|
-
liveTail(taskId: string, opts: LiveTailOptions): LiveTail | null;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* The deep module owning all plan-shaped state. Holds `planTasks` (the ordered
|
|
211
|
-
* tree the user edits), the flattened `allTasks` view and the `taskMap` index.
|
|
212
|
-
* The orchestrator calls `markCompleted`/`markFailed`/`markInProgress`/`retry`
|
|
213
|
-
* to update task status — it never mutates task state directly.
|
|
214
|
-
*
|
|
215
|
-
* Completion and failure are read from `task.status` and nothing else, so
|
|
216
|
-
* `isCompleted`, `completedCount`, `isAllComplete` and the scheduler's
|
|
217
|
-
* dependency checks cannot disagree. The store owns its task objects: `load`
|
|
218
|
-
* copies what it is given, the getters hand out readonly views, and
|
|
219
|
-
* `snapshot` is the copy a caller may keep or write to disk.
|
|
220
|
-
*
|
|
221
|
-
* `rebuild` is the internal seam that keeps the flat views in sync with the
|
|
222
|
-
* tree.
|
|
223
|
-
*
|
|
224
|
-
* `planRunners` lives here because it's part of the plan's identity (the runner
|
|
225
|
-
* set, carried on the plan). `assertAssignedRunners` is pure store logic.
|
|
226
|
-
*/
|
|
227
|
-
declare class PlanStore {
|
|
228
|
-
private _planTasks;
|
|
229
|
-
private _allTasks;
|
|
230
|
-
private _taskMap;
|
|
231
|
-
/** Task id → the top-level task it hangs under, itself for a top-level task. */
|
|
232
|
-
private _rootMap;
|
|
233
|
-
private _planRunners;
|
|
234
|
-
private _onMutate;
|
|
235
|
-
private _onTree;
|
|
236
|
-
private _executionLog;
|
|
237
|
-
/** Hook called after every structural mutation (add/remove/update/resetForRun). */
|
|
238
|
-
set onMutate(cb: (() => void) | null);
|
|
239
|
-
/**
|
|
240
|
-
* Called with every task id, subtasks included, each time the tree is
|
|
241
|
-
* rebuilt — on every route a task enters or leaves the plan, loads and
|
|
242
|
-
* reconciled edits included, which `onMutate` does not hear.
|
|
243
|
-
*/
|
|
244
|
-
set onTree(cb: ((ids: ReadonlySet<string>) => void) | null);
|
|
245
|
-
get planTasks(): ReadonlyArray<Readonly<Task>>;
|
|
246
|
-
get allTasks(): ReadonlyArray<Readonly<Task>>;
|
|
247
|
-
get planRunners(): RunnerId[];
|
|
248
|
-
get completedCount(): number;
|
|
249
|
-
get failedCount(): number;
|
|
250
|
-
isAllComplete(): boolean;
|
|
251
|
-
isAnyFailed(): boolean;
|
|
252
|
-
isCompleted(id: string): boolean;
|
|
253
|
-
isSkipped(id: string): boolean;
|
|
254
|
-
/** Nothing is left to do: every task completed or was skipped. */
|
|
255
|
-
isFinished(): boolean;
|
|
256
|
-
isFailed(id: string): boolean;
|
|
257
|
-
get(taskId: string): Readonly<Task> | undefined;
|
|
258
|
-
/**
|
|
259
|
-
* Whether a task runs as an ops task (ADR-0020): a top-level AI task marked
|
|
260
|
-
* so, or a script task, which is one by nature (ADR-0035). A subtask runs
|
|
261
|
-
* with the top-level task it hangs under.
|
|
262
|
-
*/
|
|
263
|
-
isOps(taskId: string): boolean;
|
|
264
|
-
/** A copy of the task tree, detached from the store: later status changes do not reach it. */
|
|
265
|
-
snapshot(): Task[];
|
|
266
|
-
getExecutionLog(): ReadonlyArray<TaskSnapshot>;
|
|
267
|
-
appendToLog(snapshot: TaskSnapshot): void;
|
|
268
|
-
/**
|
|
269
|
-
* Drop a task's archived snapshot. Un-marking a completion has to erase the
|
|
270
|
-
* "finished" record too — dependent tasks are prompted from the log, so a
|
|
271
|
-
* left-behind snapshot would keep feeding them a result that no longer exists.
|
|
272
|
-
*/
|
|
273
|
-
removeFromLog(taskId: string): void;
|
|
274
|
-
clearLog(): void;
|
|
275
|
-
private notifyMutate;
|
|
276
|
-
private countStatus;
|
|
277
|
-
/**
|
|
278
|
-
* `keepFailed` adopts failed tasks as failed: an edit reconciled into a run
|
|
279
|
-
* is not a retry, and the tasks it blocks wait for one (ADR-0034).
|
|
280
|
-
*/
|
|
281
|
-
load(tasks: ReadonlyArray<Readonly<Task>>, runners: readonly RunnerId[], opts?: {
|
|
282
|
-
keepFailed?: boolean;
|
|
283
|
-
}): void;
|
|
284
|
-
add(partial: Partial<Task>): Task;
|
|
285
|
-
remove(taskId: string): void;
|
|
286
|
-
update(taskId: string, changes: Partial<Task>): Task | undefined;
|
|
287
|
-
/**
|
|
288
|
-
* Run preparation as one named op: flip every AI and script task to 'approved'. By
|
|
289
|
-
* default completed tasks keep their status so a reloaded half-finished plan
|
|
290
|
-
* resumes the remainder instead of re-running work that already succeeded,
|
|
291
|
-
* and skipped ones stay skipped: a new run is not a retry of them.
|
|
292
|
-
* `preserveCompleted: false` is for a freshly committed plan, where
|
|
293
|
-
* everything starts over. `keepScheduledResumes` leaves a task waiting on
|
|
294
|
-
* its runner's usage-limit reset waiting: an edit adopted between runs is
|
|
295
|
-
* not the user starting over.
|
|
296
|
-
*/
|
|
297
|
-
resetForRun(opts?: {
|
|
298
|
-
preserveCompleted?: boolean;
|
|
299
|
-
keepScheduledResumes?: boolean;
|
|
300
|
-
}): void;
|
|
301
|
-
markCompleted(id: string): void;
|
|
302
|
-
markFailed(id: string): void;
|
|
303
|
-
markSkipped(id: string, reason?: string): void;
|
|
304
|
-
markInProgress(id: string): void;
|
|
305
|
-
/** Its first attempt is starting: from now on its chat exists, whatever becomes of the attempt. */
|
|
306
|
-
markAttempted(id: string): void;
|
|
307
|
-
markAwaitingUser(id: string, reason?: AwaitingReason): void;
|
|
308
|
-
/** When a task paused on a usage limit resumes on its own; undefined leaves it to a manual retry. */
|
|
309
|
-
setTaskResumeAt(id: string, resumeAt: string | undefined): void;
|
|
310
|
-
markPending(id: string): void;
|
|
311
|
-
/**
|
|
312
|
-
* A new attempt of the task, from nothing it earned. A loop's check starts
|
|
313
|
-
* its rounds over (ADR-0045 L7), unless `sameRound`: a resume after a usage
|
|
314
|
-
* limit goes on with the attempt the limit cut short.
|
|
315
|
-
*/
|
|
316
|
-
retry(id: string, opts?: {
|
|
317
|
-
sameRound?: boolean;
|
|
318
|
-
}): void;
|
|
319
|
-
/** A loop's check counts its rounds afresh from its next run (ADR-0045 L7). */
|
|
320
|
-
startRoundsOver(id: string): void;
|
|
321
|
-
/**
|
|
322
|
-
* The loop runs its check again, as its next round (ADR-0045 L5): a new
|
|
323
|
-
* attempt, the round counted on, and nothing of the round before kept on
|
|
324
|
-
* the task — its report went to the body, and stays in its attempt's log.
|
|
325
|
-
*/
|
|
326
|
-
repeat(id: string): void;
|
|
327
|
-
/** Kept on the task: it was force-started past its merge gate, before these ancestors' work was merged (ADR-0020). */
|
|
328
|
-
setForcedPastGate(id: string, dependencies: string[]): void;
|
|
329
|
-
/** A reason outlives nothing: any status but `awaiting_user` drops it, and the resume time with it; any status drops a skip's reason. */
|
|
330
|
-
private setStatus;
|
|
331
|
-
setTaskVerdict(id: string, verdict: Task['verdict']): void;
|
|
5
|
+
/** What a planned task may be given: the runners it may run on and their modes. */
|
|
6
|
+
interface IntakeCatalog {
|
|
7
|
+
runners: readonly RunnerId[];
|
|
8
|
+
/** Absent when no runner's modes are known: the mode is then guessed (ADR-0031). */
|
|
9
|
+
runnerModes?: Partial<Record<RunnerId, readonly RunnerModeInfo[]>>;
|
|
10
|
+
autonomousDefault?: boolean;
|
|
332
11
|
/**
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
12
|
+
* An edit's assignments are resolved against the catalog as it is planned,
|
|
13
|
+
* and a model it names that the runner does not offer is refused; a
|
|
14
|
+
* submitted plan's models are resolved as it lands instead (ADR-0003).
|
|
336
15
|
*/
|
|
337
|
-
|
|
338
|
-
/** The owner is saved with the session it belongs to, and dropped with it. */
|
|
339
|
-
setTaskRunnerSessionId(id: string, runnerSessionId: string | undefined, owner?: RunnerId): void;
|
|
340
|
-
setCarriedFrom(id: string, runner: RunnerId): void;
|
|
341
|
-
clearCarriedFrom(id: string): void;
|
|
342
|
-
startAttemptUsage(id: string, attempt: number, runner: string, startedAt: string): void;
|
|
343
|
-
recordAttemptUsage(id: string, attempt: number, record: UsageRecord, now: string): void;
|
|
344
|
-
endAttemptUsage(id: string, attempt: number, now: string, runnerSessionCost?: RunnerSessionCost, sessionId?: string): void;
|
|
345
|
-
setTaskAttemptSkills(id: string, skills: Task['attemptSkills']): void;
|
|
16
|
+
models?: AssignmentCatalog;
|
|
346
17
|
/**
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
* plan's first one instead.
|
|
18
|
+
* Why this planner may not write a delegated task or a read-only script
|
|
19
|
+
* (ADR-0055 D1, D8), or null when it may. Absent, there is no node to read:
|
|
20
|
+
* a one-shot planner, or a route that holds no mandate.
|
|
351
21
|
*/
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
22
|
+
delegationRefusal?: string | null;
|
|
23
|
+
/** Which of a child's script tasks run sealed (ADR-0056 M9): each such lands read-only, on every route. */
|
|
24
|
+
sealsScripts?: (task: Pick<Task, 'commands' | 'script' | 'timeoutMs'>) => boolean;
|
|
355
25
|
}
|
|
356
26
|
|
|
357
27
|
/**
|
|
@@ -385,6 +55,10 @@ interface AssignmentCatalog {
|
|
|
385
55
|
runnerModes?: Partial<Record<RunnerId, readonly RunnerModeInfo[]>>;
|
|
386
56
|
/** Raw (unfiltered) allowlist, keyed by runner; read through {@link effectiveAllowlist}. */
|
|
387
57
|
perRunnerAllowlist?: Partial<Record<RunnerId, string[]>>;
|
|
58
|
+
/** Why an edit may not write a delegated task, or null when it may; absent, no node is behind it (`IntakeCatalog`). */
|
|
59
|
+
delegationRefusal?: string | null;
|
|
60
|
+
/** Which script tasks an edit adds land sealed (`IntakeCatalog`). */
|
|
61
|
+
sealsScripts?: IntakeCatalog['sealsScripts'];
|
|
388
62
|
/** Full (true) or Guarded: the mode a derived task lands on unless it is read-only (ADR-0001). Full when absent. */
|
|
389
63
|
autonomousDefault?: boolean;
|
|
390
64
|
/**
|
|
@@ -556,377 +230,371 @@ declare function canSplitTask(tasks: readonly Task[], taskId: string): {
|
|
|
556
230
|
declare function applyTaskOps(currentTasks: readonly Task[], ops: TaskOp[], runners: RunnerId[], catalog?: AssignmentCatalog, earlierHandles?: ReadonlyMap<string, string>): ApplyTaskOpsResult;
|
|
557
231
|
|
|
558
232
|
/**
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
233
|
+
* The SSRF guard for anything that leaves the machine on the planner's behalf.
|
|
234
|
+
* An unguarded `http://169.254.169.254/` would hand a prompt-injected planner
|
|
235
|
+
* the cloud metadata credentials, so every outbound host is vetted here: IP
|
|
236
|
+
* literals by range, names by every address DNS answers with.
|
|
237
|
+
*/
|
|
238
|
+
type ResolveAll = (host: string) => Promise<string[]>;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* The one decision every planner web read goes through, whichever runner
|
|
242
|
+
* plans and whichever path carries the bytes (ADR-0027). A fetch names the
|
|
243
|
+
* URL it reads; a search names its query and the provider that receives it.
|
|
563
244
|
*/
|
|
564
|
-
|
|
565
|
-
|
|
245
|
+
type WebRead = {
|
|
246
|
+
kind: 'fetch';
|
|
247
|
+
url: string;
|
|
248
|
+
}
|
|
249
|
+
/** `provider` keys the grant; `providerLabel`, when given, names it to the person asked. */
|
|
250
|
+
| {
|
|
251
|
+
kind: 'search';
|
|
252
|
+
query: string;
|
|
253
|
+
provider: string;
|
|
254
|
+
providerLabel?: string;
|
|
255
|
+
note?: string;
|
|
256
|
+
};
|
|
257
|
+
/** A refusal's `reason` is written for the planner: it says what to do next. */
|
|
258
|
+
type WebReadDecision = {
|
|
259
|
+
allowed: true;
|
|
260
|
+
} | {
|
|
261
|
+
allowed: false;
|
|
262
|
+
reason: string;
|
|
263
|
+
};
|
|
264
|
+
interface DecideOptions {
|
|
265
|
+
/**
|
|
266
|
+
* Research subagents run in the background where nothing can prompt
|
|
267
|
+
* (ADR-0008, T6). When false, a read that would ask is refused with the gap
|
|
268
|
+
* to report, rather than raising a prompt nobody can answer.
|
|
269
|
+
*/
|
|
270
|
+
prompting?: boolean;
|
|
566
271
|
/**
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
272
|
+
* Where this read's decisions go, the first URL's and any redirect hop's,
|
|
273
|
+
* in place of the session's approval record. A read-only task's are its
|
|
274
|
+
* attempt's, never the planner's (ADR-0046), so its policy records nothing
|
|
275
|
+
* without one.
|
|
570
276
|
*/
|
|
571
|
-
|
|
277
|
+
record?: DecisionRecord;
|
|
572
278
|
}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
279
|
+
type DecisionRecord = (req: ApprovalRequest, granted: boolean, source: ApprovalSource) => void;
|
|
280
|
+
interface WebReadPolicyOptions {
|
|
281
|
+
approval: IApproval;
|
|
282
|
+
/** The secrets Ordewell holds — provider keys, MCP tokens — read per request. */
|
|
283
|
+
secrets?: () => Iterable<string>;
|
|
284
|
+
/** Defaults to `process.env`; its credential-named values are secrets too. */
|
|
285
|
+
env?: () => Record<string, string | undefined>;
|
|
286
|
+
/** How many web reads one planner turn may make; read per request, so a settings change applies at once. */
|
|
287
|
+
budget?: () => number;
|
|
288
|
+
/** The planner turn in progress; a new one starts a new budget. */
|
|
289
|
+
turn?: () => string | undefined;
|
|
290
|
+
/** Override DNS resolution (every answer for a name) in tests. */
|
|
291
|
+
resolveHost?: ResolveAll;
|
|
292
|
+
/**
|
|
293
|
+
* The read-only task whose attempt reads (ADR-0046), by title, set by
|
|
294
|
+
* {@link WebReadPolicy.forTask}: named in approvals and refusals, and its
|
|
295
|
+
* budget is the policy's own for its whole life, whatever `turn` says.
|
|
296
|
+
*/
|
|
297
|
+
task?: string;
|
|
298
|
+
}
|
|
299
|
+
declare const DEFAULT_WEB_READ_BUDGET = 40;
|
|
300
|
+
declare class WebReadPolicy {
|
|
301
|
+
private readonly options;
|
|
302
|
+
private readonly reader;
|
|
303
|
+
private readonly approval;
|
|
304
|
+
private readonly resolveHost;
|
|
305
|
+
private readonly secrets;
|
|
306
|
+
private readonly env;
|
|
307
|
+
private readonly budget;
|
|
308
|
+
private readonly turn;
|
|
309
|
+
private spent;
|
|
310
|
+
constructor(opts: WebReadPolicyOptions);
|
|
311
|
+
/**
|
|
312
|
+
* The same policy for one read-only task attempt (ADR-0046): the same
|
|
313
|
+
* approval, allowlist, live secrets and budget setting, with a count of its
|
|
314
|
+
* own that no planner turn resets and no other attempt spends. One per
|
|
315
|
+
* attempt, so a retry or a continue starts a fresh count.
|
|
316
|
+
*/
|
|
317
|
+
forTask(task: string): WebReadPolicy;
|
|
318
|
+
/**
|
|
319
|
+
* Every check that needs no network runs first, then the budget and the
|
|
320
|
+
* approval, and only then is a fetch's host resolved: a lookup is itself a
|
|
321
|
+
* request, so `<data>.attacker.example` would leave through DNS even for a
|
|
322
|
+
* read that is then excluded, over budget or declined.
|
|
323
|
+
*/
|
|
324
|
+
decide(read: WebRead, opts?: DecideOptions): Promise<WebReadDecision>;
|
|
325
|
+
private subagentRefusal;
|
|
326
|
+
/**
|
|
327
|
+
* Whether a search through `provider` would run without asking anyone, for
|
|
328
|
+
* a runner whose own search raises no request and is set on or off when
|
|
329
|
+
* its session starts (ADR-0027). A zero budget disables it; no query is
|
|
330
|
+
* known yet, so secrets and individual reads cannot be checked or counted.
|
|
331
|
+
*/
|
|
332
|
+
searchesUnasked(provider: string): boolean;
|
|
333
|
+
/** The last check, the one that leaves the machine: every DNS answer for the host must be public. */
|
|
334
|
+
private resolved;
|
|
335
|
+
private refuse;
|
|
336
|
+
/**
|
|
337
|
+
* A planner's decisions reach the session's record, the conversation's
|
|
338
|
+
* approval cards; a task attempt's go only where its read says, since they
|
|
339
|
+
* are not the planner's (ADR-0046).
|
|
340
|
+
*/
|
|
341
|
+
private recordFor;
|
|
342
|
+
private vetFetch;
|
|
343
|
+
private vetSearch;
|
|
344
|
+
/** Reads the current planner turn, or the task attempt, may still make, for the reader to see. */
|
|
345
|
+
remaining(): number;
|
|
346
|
+
private spend;
|
|
347
|
+
private refund;
|
|
348
|
+
private carriesSecret;
|
|
581
349
|
}
|
|
582
350
|
|
|
583
|
-
/**
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
interface
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
351
|
+
/** What a caller that can go away hands a read: once `signal` aborts, nothing more leaves for it. */
|
|
352
|
+
interface WebReadOptions {
|
|
353
|
+
signal?: AbortSignal;
|
|
354
|
+
/** Where the read's decisions go instead of the session's record; see `DecideOptions.record`. */
|
|
355
|
+
record?: DecisionRecord;
|
|
356
|
+
}
|
|
357
|
+
interface IWebFetcher {
|
|
358
|
+
/**
|
|
359
|
+
* The web-read policy's decision (ADR-0027), for a read this fetcher will
|
|
360
|
+
* carry or one a runner carries natively, such as Claude's `WebFetch`.
|
|
361
|
+
* `fetch` and `search` decide for themselves; never call both.
|
|
362
|
+
*/
|
|
363
|
+
decide(read: WebRead): Promise<WebReadDecision>;
|
|
364
|
+
/** Whether a runner's own search through `provider` would run unasked; see `WebReadPolicy.searchesUnasked`. */
|
|
365
|
+
searchesUnasked?(provider: string): boolean;
|
|
366
|
+
fetch(url: string, opts?: WebReadOptions): Promise<ToolOutcome>;
|
|
367
|
+
/**
|
|
368
|
+
* Optional web search. A fetcher without it makes the `web_search` tool
|
|
369
|
+
* report itself unavailable rather than failing the turn — the same
|
|
370
|
+
* degradation `fetch` already uses when no fetcher is wired at all.
|
|
371
|
+
*/
|
|
372
|
+
search?(query: string, opts?: WebReadOptions): Promise<ToolOutcome>;
|
|
593
373
|
/**
|
|
594
|
-
*
|
|
595
|
-
*
|
|
596
|
-
*
|
|
597
|
-
*
|
|
374
|
+
* A variant of this fetcher for a research subagent: same policy, cache,
|
|
375
|
+
* transport and budget, but a read that would ask a person is refused
|
|
376
|
+
* instead (ADR-0027, ADR-0008 T6). Absent means subagents get no web tools
|
|
377
|
+
* and the `fetch`/`web_search` tools report themselves unavailable.
|
|
378
|
+
*/
|
|
379
|
+
forSubagent?(): IWebFetcher;
|
|
380
|
+
/**
|
|
381
|
+
* A variant for one read-only task attempt, `task` naming it (ADR-0046):
|
|
382
|
+
* a subagent's in never prompting, with a web-read budget of its own that
|
|
383
|
+
* no planner turn and no other attempt spends or resets. Absent, or
|
|
384
|
+
* undefined, means read-only tasks get no web reads, and their `fetch` and
|
|
385
|
+
* `web_search` report themselves unavailable.
|
|
598
386
|
*/
|
|
599
|
-
|
|
387
|
+
forTask?(task: string): IWebFetcher | undefined;
|
|
388
|
+
/** Reads the current budget still allows, where this fetcher's policy counts them. */
|
|
389
|
+
remaining?(): number | undefined;
|
|
600
390
|
}
|
|
601
391
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
392
|
+
interface LiveTailOptions {
|
|
393
|
+
maxLines: number;
|
|
394
|
+
/** A previous {@link LiveTail.nextOffset}: only output after it is rendered. */
|
|
395
|
+
sinceOffset?: number;
|
|
396
|
+
}
|
|
397
|
+
interface LiveTail {
|
|
398
|
+
/** Plain text, escapes and control characters removed. */
|
|
399
|
+
text: string;
|
|
400
|
+
/** Total output received so far; pass it back as `sinceOffset` to read only what follows. */
|
|
401
|
+
nextOffset: number;
|
|
402
|
+
running: boolean;
|
|
403
|
+
}
|
|
609
404
|
/**
|
|
610
|
-
*
|
|
611
|
-
*
|
|
612
|
-
* hand over and was cleared up.
|
|
405
|
+
* The one owner of a task attempt's output: what it printed while running
|
|
406
|
+
* and what it answered once it ended.
|
|
613
407
|
*/
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
408
|
+
interface TaskOutputSource {
|
|
409
|
+
/** Start capturing a session; replaces any earlier capture of the task. */
|
|
410
|
+
attach(taskId: string, session: IRunnerSession): void;
|
|
411
|
+
/** Stop capturing the task's session; what was captured stays readable. */
|
|
412
|
+
detach(taskId: string): void;
|
|
413
|
+
/** Drop every capture (a new plan reuses task ids). */
|
|
414
|
+
reset(): void;
|
|
415
|
+
/** The task's final answer: the summary its runner reported through `task_complete`, else what its last turn said. */
|
|
416
|
+
finalText(taskId: string): string;
|
|
417
|
+
/** The summary the runner reported through `task_complete` in its latest turn, if it made that call. */
|
|
418
|
+
report(taskId: string): string | undefined;
|
|
419
|
+
/** The handoff of that call, findings numbered (ADR-0047); undefined when the turn made none, or it handed nothing over. */
|
|
420
|
+
handoff(taskId: string): StoredHandoff | undefined;
|
|
421
|
+
/** Recent output of the task's latest capture, or null if it never had one. */
|
|
422
|
+
liveTail(taskId: string, opts: LiveTailOptions): LiveTail | null;
|
|
622
423
|
}
|
|
424
|
+
|
|
623
425
|
/**
|
|
624
|
-
*
|
|
625
|
-
*
|
|
426
|
+
* The deep module owning all plan-shaped state. Holds `planTasks` (the ordered
|
|
427
|
+
* tree the user edits), the flattened `allTasks` view and the `taskMap` index.
|
|
428
|
+
* The orchestrator calls `markCompleted`/`markFailed`/`markInProgress`/`retry`
|
|
429
|
+
* to update task status — it never mutates task state directly.
|
|
430
|
+
*
|
|
431
|
+
* Completion and failure are read from `task.status` and nothing else, so
|
|
432
|
+
* `isCompleted`, `completedCount`, `isAllComplete` and the scheduler's
|
|
433
|
+
* dependency checks cannot disagree. The store owns its task objects: `load`
|
|
434
|
+
* copies what it is given, the getters hand out readonly views, and
|
|
435
|
+
* `snapshot` is the copy a caller may keep or write to disk.
|
|
436
|
+
*
|
|
437
|
+
* `rebuild` is the internal seam that keeps the flat views in sync with the
|
|
438
|
+
* tree.
|
|
439
|
+
*
|
|
440
|
+
* `planRunners` lives here because it's part of the plan's identity (the runner
|
|
441
|
+
* set, carried on the plan). `assertAssignedRunners` is pure store logic.
|
|
626
442
|
*/
|
|
627
|
-
|
|
443
|
+
declare class PlanStore {
|
|
444
|
+
private _planTasks;
|
|
445
|
+
private _allTasks;
|
|
446
|
+
private _taskMap;
|
|
447
|
+
/** Task id → the top-level task it hangs under, itself for a top-level task. */
|
|
448
|
+
private _rootMap;
|
|
449
|
+
private _planRunners;
|
|
450
|
+
private _onMutate;
|
|
451
|
+
private _onTree;
|
|
452
|
+
private _executionLog;
|
|
453
|
+
/** Hook called after every structural mutation (add/remove/update/resetForRun). */
|
|
454
|
+
set onMutate(cb: (() => void) | null);
|
|
628
455
|
/**
|
|
629
|
-
*
|
|
630
|
-
*
|
|
631
|
-
*
|
|
632
|
-
* to the session that was left.
|
|
456
|
+
* Called with every task id, subtasks included, each time the tree is
|
|
457
|
+
* rebuilt — on every route a task enters or leaves the plan, loads and
|
|
458
|
+
* reconciled edits included, which `onMutate` does not hear.
|
|
633
459
|
*/
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
workspaceRoot: () => string;
|
|
649
|
-
listener: IsolationRunListener;
|
|
460
|
+
set onTree(cb: ((ids: ReadonlySet<string>) => void) | null);
|
|
461
|
+
get planTasks(): ReadonlyArray<Readonly<Task>>;
|
|
462
|
+
get allTasks(): ReadonlyArray<Readonly<Task>>;
|
|
463
|
+
get planRunners(): RunnerId[];
|
|
464
|
+
get completedCount(): number;
|
|
465
|
+
get failedCount(): number;
|
|
466
|
+
isAllComplete(): boolean;
|
|
467
|
+
isAnyFailed(): boolean;
|
|
468
|
+
isCompleted(id: string): boolean;
|
|
469
|
+
isSkipped(id: string): boolean;
|
|
470
|
+
/** Nothing is left to do: every task completed or was skipped. */
|
|
471
|
+
isFinished(): boolean;
|
|
472
|
+
isFailed(id: string): boolean;
|
|
473
|
+
get(taskId: string): Readonly<Task> | undefined;
|
|
650
474
|
/**
|
|
651
|
-
*
|
|
652
|
-
*
|
|
653
|
-
* the
|
|
475
|
+
* Whether a task runs as an ops task (ADR-0020): a top-level AI task marked
|
|
476
|
+
* so, or a script task, which is one by nature (ADR-0035). A subtask runs
|
|
477
|
+
* with the top-level task it hangs under.
|
|
654
478
|
*/
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
* user has merged, the tree check of an ops task, the handoff when the run
|
|
663
|
-
* closes, and what the user does with it afterwards. The record it keeps
|
|
664
|
-
* outlives one run — a resumed plan continues it.
|
|
665
|
-
*/
|
|
666
|
-
declare class IsolationRunController {
|
|
667
|
-
private readonly isolation;
|
|
668
|
-
private readonly config;
|
|
669
|
-
private readonly notifications;
|
|
670
|
-
private readonly workspaceRoot;
|
|
671
|
-
private readonly listener;
|
|
672
|
-
private readonly liveTasks;
|
|
673
|
-
private run;
|
|
674
|
-
/** See {@link mergedRun}. */
|
|
675
|
-
private merged;
|
|
676
|
-
/** An adoption stays scoped even while cleanup temporarily leaves no run record. */
|
|
677
|
-
private adoptions;
|
|
678
|
-
/** Copied paths already reported for the current run: every task gets the same copies. */
|
|
679
|
-
private reportedCopies;
|
|
680
|
-
private reportedSetupFailures;
|
|
681
|
-
/**
|
|
682
|
-
* How the open run executes; null while no run is open, `undecided` until
|
|
683
|
-
* its first change task asks. A run is one Execute-Plan or one manual task
|
|
684
|
-
* run, from its start until it settles or is stopped.
|
|
685
|
-
*/
|
|
686
|
-
private mode;
|
|
687
|
-
/** Resolver task id → the conflicted task it resolves; see {@link linkResolver}. */
|
|
688
|
-
private resolvers;
|
|
689
|
-
private opening;
|
|
690
|
-
private opened;
|
|
691
|
-
/** Bumped by an interrupt, so an activation in flight across it does not open the run it ended. */
|
|
692
|
-
private activations;
|
|
693
|
-
/** The start a dirty tree turned away, handed back once the user chooses how to go on. */
|
|
694
|
-
private blockedStart;
|
|
695
|
-
/** The dirty repos behind {@link blockedStart}, for the stash notice. */
|
|
696
|
-
private blockedRepos;
|
|
697
|
-
constructor(deps: IsolationRunControllerDeps);
|
|
698
|
-
/** The plan's run record, open or not; null when the plan has not isolated. */
|
|
699
|
-
get current(): IsolationRun | null;
|
|
700
|
-
/**
|
|
701
|
-
* The id of the plan's last isolated run once it closed with everything it
|
|
702
|
-
* landed merged into the user's branch and was cleared up: what tells a
|
|
703
|
-
* Merge all asked for after it, which has nothing to merge, from one in a
|
|
704
|
-
* plan that never isolated (ADR-0029). Null while the plan holds a run
|
|
705
|
-
* record, and once a later run decides how it executes. Saved with the plan.
|
|
706
|
-
*/
|
|
707
|
-
get mergedRun(): string | null;
|
|
708
|
-
get isOpen(): boolean;
|
|
709
|
-
/** How many runs have opened: what tells one run's launches from the next one's. */
|
|
710
|
-
get epoch(): number;
|
|
711
|
-
/** The open run has decided whether it isolates. */
|
|
712
|
-
get decided(): boolean;
|
|
713
|
-
/** The open run executes in worktrees. */
|
|
714
|
-
get isolating(): boolean;
|
|
715
|
-
/** A run is waiting on the user to stash or to go on without isolation. */
|
|
716
|
-
get blocked(): boolean;
|
|
717
|
-
/** What the plan persists of isolated execution; null when no run ever isolated. */
|
|
718
|
-
get planIsolation(): PlanIsolation | null;
|
|
719
|
-
/** The one guard of every action on the run: a plan that never isolated is a request refused, not a fault. */
|
|
720
|
-
requireRun(): IsolationRun;
|
|
721
|
-
/** A task's record in the open run, only while that run isolates. */
|
|
722
|
-
openRecord(taskId: string): IsolationTaskRecord | undefined;
|
|
723
|
-
/** Where a task's isolated work stands; null when the plan has no isolation run to speak of. */
|
|
724
|
-
taskIsolation(taskId: string): TaskIsolation | null;
|
|
725
|
-
view(): IsolationView | null;
|
|
726
|
-
/**
|
|
727
|
-
* Take over a plan's persisted isolation, or none for a plan that has not
|
|
728
|
-
* isolated yet. Whatever a crashed process left behind for the run — a
|
|
729
|
-
* worktree still marked active, a directory no record owns — is pruned,
|
|
730
|
-
* while kept, failed and conflicted worktrees stay for the user. Then git is
|
|
731
|
-
* asked which landed work the user has merged since the record was saved:
|
|
732
|
-
* a settled run whose landed work is all in HEAD has nothing left to hand
|
|
733
|
-
* over, so it is cleared up as Merge all would have, unless it still holds
|
|
734
|
-
* work that never landed (ADR-0013).
|
|
735
|
-
*
|
|
736
|
-
* Deliberately not reported to the listener: adopting is not a change of the
|
|
737
|
-
* session's own, and a host that adopts without persisting (VS Code's
|
|
738
|
-
* restore) would otherwise write a new session file on every reload. What
|
|
739
|
-
* git changed is returned instead, for the caller to save where it can and
|
|
740
|
-
* announce. A plan loaded meanwhile supersedes this adoption, which then
|
|
741
|
-
* touches nothing and resolves `unchanged`. `mergedRun` is the plan's saved
|
|
742
|
-
* {@link mergedRun}.
|
|
743
|
-
*/
|
|
744
|
-
adopt(state: PlanIsolation | null, mergedRun?: string): Promise<AdoptOutcome>;
|
|
745
|
-
/** Open a run if none is, leaving whether it isolates to its first change task. */
|
|
746
|
-
open(): void;
|
|
747
|
-
/**
|
|
748
|
-
* Decide once per run, as its first change task starts, whether it executes
|
|
749
|
-
* in worktrees (ADR-0020): an ops task needs none, so a run of only ops
|
|
750
|
-
* tasks never asks. `resume` is what a dirty tree parks until the user
|
|
751
|
-
* chooses how to go on. Resolves false while the run waits on that choice.
|
|
752
|
-
*/
|
|
753
|
-
decide(resume: () => Promise<void>): Promise<boolean>;
|
|
754
|
-
/**
|
|
755
|
-
* Whether the run in force, or else the next one, gives each task its own
|
|
756
|
-
* worktrees, and of which repo group — what the planner is told, since it
|
|
757
|
-
* decides whether tasks on the same file have to be ordered and which shared
|
|
758
|
-
* paths two tasks must not edit at once. A tree that would block counts as
|
|
759
|
-
* not isolating: the user may yet run without isolation, and ordering is
|
|
760
|
-
* the safe rule then.
|
|
761
|
-
*/
|
|
762
|
-
plannerLayout(): Promise<IsolatedExecution>;
|
|
763
|
-
/**
|
|
764
|
-
* Where the workspace's skills are read, and whether tasks get worktrees.
|
|
765
|
-
* Read synchronously inside a planner turn or a chip edit, so it comes from
|
|
766
|
-
* the files, not git or the planner's last layout: a restored session is
|
|
767
|
-
* right from its first edit. The run's repos while it isolates; otherwise
|
|
768
|
-
* the group the workspace holds, in worktrees unless isolation is off or
|
|
769
|
-
* this run chose to share the root.
|
|
770
|
-
*/
|
|
771
|
-
skillLayout(): SkillLayout;
|
|
772
|
-
/**
|
|
773
|
-
* Go on with the start a dirty tree turned away. `stash` puts the user's
|
|
774
|
-
* tracked changes on the git stash first, so the run isolates; `shared` runs
|
|
775
|
-
* this one run in the workspace root, knowingly. Returns the parked start for
|
|
776
|
-
* the caller to replay; null when nothing was parked.
|
|
777
|
-
*/
|
|
778
|
-
continueBlocked(how: 'stash' | 'shared'): Promise<(() => Promise<void>) | null>;
|
|
779
|
-
/**
|
|
780
|
-
* The working directory of an attempt that may run in a worktree — which
|
|
781
|
-
* attempts do is the attempt kind's to say (see `attemptKind.attemptCwd`):
|
|
782
|
-
* the worktree prepared for it in an isolated run, the kept one for a
|
|
783
|
-
* conflict repair, else the workspace root. `worktree` says which. Does not
|
|
784
|
-
* itself report a worktree it creates as a change — the caller does once
|
|
785
|
-
* the attempt is committed as running, so a spawn abandoned or failed after
|
|
786
|
-
* this settles is not misreported as a change that stuck.
|
|
787
|
-
*/
|
|
788
|
-
attemptCwd(task: Task, intent: AttemptIntent): Promise<AttemptWorkspace>;
|
|
789
|
-
/** The workspace root, for an attempt that runs outside any worktree. */
|
|
790
|
-
workspaceCwd(task: Task): Promise<{
|
|
791
|
-
cwd: string;
|
|
792
|
-
worktree: boolean;
|
|
793
|
-
}>;
|
|
794
|
-
private reopenCwd;
|
|
795
|
-
private prepareCwd;
|
|
479
|
+
isOps(taskId: string): boolean;
|
|
480
|
+
/** Every task's status and what it waits for, to tell cheaply whether one has changed since this was read. */
|
|
481
|
+
statusMark(): string;
|
|
482
|
+
/** A copy of the task tree, detached from the store: later status changes do not reach it. */
|
|
483
|
+
snapshot(): Task[];
|
|
484
|
+
getExecutionLog(): ReadonlyArray<TaskSnapshot>;
|
|
485
|
+
appendToLog(snapshot: TaskSnapshot): void;
|
|
796
486
|
/**
|
|
797
|
-
*
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
* settles. A git error is `failed`, never a throw.
|
|
487
|
+
* Drop a task's archived snapshot. Un-marking a completion has to erase the
|
|
488
|
+
* "finished" record too — dependent tasks are prompted from the log, so a
|
|
489
|
+
* left-behind snapshot would keep feeding them a result that no longer exists.
|
|
801
490
|
*/
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
491
|
+
removeFromLog(taskId: string): void;
|
|
492
|
+
clearLog(): void;
|
|
493
|
+
private notifyMutate;
|
|
494
|
+
private countStatus;
|
|
495
|
+
load(tasks: ReadonlyArray<Readonly<Task>>, runners: readonly RunnerId[]): void;
|
|
496
|
+
add(partial: Partial<Task>): Task;
|
|
497
|
+
remove(taskId: string): void;
|
|
498
|
+
update(taskId: string, changes: Partial<Task>): Task | undefined;
|
|
805
499
|
/**
|
|
806
|
-
*
|
|
807
|
-
*
|
|
808
|
-
* the
|
|
809
|
-
*
|
|
810
|
-
*
|
|
500
|
+
* Run preparation as one named op: flip every AI and script task to 'approved'. By
|
|
501
|
+
* default completed tasks keep their status so a reloaded half-finished plan
|
|
502
|
+
* resumes the remainder instead of re-running work that already succeeded,
|
|
503
|
+
* and skipped ones stay skipped: a new run is not a retry of them. A failed
|
|
504
|
+
* task gets its fresh chance here, not at a load (ADR-0053).
|
|
505
|
+
* `preserveCompleted: false` is for a freshly committed plan, where
|
|
506
|
+
* everything starts over. `edited` is an edit adopted between runs, which is
|
|
507
|
+
* not the user starting over: a failed task stays failed, and a task waiting
|
|
508
|
+
* on the user, whatever for, stays waiting. `keepFailed` is what failed in
|
|
509
|
+
* the reply autorun's run follows: nobody asked for those to run again.
|
|
811
510
|
*/
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
511
|
+
resetForRun(opts?: {
|
|
512
|
+
preserveCompleted?: boolean;
|
|
513
|
+
edited?: boolean;
|
|
514
|
+
keepFailed?: ReadonlySet<string>;
|
|
515
|
+
}): void;
|
|
815
516
|
/**
|
|
816
|
-
*
|
|
817
|
-
*
|
|
818
|
-
*
|
|
819
|
-
* is cleared up as a Merge all would have.
|
|
517
|
+
* Execute's fresh chance with work already live (ADR-0053), which
|
|
518
|
+
* `resetForRun` would take back: only what failed and is not at work is
|
|
519
|
+
* readied, and a check between rounds still leaves its body to run first.
|
|
820
520
|
*/
|
|
821
|
-
|
|
521
|
+
readyFailed(live: (taskId: string) => boolean): void;
|
|
522
|
+
/** See {@link releaseMadeManual}; `live` names what a runner still holds. */
|
|
523
|
+
releaseMadeManual(live?: (taskId: string) => boolean): void;
|
|
524
|
+
private ready;
|
|
525
|
+
/** A delegated task's checks; its scheduler, which knows what makes a task read-only, says which those are. */
|
|
526
|
+
checksOf: (task: Readonly<Task>) => readonly Task[];
|
|
527
|
+
markCompleted(id: string): void;
|
|
528
|
+
markFailed(id: string): void;
|
|
529
|
+
markSkipped(id: string, reason?: string): void;
|
|
530
|
+
markInProgress(id: string): void;
|
|
531
|
+
/** Its first attempt is starting: from now on its chat exists, whatever becomes of the attempt. */
|
|
532
|
+
markAttempted(id: string): void;
|
|
533
|
+
/** Its attempt starts: the number now tells its waits from the last attempt's, so they count from nothing (ADR-0053). */
|
|
534
|
+
markAttemptStarted(id: string): void;
|
|
535
|
+
/** Saved beside the wait it explains: see {@link Task.parkedQuestion}. */
|
|
536
|
+
parkQuestion(id: string, question: string): void;
|
|
537
|
+
markAwaitingUser(id: string, reason?: AwaitingReason): void;
|
|
538
|
+
/** When a task paused on a usage limit resumes on its own; undefined leaves it to a manual retry. */
|
|
539
|
+
setTaskResumeAt(id: string, resumeAt: string | undefined): void;
|
|
540
|
+
markPending(id: string): void;
|
|
822
541
|
/**
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
*
|
|
542
|
+
* A new attempt of the task, from nothing it earned. A loop's check starts
|
|
543
|
+
* its rounds over (ADR-0045 L7), unless `sameRound`: a resume after a usage
|
|
544
|
+
* limit goes on with the attempt the limit cut short.
|
|
826
545
|
*/
|
|
827
|
-
|
|
546
|
+
retry(id: string, opts?: {
|
|
547
|
+
sameRound?: boolean;
|
|
548
|
+
}): void;
|
|
828
549
|
/**
|
|
829
|
-
*
|
|
830
|
-
*
|
|
550
|
+
* A pass judged one result, and a new attempt of a delegated task makes
|
|
551
|
+
* another (ADR-0055 D8): its checks run again, whatever their status, their
|
|
552
|
+
* rounds starting over. A check not started yet has nothing to take back. The
|
|
553
|
+
* retries of every kind pass here; the claim asks for the starts that do not.
|
|
831
554
|
*/
|
|
832
|
-
|
|
833
|
-
/**
|
|
834
|
-
|
|
835
|
-
/**
|
|
836
|
-
|
|
555
|
+
takeBackChecks(id: string): void;
|
|
556
|
+
/** Its landed work was reverted (ADR-0054): as a retry leaves it, marked so until it starts. */
|
|
557
|
+
markReverted(id: string): void;
|
|
558
|
+
/** A loop's check counts its rounds afresh from its next run (ADR-0045 L7). */
|
|
559
|
+
startRoundsOver(id: string): void;
|
|
837
560
|
/**
|
|
838
|
-
* The
|
|
839
|
-
*
|
|
840
|
-
*
|
|
841
|
-
* workspace root, where every task's edits land in it, or a workspace git
|
|
842
|
-
* cannot isolate at all.
|
|
561
|
+
* The loop runs its check again, as its next round (ADR-0045 L5): a new
|
|
562
|
+
* attempt, the round counted on, and nothing of the round before kept on
|
|
563
|
+
* the task — its report went to the body, and stays in its attempt's log.
|
|
843
564
|
*/
|
|
844
|
-
|
|
845
|
-
/**
|
|
846
|
-
|
|
565
|
+
repeat(id: string): void;
|
|
566
|
+
/** Kept on the task: it was force-started past its merge gate, before these ancestors' work was merged (ADR-0020). */
|
|
567
|
+
setForcedPastGate(id: string, dependencies: string[]): void;
|
|
568
|
+
/** One of the task's waits is over, so what it waits on next is another (ADR-0053). */
|
|
569
|
+
endWait(id: string): void;
|
|
570
|
+
/** Work under way is the one status nobody could be waiting on, so moving off any other ends a wait. */
|
|
571
|
+
private leaveStatus;
|
|
572
|
+
/** A reason outlives nothing: any status but `awaiting_user` drops it, and the resume time with it; any status drops a skip's reason. */
|
|
573
|
+
private setStatus;
|
|
574
|
+
setTaskVerdict(id: string, verdict: Task['verdict']): void;
|
|
847
575
|
/**
|
|
848
|
-
*
|
|
849
|
-
*
|
|
576
|
+
* How the task's latest attempt ended, and the handoff it left (ADR-0047),
|
|
577
|
+
* kept as its digest. An attempt that left no handoff clears the one before
|
|
578
|
+
* it: the plan holds the latest attempt's, as it does the summary.
|
|
850
579
|
*/
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
580
|
+
setTaskOutputSummary(id: string, summary: Task['outputSummary'], handoff?: StoredHandoff): void;
|
|
581
|
+
/** The owner is saved with the session it belongs to, and dropped with it. */
|
|
582
|
+
setTaskRunnerSessionId(id: string, runnerSessionId: string | undefined, owner?: RunnerId): void;
|
|
583
|
+
setCarriedFrom(id: string, runner: RunnerId): void;
|
|
584
|
+
clearCarriedFrom(id: string): void;
|
|
585
|
+
startAttemptUsage(id: string, attempt: number, runner: string, startedAt: string): void;
|
|
586
|
+
recordAttemptUsage(id: string, attempt: number, record: UsageRecord, now: string): void;
|
|
587
|
+
endAttemptUsage(id: string, attempt: number, now: string, runnerSessionCost?: RunnerSessionCost, sessionId?: string): void;
|
|
588
|
+
setTaskAttemptSkills(id: string, skills: Task['attemptSkills']): void;
|
|
854
589
|
/**
|
|
855
|
-
*
|
|
856
|
-
*
|
|
857
|
-
*
|
|
858
|
-
*
|
|
859
|
-
* at its word.
|
|
860
|
-
*/
|
|
861
|
-
linkResolver(resolverId: string, conflictedId: string): void;
|
|
862
|
-
/** The conflicted task a landed resolver was added for, forgotten as it is returned. */
|
|
863
|
-
takeResolver(resolverId: string): string | undefined;
|
|
864
|
-
taskDiff(taskId: string, options: TaskDiffRead): Promise<TaskDiffResult>;
|
|
865
|
-
reviewDiff(): Promise<string>;
|
|
866
|
-
/**
|
|
867
|
-
* "Merge all": the run's integration branches into whatever the user has
|
|
868
|
-
* checked out, in every repo or none. During a run it merges what has
|
|
869
|
-
* landed so far and the run goes on (ADR-0020): its branches stay for the
|
|
870
|
-
* tasks still to land. Once a settled run merged everything, it has nothing
|
|
871
|
-
* left to hand over, so it is cleared up and forgotten; a branch the user's
|
|
872
|
-
* HEAD somehow does not contain stays for the next run's sweep.
|
|
873
|
-
*/
|
|
874
|
-
merge(): Promise<IsolationMergeResult>;
|
|
875
|
-
/**
|
|
876
|
-
* Worktrees and task branches go; the integration branch and the record stay
|
|
877
|
-
* for review and merge. Refused while a task of the run is still live.
|
|
878
|
-
*/
|
|
879
|
-
cleanup(): Promise<void>;
|
|
880
|
-
/**
|
|
881
|
-
* The run and everything it made go, and the plan forgets it; the next run
|
|
882
|
-
* starts afresh. Refused while a task of the run is still live.
|
|
883
|
-
*/
|
|
884
|
-
discard(): Promise<void>;
|
|
885
|
-
/** The records of tasks still live, whose worktrees no clean-up of the whole run may take. */
|
|
886
|
-
private liveRecords;
|
|
887
|
-
private refuseWhileLive;
|
|
888
|
-
/**
|
|
889
|
-
* Clear a settled run up once everything it landed is merged — and only
|
|
890
|
-
* when nothing else is left in it: a live task, or a worktree holding work
|
|
891
|
-
* that never landed, keeps the whole run, worktrees and branches, rather
|
|
892
|
-
* than leaving that work to a deletion.
|
|
893
|
-
*/
|
|
894
|
-
private clearMerged;
|
|
895
|
-
/** The records that keep a settled run from being cleared up: live, or holding work that never landed. */
|
|
896
|
-
private holdouts;
|
|
897
|
-
/** The run's worktrees and merged branches go; false, said, when git would not let them. */
|
|
898
|
-
private discardMerged;
|
|
899
|
-
/** Say what a removal kept back instead of deleting: where the work went, or which worktree stayed. */
|
|
900
|
-
private report;
|
|
901
|
-
/** The run goes from the plan; `merged` names it as {@link mergedRun} when everything it landed was merged. */
|
|
902
|
-
private forget;
|
|
903
|
-
private assess;
|
|
904
|
-
private activate;
|
|
905
|
-
private begin;
|
|
906
|
-
/** What earlier runs left merged in the group goes; a failure here is worth a word, never a stopped run. */
|
|
907
|
-
private sweep;
|
|
908
|
-
/**
|
|
909
|
-
* The plan's run carries on while it still has any record: anything landed
|
|
910
|
-
* means a resumed plan's dependents must start from a tip that holds their
|
|
911
|
-
* predecessors' work, and anything held — a kept attempt, a conflict, a
|
|
912
|
-
* repair — is work the user may still want, which a fresh run's mint would
|
|
913
|
-
* delete. Only a run with no records at all is superseded.
|
|
914
|
-
*/
|
|
915
|
-
private continuableRun;
|
|
916
|
-
/**
|
|
917
|
-
* A run with no records at all holds only superseded attempts, so it goes —
|
|
918
|
-
* but its integration branch only where the user's HEAD contains it, as does
|
|
919
|
-
* that of a run that cannot be continued for another reason (it ran from a
|
|
920
|
-
* different workspace path): only the user gives landed work up.
|
|
921
|
-
*
|
|
922
|
-
* False when `interrupted` came while git was minting: a newer activation
|
|
923
|
-
* may be minting its own run, so this one is never installed over it, and
|
|
924
|
-
* is discarded rather than left as branches no record names.
|
|
590
|
+
* Widen the plan's runner set. Retargeting a task onto a runner the plan has
|
|
591
|
+
* not used before has to land here as well as on the plan state, or
|
|
592
|
+
* {@link resolveTaskRunner} reads the new runner as foreign and spawns the
|
|
593
|
+
* plan's first one instead.
|
|
925
594
|
*/
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
private
|
|
929
|
-
private tell;
|
|
595
|
+
admitRunner(runner: RunnerId): void;
|
|
596
|
+
resolveTaskRunner(task: Readonly<Task>): RunnerId;
|
|
597
|
+
private rebuild;
|
|
930
598
|
}
|
|
931
599
|
|
|
932
600
|
/** A continue the user asked for: their message, and the runner session it resumes (ADR-0018, K1). */
|
|
@@ -953,6 +621,9 @@ interface Continuation {
|
|
|
953
621
|
* - `carryOver`: a change task paused on `from`'s usage limit and moved to
|
|
954
622
|
* another runner (ADR-0018, U1). A fresh session — none can cross runners —
|
|
955
623
|
* in a worktree that starts from the paused attempt's work.
|
|
624
|
+
* - `delegated`: a delegated task's attempt, a child plan in its worktree
|
|
625
|
+
* (ADR-0055 D3). `readOnly` lands nothing, and its worktree goes as a
|
|
626
|
+
* read-only task's does.
|
|
956
627
|
*/
|
|
957
628
|
type AttemptKind = {
|
|
958
629
|
readonly kind: 'change';
|
|
@@ -969,13 +640,17 @@ type AttemptKind = {
|
|
|
969
640
|
} & Readonly<Continuation>) | {
|
|
970
641
|
readonly kind: 'carryOver';
|
|
971
642
|
readonly from: RunnerId;
|
|
643
|
+
} | {
|
|
644
|
+
readonly kind: 'delegated';
|
|
645
|
+
readonly readOnly: boolean;
|
|
972
646
|
};
|
|
973
647
|
/**
|
|
974
648
|
* What a task's work is, whichever attempt does it: a change that lands, an
|
|
975
649
|
* ops task's effects from the checkout (ADR-0020), or a read-only task's,
|
|
976
|
-
* which lands nothing (ADR-0046)
|
|
650
|
+
* which lands nothing (ADR-0046), or a child plan's (ADR-0055), which lands
|
|
651
|
+
* unless it is read-only.
|
|
977
652
|
*/
|
|
978
|
-
type TaskWork = 'change' | 'ops' | 'readOnly';
|
|
653
|
+
type TaskWork = 'change' | 'ops' | 'readOnly' | 'delegated' | 'delegatedReadOnly';
|
|
979
654
|
|
|
980
655
|
/** Which repair of a task an attempt is, of the most `conflictRepairAttempts` allows. */
|
|
981
656
|
interface RepairAttempt {
|
|
@@ -1027,6 +702,8 @@ interface LandingDeps {
|
|
|
1027
702
|
tasks: Pick<PlanStore, 'get' | 'planTasks'>;
|
|
1028
703
|
/** Whether a repair merge's message ends with the Planned-with trailer; read as the prompt is built. */
|
|
1029
704
|
plannedWith?: () => boolean;
|
|
705
|
+
/** What this node's ancestors protect, which accumulates down a tree (ADR-0056 M4). */
|
|
706
|
+
inheritedProtectedPaths?: () => readonly string[];
|
|
1030
707
|
}
|
|
1031
708
|
/**
|
|
1032
709
|
* Landing and Conflict repair (ADR-0013, ADR-0014, ADR-0015): a passed
|
|
@@ -1043,6 +720,7 @@ declare class Landing {
|
|
|
1043
720
|
private readonly config;
|
|
1044
721
|
private readonly tasks;
|
|
1045
722
|
private readonly plannedWith;
|
|
723
|
+
private readonly inheritedProtectedPaths;
|
|
1046
724
|
constructor(deps: LandingDeps);
|
|
1047
725
|
/**
|
|
1048
726
|
* Land a passed attempt's work. One whose worktree has no unlanded record
|
|
@@ -1067,6 +745,9 @@ declare class Landing {
|
|
|
1067
745
|
* must not bring it in anyway.
|
|
1068
746
|
*/
|
|
1069
747
|
settleRepair(task: Task, verdict: Verdict, current: () => boolean): Promise<LandingOutcome>;
|
|
748
|
+
/** A repair lands after the verdict that held the work to its protected paths, so it is held to them here (ADR-0055 D7, D14). */
|
|
749
|
+
private protectedPathsTouched;
|
|
750
|
+
private protectedPaths;
|
|
1070
751
|
/** A repair that ended without landing leaves the task as its conflict did: waiting on the user, worktree and refs kept. */
|
|
1071
752
|
unrepaired(task: Task, why: string): Promise<Extract<LandingOutcome, {
|
|
1072
753
|
kind: 'awaiting_user';
|
|
@@ -1085,8 +766,18 @@ declare class Landing {
|
|
|
1085
766
|
outcome: Promise<LandingOutcome>;
|
|
1086
767
|
} | null;
|
|
1087
768
|
private landConflicted;
|
|
1088
|
-
/**
|
|
769
|
+
/**
|
|
770
|
+
* The repair a conflicted task is owed next; null when repair is off, used
|
|
771
|
+
* up, or there is no isolated run to repair it in. A resolver takes the
|
|
772
|
+
* conflict instead: a conflict has one worker (ADR-0015).
|
|
773
|
+
*/
|
|
1089
774
|
nextRepair(taskId: string): RepairAttempt | null;
|
|
775
|
+
/**
|
|
776
|
+
* The tasks in the plan still out to resolve this task's conflict. A skipped
|
|
777
|
+
* one has been given up, and a link to one that left the plan points at
|
|
778
|
+
* nothing, so either leaves the conflict free for another worker.
|
|
779
|
+
*/
|
|
780
|
+
liveResolvers(taskId: string): Readonly<Task>[];
|
|
1090
781
|
/** What a repair is asked to do; read once `reopen` has recorded the tips it must bring in. */
|
|
1091
782
|
repairPrompt(task: Task): string;
|
|
1092
783
|
private hasUnlandedWork;
|
|
@@ -1188,7 +879,9 @@ type TaskLogEvent =
|
|
|
1188
879
|
/**
|
|
1189
880
|
* A turn began by delivering `message`; `messageId` names it when it had been
|
|
1190
881
|
* queued, `forced` when it was force sent. `from` on this and the other
|
|
1191
|
-
* message events marks one Ordewell sent rather than the user.
|
|
882
|
+
* message events marks one Ordewell sent rather than the user. `startedAt`
|
|
883
|
+
* (ISO) is when it began, which a reload needs to date its open turn (#81);
|
|
884
|
+
* a log saved before it was kept has none.
|
|
1192
885
|
*/
|
|
1193
886
|
| {
|
|
1194
887
|
type: 'turn_start';
|
|
@@ -1196,6 +889,7 @@ type TaskLogEvent =
|
|
|
1196
889
|
messageId?: string;
|
|
1197
890
|
forced?: boolean;
|
|
1198
891
|
from?: TaskMessageFrom;
|
|
892
|
+
startedAt?: string;
|
|
1199
893
|
}
|
|
1200
894
|
/**
|
|
1201
895
|
* A turn began by running the runner's own command `/name args` (#66): the
|
|
@@ -1206,6 +900,7 @@ type TaskLogEvent =
|
|
|
1206
900
|
name: string;
|
|
1207
901
|
args?: string;
|
|
1208
902
|
messageId?: string;
|
|
903
|
+
startedAt?: string;
|
|
1209
904
|
}
|
|
1210
905
|
/** What the running command printed, for one that runs without the model. */
|
|
1211
906
|
| {
|
|
@@ -1444,7 +1139,56 @@ declare function scriptExitText(exit: Omit<Extract<TaskLogEvent, {
|
|
|
1444
1139
|
*/
|
|
1445
1140
|
declare function digestTaskLog(events: readonly TaskLogEvent[], maxCalls: number): string;
|
|
1446
1141
|
|
|
1447
|
-
/**
|
|
1142
|
+
/** One node as a tree's log names it (ADR-0058 S3). */
|
|
1143
|
+
interface SubtreeNode {
|
|
1144
|
+
path: NodePath;
|
|
1145
|
+
sessionId: string;
|
|
1146
|
+
/** The delegated task of the plan above it. */
|
|
1147
|
+
taskId?: string;
|
|
1148
|
+
}
|
|
1149
|
+
/** A plan of the tree, read afresh: its tasks, and the logs of its attempts. */
|
|
1150
|
+
interface NodePlan {
|
|
1151
|
+
node: NodePath;
|
|
1152
|
+
tasks: readonly Task[];
|
|
1153
|
+
logs: TaskLogReader;
|
|
1154
|
+
}
|
|
1155
|
+
interface SubtreeSource {
|
|
1156
|
+
/** The node reading: what is below it is what this reads. */
|
|
1157
|
+
here: NodePath;
|
|
1158
|
+
/** Every node ever opened below `here`, closed ones too: a reference outlives the child it names (ADR-0057 R1). */
|
|
1159
|
+
nodes(): readonly SubtreeNode[];
|
|
1160
|
+
/** What a node's session file holds of its plan, which is read only when asked for (ADR-0055 D17). */
|
|
1161
|
+
plan(node: SubtreeNode): readonly Task[] | undefined;
|
|
1162
|
+
logs(node: SubtreeNode): TaskLogReader;
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* The plans below one node, as a reference reads them (ADR-0057 R1): a
|
|
1166
|
+
* reader's reach goes down and never up, or sideways, so a child's tools see
|
|
1167
|
+
* nothing of the plan that holds its check (ADR-0055 D8).
|
|
1168
|
+
*/
|
|
1169
|
+
declare class Subtree {
|
|
1170
|
+
private readonly source;
|
|
1171
|
+
private readonly reach?;
|
|
1172
|
+
constructor(source: SubtreeSource, reach?: ReadonlySet<string> | undefined);
|
|
1173
|
+
/** What a task reads: only what hangs from a delegated task its readable set holds. */
|
|
1174
|
+
reachedBy(readable: ReadonlySet<string>): Subtree;
|
|
1175
|
+
private nodes;
|
|
1176
|
+
private planOf;
|
|
1177
|
+
/** Every plan below that has been saved, nearest first, each once: a Continue opens a new node for the same child and its one plan (ADR-0055 D17). */
|
|
1178
|
+
plans(): NodePlan[];
|
|
1179
|
+
/** The plan a pinned reference names, whichever of a child's nodes it was pinned against. */
|
|
1180
|
+
planAt(path: NodePath): NodePlan | undefined;
|
|
1181
|
+
/**
|
|
1182
|
+
* The plan a written path names. A report shows a path from the root and an
|
|
1183
|
+
* author writes one from its own plan, so a path that starts at this node
|
|
1184
|
+
* and goes on is read as shown; anything else is read from here.
|
|
1185
|
+
*/
|
|
1186
|
+
at(path: string): NodePlan | undefined;
|
|
1187
|
+
/** The same as a reference is pinned against it. */
|
|
1188
|
+
readonly below: (path: string) => BelowPlan | undefined;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
/** The session's saved task logs, as `read` reads them (ADR-0018, P1). */
|
|
1448
1192
|
interface TaskLogReader {
|
|
1449
1193
|
/** The attempts of a task that have a saved log, oldest first. */
|
|
1450
1194
|
attempts(taskId: string): number[];
|
|
@@ -1453,6 +1197,264 @@ interface TaskLogReader {
|
|
|
1453
1197
|
patch?(taskId: string, attempt: number): Buffer | undefined;
|
|
1454
1198
|
}
|
|
1455
1199
|
|
|
1200
|
+
/** Where the board's `file` evidence is compared (ADR-0057 R9). */
|
|
1201
|
+
interface BoardGit {
|
|
1202
|
+
/** The branch this node's plan lands on; undefined with no run yet. */
|
|
1203
|
+
branch(): string | undefined;
|
|
1204
|
+
/** The blob `file` holds on `branch`: null where it holds none, undefined where the branch cannot be read. */
|
|
1205
|
+
blob(branch: string, file: string): Promise<string | null | undefined>;
|
|
1206
|
+
}
|
|
1207
|
+
/** The log's side of a board. */
|
|
1208
|
+
interface BoardLog {
|
|
1209
|
+
post(node: NodePath, draft: BoardDraft): BoardEntry | null;
|
|
1210
|
+
board(node: NodePath): readonly BoardEntry[];
|
|
1211
|
+
}
|
|
1212
|
+
interface NodeBoardDeps {
|
|
1213
|
+
log: BoardLog;
|
|
1214
|
+
node: NodePath;
|
|
1215
|
+
git: BoardGit;
|
|
1216
|
+
/** What this plan's checks read and run: what no pin may hold (R10). */
|
|
1217
|
+
checks?(): readonly CheckWord[];
|
|
1218
|
+
}
|
|
1219
|
+
/** The blob of a file where its author works, as git would name it; undefined for what cannot be read, which goes unpinned. */
|
|
1220
|
+
type WorkBlobs = (file: string) => Promise<string | undefined>;
|
|
1221
|
+
/**
|
|
1222
|
+
* One node's view of the tree's boards (ADR-0057 R8 to R10): it posts to its
|
|
1223
|
+
* own, and reads that and its ancestors' by pull. Nothing here wakes or tells
|
|
1224
|
+
* anyone, so it is no channel between siblings (R7). What is stale or contested
|
|
1225
|
+
* is worked out here, as a reader asks, from what the log and git hold.
|
|
1226
|
+
*/
|
|
1227
|
+
declare class NodeBoard {
|
|
1228
|
+
private readonly deps;
|
|
1229
|
+
constructor(deps: NodeBoardDeps);
|
|
1230
|
+
get node(): NodePath;
|
|
1231
|
+
/** Nearest first: this node, then each ancestor. */
|
|
1232
|
+
private chain;
|
|
1233
|
+
private readable;
|
|
1234
|
+
/** The file evidence an entry pins, read now: what its author saw and what the branch held. */
|
|
1235
|
+
private pinned;
|
|
1236
|
+
/** Why this may not be posted, or null. */
|
|
1237
|
+
private refusal;
|
|
1238
|
+
/** `work` reads where the author works: its files are pinned from there (R9). */
|
|
1239
|
+
post(entry: BoardPost, by: Omit<BoardAuthor, 'node'>, work?: WorkBlobs): Promise<McpToolReply>;
|
|
1240
|
+
/** Whether a pinned file has moved past what its entry was written on. */
|
|
1241
|
+
private stale;
|
|
1242
|
+
private marked;
|
|
1243
|
+
/** `read` of `board`, or of one entry by its reference. */
|
|
1244
|
+
read(written: string): Promise<McpToolReply>;
|
|
1245
|
+
/** The pins a new descendant of this node is told (R10). */
|
|
1246
|
+
pins(): string[];
|
|
1247
|
+
/**
|
|
1248
|
+
* A delegated task's `contract`s for what it provides, onto this board as it
|
|
1249
|
+
* lands (R6), which is how a sibling reads them: a node reads its ancestors'
|
|
1250
|
+
* boards and never another's. Each keeps its author, and is read again against
|
|
1251
|
+
* the branch it has landed on. Only what the plan declared rises, and only once.
|
|
1252
|
+
*/
|
|
1253
|
+
raise(from: readonly BoardEntry[], provides: readonly string[]): Promise<void>;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
/** One node as the log leaves it. */
|
|
1257
|
+
interface TreeNode {
|
|
1258
|
+
path: NodePath;
|
|
1259
|
+
sessionId: string;
|
|
1260
|
+
taskId?: string;
|
|
1261
|
+
limit: number;
|
|
1262
|
+
/** What its open children hold. */
|
|
1263
|
+
committed: number;
|
|
1264
|
+
/** Its own, and what its closed children spent. */
|
|
1265
|
+
spent: number;
|
|
1266
|
+
/** The subplanner's share of `reserve`, held for its next turn. */
|
|
1267
|
+
kept: number;
|
|
1268
|
+
/** What raises gave it: a grant to its task, which outlives this node, so what a parent's turn takes back comes off `limit` and not off this (M5). */
|
|
1269
|
+
raised: number;
|
|
1270
|
+
open: boolean;
|
|
1271
|
+
/** Children it has ever opened: the next one's id. */
|
|
1272
|
+
opened: number;
|
|
1273
|
+
/** What was posted on its board, oldest first; absent on a node nothing was (ADR-0057 R8). */
|
|
1274
|
+
board?: BoardEntry[];
|
|
1275
|
+
}
|
|
1276
|
+
/** A node's four numbers (ADR-0056 M5). `spent + committed + reserve ≤ limit`, unless `spent` overshot, as nothing can recall a request. */
|
|
1277
|
+
interface BudgetNumbers {
|
|
1278
|
+
limit: number;
|
|
1279
|
+
committed: number;
|
|
1280
|
+
spent: number;
|
|
1281
|
+
reserve: number;
|
|
1282
|
+
}
|
|
1283
|
+
/** What a claim holds until its attempt ends. */
|
|
1284
|
+
interface BudgetHold {
|
|
1285
|
+
/** Idempotent. */
|
|
1286
|
+
release(): void;
|
|
1287
|
+
}
|
|
1288
|
+
type Carved = {
|
|
1289
|
+
ok: true;
|
|
1290
|
+
mandate: Mandate;
|
|
1291
|
+
budget: NodeBudget;
|
|
1292
|
+
} | {
|
|
1293
|
+
ok: false;
|
|
1294
|
+
refusal: MandateRefusal;
|
|
1295
|
+
};
|
|
1296
|
+
/** One node's side of the ledger, as a Session spends it. */
|
|
1297
|
+
interface NodeBudget {
|
|
1298
|
+
readonly path: NodePath;
|
|
1299
|
+
readonly sessionId: string;
|
|
1300
|
+
readonly tree: TreeLedger;
|
|
1301
|
+
/** Why a new session may not start here, or null. Changes nothing: a claim's refusal is also asked with no claim to follow. */
|
|
1302
|
+
refusal(): string | null;
|
|
1303
|
+
/** In the claim's synchronous step, so concurrent claims each see the last one's. */
|
|
1304
|
+
hold(): BudgetHold;
|
|
1305
|
+
spent(record: UsageRecord, on: {
|
|
1306
|
+
taskId: string;
|
|
1307
|
+
attempt: number;
|
|
1308
|
+
}): void;
|
|
1309
|
+
/** Why a subplanner's turn may not start, or null: that share, room and its children's room must come to one session. */
|
|
1310
|
+
turnRefusal(): string | null;
|
|
1311
|
+
turnSpent(record: UsageRecord): void;
|
|
1312
|
+
/** `child` asked this turn: it pays first for what the turn cannot (M5). */
|
|
1313
|
+
woken(child: NodePath): void;
|
|
1314
|
+
/** The turn ended: keep one session again, from room, then from the children's. */
|
|
1315
|
+
parked(): void;
|
|
1316
|
+
/** Nothing here can go on, for this reason. Said once, until a raise. */
|
|
1317
|
+
stop(why: string): void;
|
|
1318
|
+
/** Why it stopped, or null: what a parent reads to end it `blocked`. */
|
|
1319
|
+
stoppedFor(): string | null;
|
|
1320
|
+
/** Tell `listener` why, each time this node stops. Returns how to stop being told. */
|
|
1321
|
+
onStop(listener: (why: string) => void): () => void;
|
|
1322
|
+
/** Tell `listener` each time a raise takes: it only moves numbers, so what the node's Session starts again is its own. */
|
|
1323
|
+
onRaised(listener: () => void): void;
|
|
1324
|
+
}
|
|
1325
|
+
interface TreeLedgerOptions {
|
|
1326
|
+
/** {@link SESSION_RESERVE_TOKENS} unless a test works with smaller numbers. */
|
|
1327
|
+
sessionReserve?: number;
|
|
1328
|
+
/** The log refused a write. What it refused waits and goes with the next. */
|
|
1329
|
+
failed?: (err: unknown) => void;
|
|
1330
|
+
}
|
|
1331
|
+
/**
|
|
1332
|
+
* The budget ledger (ADR-0056 M5), the root's and shared down its tree. Every
|
|
1333
|
+
* read and decision is synchronous, as a claim is (ADR-0029); what is decided
|
|
1334
|
+
* goes to the log behind it, whole, in the order it was decided. Only budgets
|
|
1335
|
+
* are here: a child's mandate and what to spend it on are its Session's.
|
|
1336
|
+
*
|
|
1337
|
+
* What is live is held here and never logged: nothing is live after a restart.
|
|
1338
|
+
*/
|
|
1339
|
+
declare class TreeLedger {
|
|
1340
|
+
private readonly store;
|
|
1341
|
+
private readonly tree;
|
|
1342
|
+
private readonly reserve;
|
|
1343
|
+
private readonly failed;
|
|
1344
|
+
/** Sessions holding an allowance, by node. */
|
|
1345
|
+
private readonly live;
|
|
1346
|
+
/** Who pays first for the turn under way, by node. */
|
|
1347
|
+
private readonly wakers;
|
|
1348
|
+
private readonly listeners;
|
|
1349
|
+
private readonly raiseListeners;
|
|
1350
|
+
/** Why each stopped node did, which a raise clears (M5). */
|
|
1351
|
+
private readonly stopped;
|
|
1352
|
+
private pending;
|
|
1353
|
+
private writing;
|
|
1354
|
+
private failureSaid;
|
|
1355
|
+
private constructor();
|
|
1356
|
+
/** Rebuild from the log, and from nothing else (ADR-0058 S3). A log with no root gets one: this is the first carve of a tree. */
|
|
1357
|
+
static open(store: EventStore, root: {
|
|
1358
|
+
sessionId: string;
|
|
1359
|
+
limit: number;
|
|
1360
|
+
}, options?: TreeLedgerOptions): Promise<TreeLedger>;
|
|
1361
|
+
private write;
|
|
1362
|
+
/** What one step decides lands as one batch: the first await lets the step finish. */
|
|
1363
|
+
private flush;
|
|
1364
|
+
/** Everything decided so far has been offered to the log. */
|
|
1365
|
+
flushed(): Promise<void>;
|
|
1366
|
+
/** The Session holding the tree is closing. */
|
|
1367
|
+
shutdown(): Promise<void>;
|
|
1368
|
+
private at;
|
|
1369
|
+
private liveReserve;
|
|
1370
|
+
/** What `limit` leaves once its node's spending and children are paid: its reserve and room. */
|
|
1371
|
+
private free;
|
|
1372
|
+
private room;
|
|
1373
|
+
/**
|
|
1374
|
+
* What a claim can take. A turn spends its subplanner's share down until it
|
|
1375
|
+
* parks, and a claim comes at that turn's end: read as it stands, the share
|
|
1376
|
+
* would pay for the claim, and the turn that follows the work would find
|
|
1377
|
+
* nothing and could not report it.
|
|
1378
|
+
*/
|
|
1379
|
+
private claimRoom;
|
|
1380
|
+
numbers(path: NodePath): BudgetNumbers;
|
|
1381
|
+
/** What a node can still carve or claim: `limit` less the other three. What `narrow` is handed as the parent's tokens (M4). */
|
|
1382
|
+
left(path: NodePath): number;
|
|
1383
|
+
node(path: NodePath): NodeBudget;
|
|
1384
|
+
/** Every node ever opened under `path`, closed ones too, nearest first: a reference outlives the child it names (ADR-0057 R1). */
|
|
1385
|
+
below(path: NodePath): TreeNode[];
|
|
1386
|
+
/**
|
|
1387
|
+
* A node's board, every opening of one child's together: a Continue opens a
|
|
1388
|
+
* new node for the same child and its one plan (ADR-0055 D17).
|
|
1389
|
+
*/
|
|
1390
|
+
board(path: NodePath): readonly BoardEntry[];
|
|
1391
|
+
/** One child's board, closed or not: a fresh retry is a new child with a board of its own (ADR-0055 D15). */
|
|
1392
|
+
boardOf(sessionId: string): readonly BoardEntry[];
|
|
1393
|
+
/** Put an entry on `path`'s board, or null where that board is full. */
|
|
1394
|
+
post(path: NodePath, draft: BoardDraft): BoardEntry | null;
|
|
1395
|
+
/** What `path` and everything under it spent: a closed child is in its parent's `spent`, an open one still its own (M5). */
|
|
1396
|
+
subtreeSpent(path: NodePath): number;
|
|
1397
|
+
/** What a node's task has cost so far: this opening's subtree and every opening before it, since a report of the last alone reads as the whole (ADR-0056 M10). */
|
|
1398
|
+
taskSpent(path: NodePath): number;
|
|
1399
|
+
/** The open node `sessionId` is, if any: what a reopen finds. */
|
|
1400
|
+
nodeOf(sessionId: string): NodeBudget | undefined;
|
|
1401
|
+
/** What every child `parent` opened for `taskId` has spent, closed ones included: a retry's budget is what they left (ADR-0056 M10). */
|
|
1402
|
+
spentOn(parent: NodePath, taskId: string): number;
|
|
1403
|
+
/** What raises gave every child `parent` opened for `taskId`: the tree granted it to the task, on top of its stated budget (ADR-0056 M5, M10). */
|
|
1404
|
+
raisedOn(parent: NodePath, taskId: string): number;
|
|
1405
|
+
private childrenFor;
|
|
1406
|
+
/** Close the children of `parent` that `gone` picks by their task: no session is live in them, so what they hold would stay committed for good. */
|
|
1407
|
+
closeChildren(parent: NodePath, gone: (taskId: string | undefined) => boolean): void;
|
|
1408
|
+
private hold;
|
|
1409
|
+
private openChildren;
|
|
1410
|
+
/** What a turn can reach: what its node has beside its live sessions, and its children's room. */
|
|
1411
|
+
private turnCover;
|
|
1412
|
+
/**
|
|
1413
|
+
* A child's mandate, carved from what `parent` has left (ADR-0056 M4, M5). One
|
|
1414
|
+
* synchronous step, so no second carve can read the same room.
|
|
1415
|
+
*/
|
|
1416
|
+
carve(parent: NodePath, mandate: Mandate, request: MandateRequest, child: {
|
|
1417
|
+
sessionId: string;
|
|
1418
|
+
taskId: string;
|
|
1419
|
+
}): Carved;
|
|
1420
|
+
/**
|
|
1421
|
+
* A raise, for the parent's answer to a checkpoint to apply (M5): from what
|
|
1422
|
+
* the parent has left, the child's limit and the parent's `committed` rising
|
|
1423
|
+
* together. Null when it took; otherwise why not.
|
|
1424
|
+
*/
|
|
1425
|
+
raise(path: NodePath, tokens: number): string | null;
|
|
1426
|
+
/** Where the user keeps the tree's budget (ADR-0056 M5), read as a carve or a raise is asked for. */
|
|
1427
|
+
setRootLimit(limit: number): void;
|
|
1428
|
+
/**
|
|
1429
|
+
* A child ended, on confirmed close: what it did not spend returns to its
|
|
1430
|
+
* parent and goes no further (M5), so a sibling gets it only by the parent's
|
|
1431
|
+
* next carve. What is still open under it closes first, in the same step.
|
|
1432
|
+
*/
|
|
1433
|
+
close(path: NodePath): void;
|
|
1434
|
+
private closeUnder;
|
|
1435
|
+
private nearestOpen;
|
|
1436
|
+
private spend;
|
|
1437
|
+
/**
|
|
1438
|
+
* A call's usage arrives with the next already sent, and nothing recalls a
|
|
1439
|
+
* request, so a node that stopped at its limit would always pass it, by a call
|
|
1440
|
+
* or more. It stops while what it can reach still pays for what is on its way:
|
|
1441
|
+
* the next call of each live session and the one after, each the size of the
|
|
1442
|
+
* one just reported, which a long context only grows from. An estimate, never
|
|
1443
|
+
* more than the reserve that is held for it. No live session means a runner
|
|
1444
|
+
* winding down, with no call to follow.
|
|
1445
|
+
*/
|
|
1446
|
+
private stopShortOfLimit;
|
|
1447
|
+
/** Past what it can pay, a node's spending takes its children's room; with none left it is out. */
|
|
1448
|
+
private settle;
|
|
1449
|
+
/** Take up to `short` of the children's room, the child that woke the turn first and then the oldest. Returns what it took. */
|
|
1450
|
+
private takeFromChildren;
|
|
1451
|
+
private park;
|
|
1452
|
+
private spentOut;
|
|
1453
|
+
private stopNode;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
/** Where a start stands against the user's Stop (ADR-0029): no longer current once one comes. */
|
|
1457
|
+
type Admitted = Pick<StartAdmission, 'current'>;
|
|
1456
1458
|
type AttemptPhase = 'starting' | 'running' | 'integrating';
|
|
1457
1459
|
/** Read-only view of a task's live attempt. */
|
|
1458
1460
|
interface TaskAttemptSnapshot {
|
|
@@ -1478,9 +1480,10 @@ type StartWait =
|
|
|
1478
1480
|
kind: 'started';
|
|
1479
1481
|
}
|
|
1480
1482
|
/**
|
|
1481
|
-
* A loop's check between rounds (ADR-0045 L3):
|
|
1482
|
-
*
|
|
1483
|
-
*
|
|
1483
|
+
* A loop's check between rounds (ADR-0045 L3): it runs again, as round
|
|
1484
|
+
* `round` of `maxRounds`, once its body has passed and landed; `waiting` is
|
|
1485
|
+
* the body that has not yet. Whether anything will run it then is no part
|
|
1486
|
+
* of the rule: a Stop or a reload leaves that to a start of it (L5).
|
|
1484
1487
|
*/
|
|
1485
1488
|
| {
|
|
1486
1489
|
kind: 'repeating';
|
|
@@ -1492,6 +1495,11 @@ type StartWait =
|
|
|
1492
1495
|
| {
|
|
1493
1496
|
kind: 'completing';
|
|
1494
1497
|
}
|
|
1498
|
+
/** A task added to resolve its conflict has it: a conflict has one worker (ADR-0015). */
|
|
1499
|
+
| {
|
|
1500
|
+
kind: 'resolver';
|
|
1501
|
+
resolver: string;
|
|
1502
|
+
}
|
|
1495
1503
|
/** An AI task with no prompt yet, or a script task with no body to run: there is nothing to run. */
|
|
1496
1504
|
| {
|
|
1497
1505
|
kind: 'no-prompt';
|
|
@@ -1538,6 +1546,11 @@ type StartWait =
|
|
|
1538
1546
|
| {
|
|
1539
1547
|
kind: 'start-hold';
|
|
1540
1548
|
}
|
|
1549
|
+
/** A delegated task's check is running: its fresh attempt takes that check back, so it waits for it to end (ADR-0055 D8). */
|
|
1550
|
+
| {
|
|
1551
|
+
kind: 'check-running';
|
|
1552
|
+
check: string;
|
|
1553
|
+
}
|
|
1541
1554
|
/** Its merge gate (ADR-0020): the ancestors whose landed work is not in the user's branch yet. */
|
|
1542
1555
|
| {
|
|
1543
1556
|
kind: 'merge-gate';
|
|
@@ -1554,15 +1567,44 @@ type StartWait =
|
|
|
1554
1567
|
* and goes past the whole gate and a planner turn's start hold. Queued behind
|
|
1555
1568
|
* its dependencies, it starts later with nobody asking, so it waits for a
|
|
1556
1569
|
* start hold as the scheduler's starts do, and goes past only the gate it was
|
|
1557
|
-
* confirmed past: `pastGate`.
|
|
1570
|
+
* confirmed past: `pastGate`. `asScheduled` is one the start rule has already
|
|
1571
|
+
* passed whole, carried back to the queue if it has to wait again.
|
|
1558
1572
|
*/
|
|
1559
1573
|
type ForcedStart = {
|
|
1560
1574
|
queued: false;
|
|
1561
1575
|
} | {
|
|
1562
1576
|
queued: true;
|
|
1563
1577
|
pastGate: readonly string[];
|
|
1578
|
+
asScheduled?: true;
|
|
1564
1579
|
};
|
|
1565
1580
|
|
|
1581
|
+
type RevertRefusalReason = 'no-landing' | 'no-own-merge' | 'checked-out' | 'in-a-loop' | 'live-dependent' | 'in-branch' | 'git';
|
|
1582
|
+
interface RevertRefusal {
|
|
1583
|
+
reason: RevertRefusalReason;
|
|
1584
|
+
message: string;
|
|
1585
|
+
/** `live-dependent`: the tasks in the way. */
|
|
1586
|
+
tasks?: IsolationTaskRef[];
|
|
1587
|
+
/** `in-branch`: what undoes the work there, newest first, for the user to run. */
|
|
1588
|
+
commands?: RevertCommand[];
|
|
1589
|
+
}
|
|
1590
|
+
/** The tasks a revert would take, the one asked for first; `refusal` says why it may not go ahead, and with no landing there is nothing to take. */
|
|
1591
|
+
interface RevertScope {
|
|
1592
|
+
taskIds: string[];
|
|
1593
|
+
refusal?: RevertRefusal;
|
|
1594
|
+
}
|
|
1595
|
+
/** A task a preview lists; `dependent` is one that goes with the task the user chose, and `ref` how the plan calls it, a subtask's full path. */
|
|
1596
|
+
interface RevertPreviewTask extends IsolationRevertTask {
|
|
1597
|
+
dependent: boolean;
|
|
1598
|
+
ref?: string;
|
|
1599
|
+
}
|
|
1600
|
+
/** What a revert would do now, for a surface to confirm with the user before anything changes. */
|
|
1601
|
+
type TaskRevertPreview = {
|
|
1602
|
+
revertible: true;
|
|
1603
|
+
tasks: RevertPreviewTask[];
|
|
1604
|
+
} | ({
|
|
1605
|
+
revertible: false;
|
|
1606
|
+
} & RevertRefusal);
|
|
1607
|
+
|
|
1566
1608
|
/** One reported window: what share of it is used, how long it is, and when it resets. */
|
|
1567
1609
|
interface AccountLimitWindow {
|
|
1568
1610
|
/** Which of a bucket's windows this is, in the order reported; only a label when the length is unknown. */
|
|
@@ -1621,16 +1663,190 @@ declare function accountLimitWindowLabel(window: AccountLimitWindow): string;
|
|
|
1621
1663
|
/** `24% used`, `<1% used` for a sliver, `0% used` only when the runner said 0. */
|
|
1622
1664
|
declare function accountLimitPercentText(percent: number): string;
|
|
1623
1665
|
/**
|
|
1624
|
-
* The compact row: `Codex 5h 24% used · Weekly 61% used`, with any other
|
|
1625
|
-
* bucket after its own name, and `(stale)` when the read is not current.
|
|
1626
|
-
* Null when there is nothing known to draw.
|
|
1627
|
-
*/
|
|
1628
|
-
declare function accountLimitsText(snapshot: AccountLimitSnapshot): string | null;
|
|
1666
|
+
* The compact row: `Codex 5h 24% used · Weekly 61% used`, with any other
|
|
1667
|
+
* bucket after its own name, and `(stale)` when the read is not current.
|
|
1668
|
+
* Null when there is nothing known to draw.
|
|
1669
|
+
*/
|
|
1670
|
+
declare function accountLimitsText(snapshot: AccountLimitSnapshot): string | null;
|
|
1671
|
+
/**
|
|
1672
|
+
* The row's hover: each window's exact share and reset, the plan, and how
|
|
1673
|
+
* current the read is. `time` words an instant in the reader's clock.
|
|
1674
|
+
*/
|
|
1675
|
+
declare function accountLimitsTitle(snapshot: AccountLimitSnapshot, time: (at: Date) => string): string;
|
|
1676
|
+
|
|
1677
|
+
/**
|
|
1678
|
+
* The bridge between "core needs an answer" and "a human somewhere is looking
|
|
1679
|
+
* at a UI". Core cannot prompt: the human may be at a browser, a TUI, a CLI
|
|
1680
|
+
* stream, or a VS Code webview, and on the web server they are on the far end
|
|
1681
|
+
* of a socket. So the Session parks a promise here, announces the request
|
|
1682
|
+
* through the normal broadcast seam, and every surface answers through the
|
|
1683
|
+
* same `resolve(id, granted)` call.
|
|
1684
|
+
*
|
|
1685
|
+
* Timeouts are load-bearing rather than defensive: a planner turn that blocks
|
|
1686
|
+
* forever on an unanswered prompt would hang the whole research loop with no
|
|
1687
|
+
* visible cause. On expiry the request resolves to denied and the model gets a
|
|
1688
|
+
* normal, actionable tool result. A task runner's request is the exception
|
|
1689
|
+
* (ADR-0018, A1): the runner is parked on it rather than a research loop, and
|
|
1690
|
+
* it waits for a person — or the supervisor — however long that takes.
|
|
1691
|
+
*/
|
|
1692
|
+
interface PendingApproval {
|
|
1693
|
+
id: string;
|
|
1694
|
+
request: ApprovalRequest;
|
|
1695
|
+
createdAt: string;
|
|
1696
|
+
}
|
|
1697
|
+
interface PendingApprovalsOptions {
|
|
1698
|
+
/** Denies and resolves after this long with no answer. Default 5 minutes. */
|
|
1699
|
+
timeoutMs?: number;
|
|
1700
|
+
/** Announce a new request to the surfaces. */
|
|
1701
|
+
onRequest?: (pending: PendingApproval) => void;
|
|
1702
|
+
/** Announce that a request is no longer actionable (answered or expired). */
|
|
1703
|
+
onSettled?: (id: string, granted: boolean, settled: {
|
|
1704
|
+
request: ApprovalRequest;
|
|
1705
|
+
decision: ApprovalDecision;
|
|
1706
|
+
}) => void;
|
|
1707
|
+
}
|
|
1708
|
+
interface AskOptions {
|
|
1709
|
+
/**
|
|
1710
|
+
* An id the caller already announced the request under. One still in use is
|
|
1711
|
+
* refused — denied at once — rather than overwriting the request that has it.
|
|
1712
|
+
*/
|
|
1713
|
+
id?: string;
|
|
1714
|
+
/** Wait for an answer however long it takes. */
|
|
1715
|
+
noTimeout?: boolean;
|
|
1716
|
+
/**
|
|
1717
|
+
* Given the answer as the request settles, before anything awaiting the
|
|
1718
|
+
* promise runs: a caller about to tear down what asked (a runner being
|
|
1719
|
+
* stopped) must deliver the answer before it goes.
|
|
1720
|
+
*/
|
|
1721
|
+
onDecision?: (decision: ApprovalDecision) => void;
|
|
1722
|
+
}
|
|
1723
|
+
declare class PendingApprovals {
|
|
1724
|
+
private readonly opts;
|
|
1725
|
+
private readonly entries;
|
|
1726
|
+
private readonly listeners;
|
|
1727
|
+
constructor(opts?: PendingApprovalsOptions);
|
|
1728
|
+
/** Hear each new request once it is announced — the supervisor wakes on a runner's (ADR-0029). */
|
|
1729
|
+
listen(listener: (pending: PendingApproval) => void): () => void;
|
|
1730
|
+
/** Park a request and return the promise the approval policy awaits. */
|
|
1731
|
+
ask(request: ApprovalRequest, options?: AskOptions): Promise<boolean>;
|
|
1732
|
+
/** Park a request whose answer is more than yes or no. */
|
|
1733
|
+
decide(request: ApprovalRequest, options?: AskOptions): Promise<ApprovalDecision>;
|
|
1734
|
+
/**
|
|
1735
|
+
* Answer one request. Returns false when the id is unknown or already
|
|
1736
|
+
* settled. "Allow for this task" on a request that did not offer it is a
|
|
1737
|
+
* plain allow: no grant is made that the requester never proposed.
|
|
1738
|
+
*/
|
|
1739
|
+
resolve(id: string, answer: ApprovalAnswer): boolean;
|
|
1740
|
+
/** Everything still awaiting an answer — replayed to a surface that connects late. */
|
|
1741
|
+
outstanding(): PendingApproval[];
|
|
1742
|
+
/**
|
|
1743
|
+
* Deny everything in flight, or only the requests `which` picks. Called on
|
|
1744
|
+
* abort and on session reset.
|
|
1745
|
+
*/
|
|
1746
|
+
clear(which?: (request: ApprovalRequest) => boolean, note?: string): void;
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
/**
|
|
1750
|
+
* What an escalation waits on (ADR-0053). `approval`, `checkpoint`, `input`,
|
|
1751
|
+
* `conflict`, `files-changed` and `usage-limit` are a task's wait; `failed` and
|
|
1752
|
+
* `out-of-rounds` its end; `merge-gate`, `unapproved`, `on-hold`, `no-prompt`
|
|
1753
|
+
* and `by-hand` what alone keeps a task from starting; `merge-all` and
|
|
1754
|
+
* `blocked-run` are the run's own.
|
|
1755
|
+
*/
|
|
1756
|
+
type EscalationKind = 'approval' | 'checkpoint' | 'input' | 'conflict' | 'files-changed' | 'usage-limit' | 'failed' | 'out-of-rounds' | 'merge-gate' | 'unapproved' | 'on-hold' | 'no-prompt' | 'by-hand' | 'merge-all' | 'blocked-run';
|
|
1757
|
+
type EscalationOptionId = 'allow' | 'allow-for-task' | 'deny' | 'approve' | 'reject' | 'reply' | 'resume' | 'continue' | 'retry' | 'run' | 'force-start' | 'skip' | 'complete' | 'merge-all' | 'resolve-conflict' | 'start-resolver' | 'stash' | 'run-without-isolation';
|
|
1758
|
+
/** One answer the user may give: what the wait's own card or command offers. */
|
|
1759
|
+
interface EscalationOption {
|
|
1760
|
+
id: EscalationOptionId;
|
|
1761
|
+
label: string;
|
|
1762
|
+
/** What this answer does with a note; absent when it takes none. */
|
|
1763
|
+
note?: 'optional' | 'required';
|
|
1764
|
+
/** The question a surface asks first, as it does on the card; the answer then carries the user's yes. */
|
|
1765
|
+
confirm?: string;
|
|
1766
|
+
}
|
|
1629
1767
|
/**
|
|
1630
|
-
*
|
|
1631
|
-
*
|
|
1768
|
+
* One thing the run waits on a person for, derived and never stored
|
|
1769
|
+
* (ADR-0053). No deadline and no default answer: answering for the user on a
|
|
1770
|
+
* timer is a consent decision, which belongs to the mandate (#23).
|
|
1632
1771
|
*/
|
|
1633
|
-
|
|
1772
|
+
interface Escalation {
|
|
1773
|
+
/**
|
|
1774
|
+
* Kind, task and attempt, then the approval, what a merge gate waits to have
|
|
1775
|
+
* merged, and how many of the attempt's waits ended before it; for Merge all,
|
|
1776
|
+
* the run and the attempts it would merge. A later wait is another
|
|
1777
|
+
* escalation, so a stale answer is told from a live one.
|
|
1778
|
+
*/
|
|
1779
|
+
id: string;
|
|
1780
|
+
kind: EscalationKind;
|
|
1781
|
+
/** The task it belongs to, the link to its evidence; absent on the run's own. */
|
|
1782
|
+
task?: {
|
|
1783
|
+
id: string;
|
|
1784
|
+
ref: string;
|
|
1785
|
+
title: string;
|
|
1786
|
+
};
|
|
1787
|
+
/** The attempt it was raised in; absent before any ran. */
|
|
1788
|
+
attempt?: number;
|
|
1789
|
+
/** The runner request it answers, for `approval`. */
|
|
1790
|
+
approval?: string;
|
|
1791
|
+
/** The task out to resolve it, for a `conflict` nothing is starting that task for. */
|
|
1792
|
+
resolver?: string;
|
|
1793
|
+
reason: string;
|
|
1794
|
+
options: EscalationOption[];
|
|
1795
|
+
}
|
|
1796
|
+
/** What the list reads of the run. */
|
|
1797
|
+
interface EscalationRun {
|
|
1798
|
+
/** A full-plan run is scheduling, held, or ended on a failure a retry continues: only then, or in a carried loop, does a task that has not started wait on anyone, a reverted one apart. */
|
|
1799
|
+
open: boolean;
|
|
1800
|
+
/** Something could move a task on unasked, so the seam refuses a Mark complete (ADR-0029). */
|
|
1801
|
+
advancing: boolean;
|
|
1802
|
+
/** A Merge all is under way. */
|
|
1803
|
+
merging: boolean;
|
|
1804
|
+
/** Ordewell merges at gates by itself: the setting is on, and no merge has stopped it. */
|
|
1805
|
+
autoMerges: boolean;
|
|
1806
|
+
/** The run's close merges what landed by itself, so nobody has to; a Stop or a merge that stopped ends this, and the wait is real. */
|
|
1807
|
+
mergesAtClose: boolean;
|
|
1808
|
+
/** What Merge all would merge now. */
|
|
1809
|
+
merge: RunMergeView | null;
|
|
1810
|
+
/** The checks that have not passed work Merge all would merge (ADR-0055 D9): the user's is not held, and its confirmation names them. */
|
|
1811
|
+
mergeHold: readonly string[];
|
|
1812
|
+
/** The isolated run's id. */
|
|
1813
|
+
id: string | null;
|
|
1814
|
+
/** Which of the session's starts a dirty checkout turned away, when one waits on it; null when none does. */
|
|
1815
|
+
blocked: number | null;
|
|
1816
|
+
}
|
|
1817
|
+
/** What the list is derived from: nothing here is kept for it. */
|
|
1818
|
+
interface EscalationInput {
|
|
1819
|
+
/** The plan tree. */
|
|
1820
|
+
tasks: readonly Task[];
|
|
1821
|
+
/** Every task's start waits; see `planStartWaits`. */
|
|
1822
|
+
waits: ReadonlyMap<string, readonly StartWait[]>;
|
|
1823
|
+
approvals: readonly PendingApproval[];
|
|
1824
|
+
/** The task's latest attempt, 0 before any ran. */
|
|
1825
|
+
attempt: (task: Readonly<Task>) => number;
|
|
1826
|
+
/** An attempt of the task is live, so a runner is there to hear an answer. */
|
|
1827
|
+
live: (taskId: string) => boolean;
|
|
1828
|
+
/** What the task's waiting checkpoint asks, whole. */
|
|
1829
|
+
checkpoint: (taskId: string) => string | undefined;
|
|
1830
|
+
/** Added since the user approved the plan, and left for them (ADR-0035). */
|
|
1831
|
+
waitsForApproval: (taskId: string) => boolean;
|
|
1832
|
+
/** Queued to start with no scheduler, once what holds it clears. */
|
|
1833
|
+
startQueued: (taskId: string) => boolean;
|
|
1834
|
+
/** Why the task is on hold. */
|
|
1835
|
+
holdReason: (taskId: string) => string | null | undefined;
|
|
1836
|
+
/** Something will run this check between rounds without being asked (ADR-0045 L5). */
|
|
1837
|
+
loopRunsOn: (taskId: string) => boolean;
|
|
1838
|
+
/** A loop or a delegated task's check carried on with no scheduler starts this task, so the run is open for it alone (ADR-0045 L5, ADR-0055 D8). */
|
|
1839
|
+
carried: (taskId: string) => boolean;
|
|
1840
|
+
run: EscalationRun;
|
|
1841
|
+
}
|
|
1842
|
+
/**
|
|
1843
|
+
* Everything that will not move without a person (ADR-0053), in the order of
|
|
1844
|
+
* what stops the most first: a run that cannot start, then the plan's tasks in
|
|
1845
|
+
* order, then the work waiting to be merged. Pure and derived, as `planBlocks`
|
|
1846
|
+
* and `startWaits` are: nothing is stored, so nothing has to be cleared, and it
|
|
1847
|
+
* survives a reload as the waits it reads do.
|
|
1848
|
+
*/
|
|
1849
|
+
declare function escalations(input: EscalationInput): Escalation[];
|
|
1634
1850
|
|
|
1635
1851
|
type SerializedTaskStatus = {
|
|
1636
1852
|
id: string;
|
|
@@ -1695,6 +1911,8 @@ type SerializedTaskStatus = {
|
|
|
1695
1911
|
waitsForApproval?: true;
|
|
1696
1912
|
/** Why a task is held out of auto-scheduling, in the user's words; absent when it is not held. */
|
|
1697
1913
|
holdReason?: string;
|
|
1914
|
+
/** A loop's check between rounds that nothing will run, after a Stop or a reload (ADR-0045 L5). Absent for any other task. */
|
|
1915
|
+
loopStranded?: true;
|
|
1698
1916
|
/** Set only on a research task, so a stream of statuses alone can say which task is one (ADR-0037). */
|
|
1699
1917
|
research?: true;
|
|
1700
1918
|
/** The latest attempt's handoff, as the plan keeps it (ADR-0047); absent when the attempt left none. */
|
|
@@ -1706,6 +1924,8 @@ type SerializedTaskStatus = {
|
|
|
1706
1924
|
loop?: TaskLoop;
|
|
1707
1925
|
/** The round a loop's check is in, past its first (ADR-0045 L5); absent on round 1 and on any other task. */
|
|
1708
1926
|
loopRound?: number;
|
|
1927
|
+
/** A delegated task's row: its child's tasks, what is left of its budget, a Stop still winding down (ADR-0055 D20); absent on any other task and when it has nothing to say. */
|
|
1928
|
+
delegation?: DelegatedRow;
|
|
1709
1929
|
};
|
|
1710
1930
|
/**
|
|
1711
1931
|
* Landed work not yet in the user's branch. `paused` means the running plan
|
|
@@ -1760,6 +1980,8 @@ type SerializedTask = {
|
|
|
1760
1980
|
loop?: TaskLoop;
|
|
1761
1981
|
/** As on {@link SerializedTaskStatus}: only on a loop's check past its first round. */
|
|
1762
1982
|
loopRound?: number;
|
|
1983
|
+
/** What a delegated task's child plan must achieve (ADR-0055 D1); absent on any other task. */
|
|
1984
|
+
goal?: string;
|
|
1763
1985
|
};
|
|
1764
1986
|
/** Skill loads go out as notices: their bodies are for the planner, and stay in the session. */
|
|
1765
1987
|
type SerializedConversationMessage = Omit<ConversationMessage, 'skill'> & {
|
|
@@ -1862,6 +2084,8 @@ type SessionMessage =
|
|
|
1862
2084
|
* digests the turn delivers, shown ahead of the prompt; `supervisor` marks a
|
|
1863
2085
|
* wake-up turn, which no user message opened (ADR-0029). `forced`: the
|
|
1864
2086
|
* prompt was force sent, and this turn replaces the one it stopped.
|
|
2087
|
+
* `startedAt` (ISO) is when it began, which a surface counts its elapsed
|
|
2088
|
+
* time from (#81); an older daemon sends none.
|
|
1865
2089
|
*/
|
|
1866
2090
|
| {
|
|
1867
2091
|
type: 'planner_turn_started';
|
|
@@ -1871,6 +2095,7 @@ type SessionMessage =
|
|
|
1871
2095
|
wakeUps?: string[];
|
|
1872
2096
|
supervisor?: true;
|
|
1873
2097
|
forced?: true;
|
|
2098
|
+
startedAt?: string;
|
|
1874
2099
|
} | {
|
|
1875
2100
|
type: 'planner_skill_loaded';
|
|
1876
2101
|
turnId: string;
|
|
@@ -1981,12 +2206,26 @@ type SessionMessage =
|
|
|
1981
2206
|
type: 'planner_compaction';
|
|
1982
2207
|
compaction: PlannerCompaction;
|
|
1983
2208
|
turnId?: string;
|
|
1984
|
-
}
|
|
2209
|
+
}
|
|
2210
|
+
/**
|
|
2211
|
+
* A planner turn waits for the probe of installed coding agents (ADR-0009),
|
|
2212
|
+
* or nothing does any longer. While `waiting`, no planner has heard of that
|
|
2213
|
+
* turn, so a surface says so rather than that it is planning. It ends with
|
|
2214
|
+
* the probe, whatever became of the turn: one stopped at the gate leaves it
|
|
2215
|
+
* `true` for the next to wait under.
|
|
2216
|
+
*/
|
|
2217
|
+
| {
|
|
2218
|
+
type: 'planner_detection';
|
|
2219
|
+
waiting: boolean;
|
|
2220
|
+
}
|
|
2221
|
+
/** `escalations`: what waits on a person now (ADR-0053), whole; absent from an older daemon. */
|
|
2222
|
+
| {
|
|
1985
2223
|
type: 'status_update';
|
|
1986
2224
|
tasks: SerializedTaskStatus[];
|
|
1987
2225
|
runMerge?: RunMergeView;
|
|
1988
2226
|
usage?: PlanUsage;
|
|
1989
2227
|
activity?: RunActivity;
|
|
2228
|
+
escalations?: Escalation[];
|
|
1990
2229
|
} | {
|
|
1991
2230
|
type: 'review_needed';
|
|
1992
2231
|
tasks: SerializedTask[];
|
|
@@ -2100,7 +2339,7 @@ type PlanSnapshot = {
|
|
|
2100
2339
|
plan: SurfacePlan | SurfacePlanState;
|
|
2101
2340
|
};
|
|
2102
2341
|
/** What only the status stream says about a task; a plan refresh keeps these as they were. */
|
|
2103
|
-
type RunTaskStatus = Partial<Pick<SerializedTaskStatus, 'verdict' | 'idleSince' | 'completionReceived' | 'attaching' | 'isolation' | 'checkpoint' | 'queued' | 'continuable' | 'awaitingApproval' | 'mergeGate' | 'forcedPastGate' | 'waitsForApproval' | 'holdReason' | 'handoff' | 'attempted'>>;
|
|
2342
|
+
type RunTaskStatus = Partial<Pick<SerializedTaskStatus, 'verdict' | 'idleSince' | 'completionReceived' | 'attaching' | 'isolation' | 'checkpoint' | 'queued' | 'continuable' | 'awaitingApproval' | 'mergeGate' | 'forcedPastGate' | 'waitsForApproval' | 'holdReason' | 'loopStranded' | 'handoff' | 'attempted' | 'delegation'>>;
|
|
2104
2343
|
/** A task in the run view: the plan's fields, then the status stream's. */
|
|
2105
2344
|
type RunTask = Omit<SerializedTask, 'subtasks'> & RunTaskStatus & {
|
|
2106
2345
|
subtasks: RunTask[];
|
|
@@ -2147,6 +2386,8 @@ interface RunView {
|
|
|
2147
2386
|
mergeResult: IsolationMergeResult | null;
|
|
2148
2387
|
/** What the scheduler is doing with the plan, as {@link RunActivity}. */
|
|
2149
2388
|
activity?: RunActivity;
|
|
2389
|
+
/** What will not move without a person (ADR-0053), as the newest status update said; absent from an older daemon's snapshot. */
|
|
2390
|
+
escalations?: Escalation[];
|
|
2150
2391
|
}
|
|
2151
2392
|
type RunInput = SessionMessage | PlanSnapshot;
|
|
2152
2393
|
/**
|
|
@@ -2162,7 +2403,7 @@ type SessionNotice = {
|
|
|
2162
2403
|
};
|
|
2163
2404
|
type SessionBroadcaster = (msg: SessionMessage) => void;
|
|
2164
2405
|
declare function serializeTask(t: SurfaceTask): SerializedTask;
|
|
2165
|
-
declare function serializeTaskStatus(t: Task, idleSince?: string | null, isolation?: TaskIsolation | null, queued?: readonly QueuedTaskMessage[], awaitingApproval?: number, mergeGate?: readonly string[], checkpoint?: string, waitsForApproval?: boolean, holdReason?: string | null, completionReceived?: Verdict['reported'] | null, attaching?: 1 | 2 | null): SerializedTaskStatus;
|
|
2406
|
+
declare function serializeTaskStatus(t: Task, idleSince?: string | null, isolation?: TaskIsolation | null, queued?: readonly QueuedTaskMessage[], awaitingApproval?: number, mergeGate?: readonly string[], checkpoint?: string, waitsForApproval?: boolean, holdReason?: string | null, completionReceived?: Verdict['reported'] | null, attaching?: 1 | 2 | null, loopStranded?: boolean, delegation?: DelegatedRow | undefined): SerializedTaskStatus;
|
|
2166
2407
|
/** The one place a plan's skill bodies come off before it leaves the session: every wire path that carries plan state goes through here. */
|
|
2167
2408
|
declare function surfacePlan({ queuedMessages: _carriedOverAtLoad, ...plan }: LegacyPlanState): SurfacePlan;
|
|
2168
2409
|
declare function surfacePlanState(state: PlanState): SurfacePlanState;
|
|
@@ -2252,9 +2493,11 @@ declare class SessionHeldError extends Error {
|
|
|
2252
2493
|
interface SessionLease {
|
|
2253
2494
|
/**
|
|
2254
2495
|
* Hold `sessionId`'s lease in `workspace`, letting go of the one held before
|
|
2255
|
-
* only once this one is held. Throws {@link SessionHeldError}.
|
|
2496
|
+
* only once this one is held. Throws {@link SessionHeldError}. `commit` runs
|
|
2497
|
+
* holding both: when it throws, the one held before is still held, and a
|
|
2498
|
+
* lease this claim took is let go.
|
|
2256
2499
|
*/
|
|
2257
|
-
claim(sessionId: string, workspace: string): void;
|
|
2500
|
+
claim(sessionId: string, workspace: string, commit?: () => void): void;
|
|
2258
2501
|
/**
|
|
2259
2502
|
* Null while this Session holds `sessionId`'s lease, claiming it when no
|
|
2260
2503
|
* live host holds it; otherwise who holds it. A lease another host took from
|
|
@@ -2335,7 +2578,7 @@ declare class HostedLease implements SessionLease {
|
|
|
2335
2578
|
workspace: string;
|
|
2336
2579
|
private lostLease;
|
|
2337
2580
|
constructor(host: LeaseHost, onLost: (held: SessionHeld) => void);
|
|
2338
|
-
claim(sessionId: string, workspace: string): void;
|
|
2581
|
+
claim(sessionId: string, workspace: string, commit?: () => void): void;
|
|
2339
2582
|
hold(sessionId: string, workspace: string): SessionHeld | null;
|
|
2340
2583
|
release(): void;
|
|
2341
2584
|
/** @internal Another host took `file`'s lease from this one. */
|
|
@@ -2348,6 +2591,115 @@ declare class HostedLease implements SessionLease {
|
|
|
2348
2591
|
*/
|
|
2349
2592
|
declare function processLeaseHost(): LeaseHost;
|
|
2350
2593
|
|
|
2594
|
+
/** The changes to a run in flight, as a closing Session waits them out. */
|
|
2595
|
+
interface RunChanges {
|
|
2596
|
+
/** One is under way. */
|
|
2597
|
+
readonly changing: boolean;
|
|
2598
|
+
/** Every one under way has ended and none follows: nothing of this run changes git past here, so its lease can go. */
|
|
2599
|
+
closeChanges(): Promise<void>;
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
/** What a Session hears from the pool of its tree. */
|
|
2603
|
+
interface PoolNode {
|
|
2604
|
+
/** A slot freed in another Session: tick, as a Session's own events do. */
|
|
2605
|
+
tick(): Promise<void>;
|
|
2606
|
+
/** A slot is free for the planner turn this Session was refused: ask again now, synchronously. */
|
|
2607
|
+
openTurn(): void;
|
|
2608
|
+
/** Whether this Session's attempt on `taskId` waits on its planner: a question it asked, or a turn that ended without a report. */
|
|
2609
|
+
waitsOnPlanner(taskId: string): boolean;
|
|
2610
|
+
/** Another node found `runner`'s usage limit, which resets at `at`. */
|
|
2611
|
+
limitFound(runner: string, at: Date): void;
|
|
2612
|
+
}
|
|
2613
|
+
/** What a node asks of the pool: only a role tells it what a claim takes. */
|
|
2614
|
+
interface SlotRequest {
|
|
2615
|
+
role: 'planner' | 'task' | 'script' | 'child-plan' | 'merge';
|
|
2616
|
+
taskId?: string;
|
|
2617
|
+
}
|
|
2618
|
+
/** What {@link SlotPool.take} granted. */
|
|
2619
|
+
interface HeldSlot {
|
|
2620
|
+
/** False for a role that reserves no slot. */
|
|
2621
|
+
readonly holdsSlot: boolean;
|
|
2622
|
+
/** Idempotent: a slot is freed once, and offered on at once. */
|
|
2623
|
+
free(): void;
|
|
2624
|
+
}
|
|
2625
|
+
/**
|
|
2626
|
+
* One pool of slots across a tree (ADR-0055 D18, ADR-0058 S4), the root's and
|
|
2627
|
+
* shared by every Session under it. A flat run has a pool of its own, with one
|
|
2628
|
+
* node: there it is the Parallel limit over attempts alone, and it ticks nobody.
|
|
2629
|
+
*
|
|
2630
|
+
* A claim is synchronous and so is everything here that grants one (ADR-0029);
|
|
2631
|
+
* a Session waiting on a slot in another Session is ticked from here, because a
|
|
2632
|
+
* scheduler ticks only on its own Session's events.
|
|
2633
|
+
*/
|
|
2634
|
+
declare class SlotPool {
|
|
2635
|
+
private readonly limit;
|
|
2636
|
+
private readonly nodes;
|
|
2637
|
+
private root;
|
|
2638
|
+
private readonly holders;
|
|
2639
|
+
/** Nodes whose subplanner turn was refused, oldest first. */
|
|
2640
|
+
private readonly keptTurns;
|
|
2641
|
+
/** Sessions a start was refused, oldest first. */
|
|
2642
|
+
private readonly keptStarts;
|
|
2643
|
+
/** The one turn past the limit: see {@link turnPasses}. */
|
|
2644
|
+
private passing;
|
|
2645
|
+
/** The turn being offered: out of {@link keptTurns}, so it would otherwise queue behind the turns it was chosen ahead of. */
|
|
2646
|
+
private offered;
|
|
2647
|
+
private offering;
|
|
2648
|
+
/** Wakes the offer in flight once a slot goes: a tick's own spawn can take far longer than its claim. */
|
|
2649
|
+
private taken;
|
|
2650
|
+
/** When the tree was held on a usage limit, oldest first and never overlapping. */
|
|
2651
|
+
private readonly holds;
|
|
2652
|
+
private readonly limits;
|
|
2653
|
+
constructor(limit: () => number);
|
|
2654
|
+
/** Add a Session to the tree; the first is its root. Returns how it leaves. */
|
|
2655
|
+
join(node: PoolNode): () => void;
|
|
2656
|
+
/** The tree has a child: there is more than one Session to count across. */
|
|
2657
|
+
get shared(): boolean;
|
|
2658
|
+
private get counted();
|
|
2659
|
+
private get full();
|
|
2660
|
+
/** Why `node` may not take this now, or null. Changes nothing: a claim's refusal is also asked with no claim to follow. */
|
|
2661
|
+
refusal(node: PoolNode, request: SlotRequest): string | null;
|
|
2662
|
+
/**
|
|
2663
|
+
* Take a slot, or be refused and kept (ADR-0059 L1): what a refusal changes
|
|
2664
|
+
* is that the node is told when one frees. {@link refusal} keeps nobody, so
|
|
2665
|
+
* a wait for a slot asks here even when it knows the answer.
|
|
2666
|
+
*/
|
|
2667
|
+
take(node: PoolNode, request: SlotRequest): HeldSlot | {
|
|
2668
|
+
refused: string;
|
|
2669
|
+
};
|
|
2670
|
+
/** An attempt's wait on its planner began or ended: the test {@link turnPasses} reads has changed. */
|
|
2671
|
+
waitsChanged(): void;
|
|
2672
|
+
/**
|
|
2673
|
+
* `node` found `runner`'s limit (D18). Returns when it resets, the later of
|
|
2674
|
+
* this and any limit a sibling found: a runner is usable only once every
|
|
2675
|
+
* limit it hit has reset, and the account is the tree's. A flat run's waits
|
|
2676
|
+
* stay its own.
|
|
2677
|
+
*/
|
|
2678
|
+
limitFound(node: PoolNode, runner: string, at: Date): Date;
|
|
2679
|
+
/**
|
|
2680
|
+
* How long the tree has been held on a usage limit since `since`, up to each
|
|
2681
|
+
* limit's reset: what a child's wall clock does not count (ADR-0056 M3). It
|
|
2682
|
+
* ends at the reset whatever happens first, so what waits on a slot past it
|
|
2683
|
+
* is on the clock, and limits that overlap count once.
|
|
2684
|
+
*/
|
|
2685
|
+
heldSince(since: number): number;
|
|
2686
|
+
private held;
|
|
2687
|
+
/** The runners a usage limit holds across the tree. */
|
|
2688
|
+
limited(): ReadonlySet<string>;
|
|
2689
|
+
/**
|
|
2690
|
+
* Everything that holds a slot waits on a planner, and `node`'s turn is the
|
|
2691
|
+
* oldest one of them waits on: a limit that stopped the answer would stop
|
|
2692
|
+
* the tree. One at a time: a turn waits on nothing (ADR-0056 M8), so when it
|
|
2693
|
+
* ends this is read again, and nothing holds a slot for ever on a turn that
|
|
2694
|
+
* waits for that slot.
|
|
2695
|
+
*/
|
|
2696
|
+
private turnPasses;
|
|
2697
|
+
private waitedTurn;
|
|
2698
|
+
private nextTurn;
|
|
2699
|
+
private offer;
|
|
2700
|
+
private offerStarts;
|
|
2701
|
+
}
|
|
2702
|
+
|
|
2351
2703
|
/** What ran an automatic Merge all: a task reaching its merge gate, or the run settling with landed work unmerged. */
|
|
2352
2704
|
type AutoMergeTrigger = {
|
|
2353
2705
|
kind: 'gate';
|
|
@@ -2357,10 +2709,12 @@ type AutoMergeTrigger = {
|
|
|
2357
2709
|
};
|
|
2358
2710
|
/**
|
|
2359
2711
|
* Who opened a run (ADR-0029): a call the user made, or one made for them; a
|
|
2360
|
-
* call of the supervisor's own
|
|
2361
|
-
*
|
|
2712
|
+
* call of the supervisor's own, or a subplanner's, which has no user to make
|
|
2713
|
+
* one for (ADR-0056 M6); a usage-limit reset resuming what it paused; or a loop
|
|
2714
|
+
* carried on with no scheduler (ADR-0045 L5). Only the user's starts a run's
|
|
2715
|
+
* supervision afresh.
|
|
2362
2716
|
*/
|
|
2363
|
-
type RunOrigin = 'user' | 'supervisor' | 'limit-reset';
|
|
2717
|
+
type RunOrigin = 'user' | 'supervisor' | 'limit-reset' | 'loop';
|
|
2364
2718
|
/** What the scheduler reads of the open run's settings, at each decision it makes from them. */
|
|
2365
2719
|
type SchedulerRunSettings = Pick<RunSettings, 'mergeAtGatesAutomatically'>;
|
|
2366
2720
|
/**
|
|
@@ -2485,6 +2839,8 @@ interface TaskOrchestratorDeps {
|
|
|
2485
2839
|
runner: IRunner;
|
|
2486
2840
|
/** Runs script tasks' bodies (ADR-0035), in place of a registered runner. */
|
|
2487
2841
|
scriptRunner: IRunner;
|
|
2842
|
+
/** Runs delegated tasks' child plans (ADR-0055 D3). */
|
|
2843
|
+
childPlanRunner: IRunner;
|
|
2488
2844
|
store: PlanStore;
|
|
2489
2845
|
output: TaskOutputSource;
|
|
2490
2846
|
/** The plan's isolation run and the open run's lifecycle (ADR-0013). */
|
|
@@ -2518,8 +2874,14 @@ interface TaskOrchestratorDeps {
|
|
|
2518
2874
|
* owns it, and the scheduler starts nothing outside it.
|
|
2519
2875
|
*/
|
|
2520
2876
|
isApproved: (taskId: string) => boolean;
|
|
2877
|
+
/** Read beside the run's setting at each automatic merge, which passes no command (ADR-0056 M6). */
|
|
2878
|
+
mayMergeUnasked: () => boolean;
|
|
2879
|
+
/** The run's changes to git in flight; absent where no session's lease stands behind them. */
|
|
2880
|
+
runChanges?: RunChanges;
|
|
2521
2881
|
/** A read-only attempt's shell (ADR-0046); absent, its runner is given no `run_command`. */
|
|
2522
2882
|
taskShell?: (site: TaskShellSite) => TaskShell | undefined;
|
|
2883
|
+
/** Why a script that would land its work may not run unsealed now; absent at a root, whose scripts ADR-0035 answers for. */
|
|
2884
|
+
unsealedRefusal?: (task: Readonly<Task>) => string | null;
|
|
2523
2885
|
/** The session's web fetcher for one read-only attempt (ADR-0046); absent, its `fetch` and `web_search` are not available. */
|
|
2524
2886
|
taskWebFetcher?: (task: string) => IWebFetcher | undefined;
|
|
2525
2887
|
/** Keep a read-only attempt's saved patch beside its log (ADR-0050); absent, `save_patch` is not available. */
|
|
@@ -2529,8 +2891,47 @@ interface TaskOrchestratorDeps {
|
|
|
2529
2891
|
* ran (ADR-0047). A task that ran no session, a user task, gets a log of its own.
|
|
2530
2892
|
*/
|
|
2531
2893
|
recordHandoff: (sessionId: string | undefined, taskId: string, handoff: StoredHandoff) => void;
|
|
2532
|
-
/** The session's saved task logs, which a task's `
|
|
2894
|
+
/** The session's saved task logs, which a task's `read` reads handoffs from (ADR-0047). */
|
|
2533
2895
|
taskLog: TaskLogReader;
|
|
2896
|
+
/** The plans below this one (ADR-0057 R1); absent or null with nothing delegated. */
|
|
2897
|
+
subtree?: () => Promise<Subtree | null>;
|
|
2898
|
+
/** This plan's node in its tree, what a reference is pinned under. Absent, the root's. */
|
|
2899
|
+
planNode?: () => string;
|
|
2900
|
+
/** This plan's board; null for a flat plan, which has none (ADR-0057 R8). */
|
|
2901
|
+
board?: () => Promise<NodeBoard | null>;
|
|
2902
|
+
/** What a landing owes the tasks beside it (ADR-0057 R6); undefined where it owes nothing, as on a flat plan. */
|
|
2903
|
+
landed?: (task: Readonly<Task>) => Promise<void> | undefined;
|
|
2904
|
+
/** Where sessions run (ADR-0059). */
|
|
2905
|
+
leases: ExecutionBackend;
|
|
2906
|
+
/** The tree's slots and usage limits (ADR-0055 D18), which the backend reserves from. */
|
|
2907
|
+
pool: SlotPool;
|
|
2908
|
+
/** The Session's id, as it saves under it. */
|
|
2909
|
+
sessionId: () => string;
|
|
2910
|
+
/** Tell the tree this Session found a runner's usage limit; the reset as the tree has it. */
|
|
2911
|
+
limitFound: (runner: string, at: Date) => Date;
|
|
2912
|
+
/** This Session is done with the tree. */
|
|
2913
|
+
leaveTree: () => void;
|
|
2914
|
+
/** This node's side of the tree's ledger; absent at the root, which is charged nothing, and on a flat run, which has no ledger (ADR-0056 M5). */
|
|
2915
|
+
budget?: NodeBudget;
|
|
2916
|
+
/** What is ready cannot start, and nothing live will free room for it, so nothing ticks this again. */
|
|
2917
|
+
startRefused: (why: string) => void;
|
|
2918
|
+
/** This node's autonomy, as its mandate reads it (ADR-0056 M6). */
|
|
2919
|
+
autonomous: () => boolean;
|
|
2920
|
+
/** Nothing is deciding where the run goes any more; see {@link TaskOrchestrator.movesUnasked}. */
|
|
2921
|
+
decided?: () => void;
|
|
2922
|
+
/** Why nothing may start at this node (ADR-0055 D16, ADR-0056 M10); absent at the root, whose own Stop is its generation. */
|
|
2923
|
+
nodeRefusal?: () => string | null;
|
|
2924
|
+
/** The child `task` holds goes (ADR-0055 D15). Absent where no Session hosts one. */
|
|
2925
|
+
discardChild?: (task: Readonly<Task>) => Promise<void>;
|
|
2926
|
+
}
|
|
2927
|
+
/** What a backend hears of the Session it serves, past the local lease it wraps. */
|
|
2928
|
+
interface ExecutionContext {
|
|
2929
|
+
sessionId: () => string;
|
|
2930
|
+
/** The root of this Session's tree: what a clean-up at the root finds a child's leavings by. */
|
|
2931
|
+
treeId: () => string;
|
|
2932
|
+
tell: (level: 'info' | 'warn' | 'error', text: string) => void;
|
|
2933
|
+
/** What a worktree's bootstrap runs on this host, in what was last landed. */
|
|
2934
|
+
setupCommand: () => string | undefined;
|
|
2534
2935
|
}
|
|
2535
2936
|
/**
|
|
2536
2937
|
* What a caller supplies to {@link TaskOrchestrator.compose}; every optional
|
|
@@ -2538,17 +2939,28 @@ interface TaskOrchestratorDeps {
|
|
|
2538
2939
|
* resolved wiring the orchestrator itself runs on.
|
|
2539
2940
|
*/
|
|
2540
2941
|
interface TaskOrchestratorOptions {
|
|
2942
|
+
/** The plans below this one (ADR-0057 R1); absent or null with nothing delegated. */
|
|
2943
|
+
subtree?: () => Promise<Subtree | null>;
|
|
2944
|
+
/** This plan's node in its tree, what a reference is pinned under. Absent, the root's. */
|
|
2945
|
+
planNode?: () => string;
|
|
2946
|
+
/** This plan's board; null for a flat plan, which has none (ADR-0057 R8). */
|
|
2947
|
+
board?: () => Promise<NodeBoard | null>;
|
|
2948
|
+
/** What a landing owes the tasks beside it (ADR-0057 R6); undefined where it owes nothing, as on a flat plan. */
|
|
2949
|
+
landed?: (task: Readonly<Task>) => Promise<void> | undefined;
|
|
2541
2950
|
/** What starting a research task owes the planner (ADR-0037 R3). */
|
|
2542
2951
|
research?: Pick<ResearchTasks, 'started'>;
|
|
2543
2952
|
config: IConfig;
|
|
2544
2953
|
notifications: INotification;
|
|
2545
2954
|
runner: IRunner;
|
|
2546
2955
|
scriptRunner?: IRunner;
|
|
2956
|
+
childPlanRunner?: IRunner;
|
|
2547
2957
|
store?: PlanStore;
|
|
2548
2958
|
output?: TaskOutputSource;
|
|
2549
2959
|
isolation?: IWorktreeIsolation;
|
|
2550
2960
|
registry?: RunnerRegistry | null;
|
|
2551
2961
|
workspaceRoot?: () => string;
|
|
2962
|
+
/** A child session's state root (ADR-0055 D11); absent on a flat run, whose workspace is both roots. */
|
|
2963
|
+
stateRoot?: string;
|
|
2552
2964
|
workspaceEnv?: (cwd: string) => Promise<WorkspaceEnv>;
|
|
2553
2965
|
skillsAt?: (roots: readonly string[]) => SkillLookup;
|
|
2554
2966
|
previousAttemptFromLog?: (taskId: string) => string | null;
|
|
@@ -2559,7 +2971,11 @@ interface TaskOrchestratorOptions {
|
|
|
2559
2971
|
plannedWith?: () => boolean;
|
|
2560
2972
|
/** Every task is approved unless a Session supplies its record: an orchestrator on its own has no user to ask. */
|
|
2561
2973
|
isApproved?: (taskId: string) => boolean;
|
|
2974
|
+
/** Whether this node's mandate lets an automatic merge run; true unless set. */
|
|
2975
|
+
mayMergeUnasked?: () => boolean;
|
|
2562
2976
|
taskShell?: (site: TaskShellSite) => TaskShell | undefined;
|
|
2977
|
+
/** See {@link TaskOrchestratorDeps.unsealedRefusal}. */
|
|
2978
|
+
unsealedRefusal?: (task: Readonly<Task>) => string | null;
|
|
2563
2979
|
taskWebFetcher?: (task: string) => IWebFetcher | undefined;
|
|
2564
2980
|
keepPatch?: (taskId: string, attempt: number, patch: Buffer) => string;
|
|
2565
2981
|
recordHandoff?: (sessionId: string | undefined, taskId: string, handoff: StoredHandoff) => void;
|
|
@@ -2569,6 +2985,30 @@ interface TaskOrchestratorOptions {
|
|
|
2569
2985
|
* to the run (ADR-0049); the run is changed only while it answers null.
|
|
2570
2986
|
*/
|
|
2571
2987
|
sessionHeld?: () => SessionHeld | null;
|
|
2988
|
+
/** Where sessions run (ADR-0059), given the local worktrees: those, unless the `containers` setting or a test supplies another. */
|
|
2989
|
+
execution?: (local: ExecutionBackend, context: ExecutionContext) => ExecutionBackend;
|
|
2990
|
+
/** The root's pool, handed down to a child (ADR-0055 D18); absent, this is a root, with a pool of its own. */
|
|
2991
|
+
pool?: SlotPool;
|
|
2992
|
+
/** The Session's id, as it saves under it. */
|
|
2993
|
+
sessionId?: () => string;
|
|
2994
|
+
/** Its tree's root's, when it is a child; absent, it is a root. */
|
|
2995
|
+
treeId?: () => string;
|
|
2996
|
+
/** The pool has a slot for the planner turn it refused this Session. */
|
|
2997
|
+
openTurn?: () => void;
|
|
2998
|
+
/** A child's side of the tree's ledger (ADR-0056 M5). */
|
|
2999
|
+
budget?: NodeBudget;
|
|
3000
|
+
/** What follows a start its budget refuses with nothing live; the node stops, unless a subplanner can ask. */
|
|
3001
|
+
startRefused?: (why: string) => void;
|
|
3002
|
+
/** This node's autonomy, as its mandate reads it (ADR-0056 M6); the config's, at a root. */
|
|
3003
|
+
autonomous?: () => boolean;
|
|
3004
|
+
/** Nothing is deciding where the run goes any more. */
|
|
3005
|
+
decided?: () => void;
|
|
3006
|
+
/** What this node's ancestors protect (ADR-0056 M4). */
|
|
3007
|
+
inheritedProtectedPaths?: () => readonly string[];
|
|
3008
|
+
/** See {@link TaskOrchestratorDeps.nodeRefusal}. */
|
|
3009
|
+
nodeRefusal?: () => string | null;
|
|
3010
|
+
/** See {@link TaskOrchestratorDeps.discardChild}. */
|
|
3011
|
+
discardChild?: (task: Readonly<Task>) => Promise<void>;
|
|
2572
3012
|
}
|
|
2573
3013
|
/**
|
|
2574
3014
|
* The pure scheduler. Owns execution state (the {@link RunState},
|
|
@@ -2583,6 +3023,7 @@ interface TaskOrchestratorOptions {
|
|
|
2583
3023
|
* and does not unblock dependent work.
|
|
2584
3024
|
*/
|
|
2585
3025
|
declare class TaskOrchestrator {
|
|
3026
|
+
private readonly deps;
|
|
2586
3027
|
private config;
|
|
2587
3028
|
private notifications;
|
|
2588
3029
|
private store;
|
|
@@ -2592,12 +3033,20 @@ declare class TaskOrchestrator {
|
|
|
2592
3033
|
private runState;
|
|
2593
3034
|
/** Planner turns in flight that new starts wait for (ADR-0029); running attempts carry on. */
|
|
2594
3035
|
private startHolds;
|
|
3036
|
+
/** The judgement a {@link judgingOnce} read shares, while one runs. */
|
|
3037
|
+
private judgement;
|
|
3038
|
+
/** The {@link revertReach} of each revert under way: unlike a hold, it stops a start admitted before the revert too. */
|
|
3039
|
+
private readonly reverting;
|
|
2595
3040
|
/** Bumped by the user's Stop: a start admitted under an older generation never takes its claim. */
|
|
2596
3041
|
private stopGeneration;
|
|
2597
3042
|
/** Starts admitted and not yet claimed or let go; see {@link StartAdmission}. */
|
|
2598
3043
|
private admissions;
|
|
2599
3044
|
private reviewApproved;
|
|
2600
3045
|
private autoMergeBlocked;
|
|
3046
|
+
/** Ticks and attempt ends under way; see {@link deciding}. */
|
|
3047
|
+
private decisions;
|
|
3048
|
+
/** The run closed with its merge held, which it would otherwise have made itself. */
|
|
3049
|
+
private mergeOwedAtClose;
|
|
2601
3050
|
private mergesInFlight;
|
|
2602
3051
|
private retryCounts;
|
|
2603
3052
|
/** A Merge all is under way: no ops task starts until it ends (ADR-0020). */
|
|
@@ -2628,6 +3077,18 @@ declare class TaskOrchestrator {
|
|
|
2628
3077
|
private queuedStarts;
|
|
2629
3078
|
/** Conflict repairs owed with every slot taken and no scheduler to claim them: a freed slot starts them. */
|
|
2630
3079
|
private owedRepairs;
|
|
3080
|
+
/**
|
|
3081
|
+
* The checks whose loop goes on with no scheduler: each failed a round in a
|
|
3082
|
+
* run the scheduler was not driving, so nothing else would start what it
|
|
3083
|
+
* owes (ADR-0045 L5). Held here and not on the plan, because a Stop ends it
|
|
3084
|
+
* and a reload does not bring it back; an edit does neither. A loop stopped
|
|
3085
|
+
* by its body stays here, so a retry of that task resumes it (L7).
|
|
3086
|
+
*/
|
|
3087
|
+
private readonly carriedLoops;
|
|
3088
|
+
/** The checks of a delegated task that passed with no scheduler to start them (ADR-0055 D8): carried as a loop is, never queued, since one that stops being ready simply stops being owed. */
|
|
3089
|
+
private readonly carriedChecks;
|
|
3090
|
+
/** What was last said of a carried loop's approvals, so it is said once. */
|
|
3091
|
+
private loopNotice;
|
|
2631
3092
|
/**
|
|
2632
3093
|
* Tasks Mark complete is landing after it ended their attempt, or that
|
|
2633
3094
|
* their conflict resolver is landing, and that landing: in progress with
|
|
@@ -2639,6 +3100,13 @@ declare class TaskOrchestrator {
|
|
|
2639
3100
|
private releasing;
|
|
2640
3101
|
/** Tasks paused on a usage limit, the run's hold on them, and each runner's wait for its reset (ADR-0018, U1). */
|
|
2641
3102
|
private readonly limitPauses;
|
|
3103
|
+
/**
|
|
3104
|
+
* Resumes whose reset came with every slot of the tree taken: past their
|
|
3105
|
+
* time, with no timer to fire again, so a tick offers them (ADR-0055 D18).
|
|
3106
|
+
*/
|
|
3107
|
+
private readonly keptResumes;
|
|
3108
|
+
/** What a close waits out past the runners: ticks, attempt ends, and work nothing awaits, a Stop's release of a worktree chiefly. */
|
|
3109
|
+
private readonly loose;
|
|
2642
3110
|
/**
|
|
2643
3111
|
* The plan's isolation run and the open run's lifecycle (ADR-0013); see
|
|
2644
3112
|
* {@link IsolationRunController}. Read and acted on there directly, except
|
|
@@ -2646,12 +3114,18 @@ declare class TaskOrchestrator {
|
|
|
2646
3114
|
* ops tasks and starts the tasks its merge lets through.
|
|
2647
3115
|
*/
|
|
2648
3116
|
readonly runs: IsolationRunController;
|
|
3117
|
+
/** Where a session runs (ADR-0059): every start reserves here in its claim, and opens here after it. */
|
|
3118
|
+
private readonly leases;
|
|
3119
|
+
/** The tree's slots and usage limits (ADR-0055 D18); a flat run's own. */
|
|
3120
|
+
private readonly pool;
|
|
3121
|
+
private readonly sessionId;
|
|
2649
3122
|
/** A passed attempt's work onto the integration branch, and the conflict repair a landing may need. */
|
|
2650
3123
|
private landing;
|
|
2651
3124
|
private observers;
|
|
2652
3125
|
private previousRounds;
|
|
2653
3126
|
private runSettings;
|
|
2654
3127
|
private isApproved;
|
|
3128
|
+
private mayMergeUnasked;
|
|
2655
3129
|
constructor(deps: TaskOrchestratorDeps);
|
|
2656
3130
|
/**
|
|
2657
3131
|
* The composition root: resolves every optional collaborator and wires the
|
|
@@ -2670,12 +3144,14 @@ declare class TaskOrchestrator {
|
|
|
2670
3144
|
/** Recent clean output of a task's latest attempt, running or ended; null if it never ran. */
|
|
2671
3145
|
getLiveOutput(taskId: string, opts: LiveTailOptions): LiveTail | null;
|
|
2672
3146
|
get storeInstance(): PlanStore;
|
|
2673
|
-
approveCheckpoint(taskId: string): void;
|
|
3147
|
+
approveCheckpoint(taskId: string, note?: string): void;
|
|
2674
3148
|
rejectCheckpoint(taskId: string, reason?: string): void;
|
|
2675
3149
|
/** What the task's waiting checkpoint asks, whole; undefined once it settles or when none waits. */
|
|
2676
3150
|
getCheckpointQuestion(taskId: string): string | undefined;
|
|
2677
3151
|
/** Whether the task waits at a checkpoint its live attempt can still answer. */
|
|
2678
3152
|
awaitsCheckpoint(taskId: string): boolean;
|
|
3153
|
+
/** A line from Ordewell to a running task (ADR-0057 R6); false where nothing is running. */
|
|
3154
|
+
addressTask(taskId: string, line: string): boolean;
|
|
2679
3155
|
/**
|
|
2680
3156
|
* Send a structured task a user message (ADR-0018, M1). Mid-turn it queues
|
|
2681
3157
|
* behind the turn; a task waiting for input takes it at once and is back in
|
|
@@ -2719,6 +3195,10 @@ declare class TaskOrchestrator {
|
|
|
2719
3195
|
get isReviewApproved(): boolean;
|
|
2720
3196
|
/** The scheduler is driving the plan: ready tasks start on their own as slots free. Narrower than {@link isRunning}. */
|
|
2721
3197
|
get isScheduling(): boolean;
|
|
3198
|
+
/** A scheduled run, driving the plan or held by a usage limit that gives it back: a hold never closes one. */
|
|
3199
|
+
get scheduledRun(): boolean;
|
|
3200
|
+
/** A usage limit holds the run, whatever it goes back to at the reset. */
|
|
3201
|
+
get runHeld(): boolean;
|
|
2722
3202
|
/**
|
|
2723
3203
|
* A full-plan run with nothing starting that something still resumes: a
|
|
2724
3204
|
* usage limit's reset, or a retry of a failed task its blocked tasks wait on.
|
|
@@ -2729,6 +3209,8 @@ declare class TaskOrchestrator {
|
|
|
2729
3209
|
/** Task id → session id of every attempt whose runner is up; a spawn in flight has no session yet. */
|
|
2730
3210
|
get activeSessionMap(): Map<string, string>;
|
|
2731
3211
|
getAttempt(taskId: string): TaskAttemptSnapshot | undefined;
|
|
3212
|
+
/** The number of the task's latest attempt, live or ended; 0 before any ran. */
|
|
3213
|
+
latestAttempt(task: Readonly<Task>): number;
|
|
2732
3214
|
/** A planner turn holds new starts: what is ready starts when it releases them. */
|
|
2733
3215
|
get startsHeld(): boolean;
|
|
2734
3216
|
/**
|
|
@@ -2748,11 +3230,20 @@ declare class TaskOrchestrator {
|
|
|
2748
3230
|
* Something can still start that nobody has to ask for again: a start
|
|
2749
3231
|
* admitted and not yet claimed, a force start queued behind its
|
|
2750
3232
|
* dependencies, a conflict repair owed a slot or the end of a start hold,
|
|
2751
|
-
* a task that resumes on its own at its usage limit's reset,
|
|
2752
|
-
* dirty checkout parked for Stash and continue to replay
|
|
2753
|
-
*
|
|
3233
|
+
* a task that resumes on its own at its usage limit's reset, a start a
|
|
3234
|
+
* dirty checkout parked for Stash and continue to replay, or a loop or a
|
|
3235
|
+
* delegated task's check carried on with no scheduler. A Stop is owed to it,
|
|
3236
|
+
* whether or not anything runs.
|
|
3237
|
+
* A carried loop a body task stopped starts nothing, so it is not here: see
|
|
3238
|
+
* {@link loopCarried}.
|
|
2754
3239
|
*/
|
|
2755
3240
|
get startsPending(): boolean;
|
|
3241
|
+
/**
|
|
3242
|
+
* A loop is carried on, one a body task stopped included. Nothing of that
|
|
3243
|
+
* one starts by itself, so nothing here moves a task on, but a retry that
|
|
3244
|
+
* passes would resume it: a Stop is owed to it too (ADR-0045 L7).
|
|
3245
|
+
*/
|
|
3246
|
+
get loopCarried(): boolean;
|
|
2756
3247
|
/**
|
|
2757
3248
|
* The plan's activity as one word for every surface: a start on its way,
|
|
2758
3249
|
* work running, a scheduler driving the plan, or a run that resumes by
|
|
@@ -2772,7 +3263,9 @@ declare class TaskOrchestrator {
|
|
|
2772
3263
|
*/
|
|
2773
3264
|
get advancesOnItsOwn(): boolean;
|
|
2774
3265
|
/** A start admitted now that nothing has to count as live work: one that claims before it awaits, or follows on from one that did. */
|
|
2775
|
-
|
|
3266
|
+
admittedNow(): Admitted;
|
|
3267
|
+
/** The user's Stop found nothing to stop: it still withdraws every start admitted before it, one no live work counts included (ADR-0029). */
|
|
3268
|
+
stopAsked(): void;
|
|
2776
3269
|
/** Run `work`, which awaits before it claims, under an admission it holds throughout and claims under. */
|
|
2777
3270
|
private whileAdmitted;
|
|
2778
3271
|
/**
|
|
@@ -2790,6 +3283,15 @@ declare class TaskOrchestrator {
|
|
|
2790
3283
|
* over as before.
|
|
2791
3284
|
*/
|
|
2792
3285
|
private closeRun;
|
|
3286
|
+
/** A hold is no merge that stopped (ADR-0055 D9): the tick after its check's pass or Skip merges, the run closed or not. */
|
|
3287
|
+
private mergeOwedAfterHold;
|
|
3288
|
+
/**
|
|
3289
|
+
* Whether closing the run merges what landed, with nobody asked. The run
|
|
3290
|
+
* says it has ended before it closes, and a list read in between must not
|
|
3291
|
+
* name a Merge all it is about to do itself (ADR-0053). A Stop takes the run
|
|
3292
|
+
* out of isolating and a merge that stopped blocks this, so neither wait is hidden.
|
|
3293
|
+
*/
|
|
3294
|
+
get mergesAtClose(): boolean;
|
|
2793
3295
|
/**
|
|
2794
3296
|
* The run as a surface offers Merge all mid-run (ADR-0020): what has landed
|
|
2795
3297
|
* and is not merged, and whether the run is paused at its gates with nothing
|
|
@@ -2812,9 +3314,48 @@ declare class TaskOrchestrator {
|
|
|
2812
3314
|
* Takes the task, not its id: the one the command seam located.
|
|
2813
3315
|
*/
|
|
2814
3316
|
startWaits(task: Readonly<Task>, forced?: ForcedStart): StartWait[];
|
|
3317
|
+
/** Every task's {@link startWaits}, the plan judged once. */
|
|
3318
|
+
planStartWaits(): Map<string, StartWait[]>;
|
|
3319
|
+
/**
|
|
3320
|
+
* Run `read`, a synchronous read of the plan, on one judgement of it: what a
|
|
3321
|
+
* read asks task by task would otherwise judge the whole plan per task.
|
|
3322
|
+
* Nothing can change the plan inside it, so no answer can be stale.
|
|
3323
|
+
*/
|
|
3324
|
+
judgingOnce<T>(read: () => T): T;
|
|
2815
3325
|
private startRule;
|
|
3326
|
+
/** What tells a check, which reads the runners' modes as an attempt's kind does (ADR-0031). */
|
|
3327
|
+
private get checkRules();
|
|
3328
|
+
private liveCheck;
|
|
3329
|
+
/** A retry takes the task's checks back, and a live one cannot be (ADR-0055 D8). */
|
|
3330
|
+
private refuseBesideLiveCheck;
|
|
3331
|
+
/** What holds every merge but the user's (ADR-0055 D9), named as a refusal names it. */
|
|
3332
|
+
get mergeHold(): readonly Task[];
|
|
3333
|
+
/**
|
|
3334
|
+
* Why no resolver may be added to this task's conflict now, or null: a
|
|
3335
|
+
* conflict has one worker (ADR-0015), so a repair or a resolver that has it
|
|
3336
|
+
* keeps it. The words are for whoever asked, since a surface may still offer
|
|
3337
|
+
* the action from a status update it has not yet replaced.
|
|
3338
|
+
*/
|
|
3339
|
+
resolverRefusal(taskId: string): string | null;
|
|
3340
|
+
/** What the conflict repair this task is owed waits for; null when no repair will start by itself. */
|
|
3341
|
+
repairWait(taskId: string): RepairWait | null;
|
|
3342
|
+
/** A usage limit keeps this task from starting by itself: the hold on the run, or its own runner's limit with no reset to wait for. */
|
|
3343
|
+
private onUsageLimit;
|
|
3344
|
+
/** Where a task's isolated work stands, and who has its conflict: the record says the first, the scheduler the second. */
|
|
3345
|
+
taskIsolation(taskId: string): TaskIsolation | null;
|
|
3346
|
+
/** Each task's isolation mark and the run's handoff, as {@link taskIsolation} reads them. */
|
|
3347
|
+
isolationView(): IsolationView | null;
|
|
3348
|
+
private withConflictWorker;
|
|
3349
|
+
/**
|
|
3350
|
+
* A repair will start by itself: the task is not started, it has one left,
|
|
3351
|
+
* and something will claim it, the scheduler or {@link owedRepairs}. Nothing
|
|
3352
|
+
* saves this: a reload or a Stop leaves the conflict waiting on the user.
|
|
3353
|
+
*/
|
|
3354
|
+
private owesRepair;
|
|
2816
3355
|
/** The failed tasks a task not started yet waits on, through its dependencies (ADR-0034); empty when it is not blocked. */
|
|
2817
3356
|
getBlockedBy(taskId: string): string[];
|
|
3357
|
+
/** Throws what {@link loadPlan} would, for a caller with work of its own to do before it loads. */
|
|
3358
|
+
assertLoadable(tasks: readonly Task[], planRunners?: RunnerId[]): void;
|
|
2818
3359
|
/**
|
|
2819
3360
|
* `edited`: the plan is the last one edited, not a new one. Only a Stop
|
|
2820
3361
|
* withdraws a queued start (ADR-0035), so one of a task the edit keeps
|
|
@@ -2828,8 +3369,9 @@ declare class TaskOrchestrator {
|
|
|
2828
3369
|
* reload would clear the holds and the review approval, so a task the user
|
|
2829
3370
|
* cancelled would be re-armed by the tick that follows, and a retry after
|
|
2830
3371
|
* the edit would run the failed task alone, its failure lost. Otherwise it
|
|
2831
|
-
* is the plan the next run starts from, with
|
|
2832
|
-
*
|
|
3372
|
+
* is the plan the next run starts from, with a failed task still failed and
|
|
3373
|
+
* what waits on the user still waiting: an edit between runs is not the user
|
|
3374
|
+
* starting over.
|
|
2833
3375
|
*/
|
|
2834
3376
|
adoptEdit(tasks: readonly Task[], planRunners: RunnerId[]): void;
|
|
2835
3377
|
/**
|
|
@@ -2844,37 +3386,51 @@ declare class TaskOrchestrator {
|
|
|
2844
3386
|
* input it waits at — adopting the snapshot's "pending" would offer the
|
|
2845
3387
|
* scheduler work a runner is already doing.
|
|
2846
3388
|
*
|
|
2847
|
-
* A failed task stays failed
|
|
2848
|
-
*
|
|
3389
|
+
* A failed task stays failed: an edit is not a retry, and the tasks it blocks
|
|
3390
|
+
* wait for that retry (ADR-0034). One the edit made manual has no retry to wait for.
|
|
2849
3391
|
*/
|
|
2850
3392
|
reconcilePlan(newTasks: readonly Task[], planRunners?: RunnerId[]): void;
|
|
2851
3393
|
/**
|
|
2852
3394
|
* An edit landed on the plan — a planner's task ops through
|
|
2853
3395
|
* {@link reconcilePlan}, or the user's direct edit through the PlanEditor.
|
|
2854
|
-
*
|
|
2855
|
-
*
|
|
2856
|
-
*
|
|
2857
|
-
*
|
|
2858
|
-
*
|
|
3396
|
+
* A task it made manual is the manual task it now is (ADR-0053), a runner
|
|
3397
|
+
* still at a question apart. One that leaves a loop's check out of rounds
|
|
3398
|
+
* ends the loop (ADR-0045 L6): what of its body has not run will not run,
|
|
3399
|
+
* and, while the run is under way, the check settles once more so the
|
|
3400
|
+
* supervisor hears the end. Nothing else notices such an edit: the check
|
|
3401
|
+
* settled when it failed a round, and no round will run it again.
|
|
2859
3402
|
*/
|
|
2860
3403
|
planEdited(before: readonly Task[]): void;
|
|
2861
3404
|
/**
|
|
2862
|
-
* Begin the full-plan run afresh, as Execute does with
|
|
2863
|
-
* Whatever an earlier run left goes: its state,
|
|
2864
|
-
*
|
|
2865
|
-
*
|
|
3405
|
+
* Begin the full-plan run afresh, as Execute does with no open run to join.
|
|
3406
|
+
* Whatever an earlier run left goes: its state, which {@link start} would
|
|
3407
|
+
* take as a run already under way; its scheduled resumes and execution log;
|
|
3408
|
+
* and, as the plan is loaded over
|
|
2866
3409
|
* itself, its retry counts, holds, loop rounds and review approval. Every
|
|
2867
3410
|
* task not done is ready to run again, and the scheduler starts it; a plan
|
|
2868
|
-
* with nothing left to run ends at once, and the scheduler says so
|
|
3411
|
+
* with nothing left to run ends at once, and the scheduler says so, but for
|
|
3412
|
+
* `keepFailed`: failures nobody asked this run to try again (ADR-0030).
|
|
2869
3413
|
*/
|
|
2870
|
-
beginRun(origin: RunOrigin): Promise<void>;
|
|
3414
|
+
beginRun(origin: RunOrigin, keepFailed?: ReadonlySet<string>): Promise<void>;
|
|
2871
3415
|
/**
|
|
2872
3416
|
* Take the plan into the run under way (#95), whose tasks were approved
|
|
2873
3417
|
* first: a scheduled run starts them as their dependencies finish, and one
|
|
2874
3418
|
* the scheduler was not driving — tasks started on their own — becomes the
|
|
2875
|
-
* plan's run, as Execute would make it.
|
|
3419
|
+
* plan's run, as Execute would make it. A hold starts nothing either way:
|
|
3420
|
+
* the plan's run is what its reset gives back (ADR-0018 U1). A start a dirty
|
|
3421
|
+
* checkout parked in a scheduled run is replayed, which reads the checkout
|
|
3422
|
+
* again; a new run would take back the run's failures (ADR-0053).
|
|
2876
3423
|
*/
|
|
2877
3424
|
joinRun(origin: RunOrigin): Promise<void>;
|
|
3425
|
+
private joinHold;
|
|
3426
|
+
/**
|
|
3427
|
+
* The user's Execute takes in work the scheduler was not driving: it becomes
|
|
3428
|
+
* the plan's run, so what failed gets the fresh chance Execute gives
|
|
3429
|
+
* (ADR-0053). A scheduled run keeps its failures, which a retry continues
|
|
3430
|
+
* (ADR-0034), and Execute only approves what waits in it: a hold that gives
|
|
3431
|
+
* one back is that run still.
|
|
3432
|
+
*/
|
|
3433
|
+
readyFailed(): void;
|
|
2878
3434
|
/** Start the full-plan run, or continue one that is held or ended on a failure. */
|
|
2879
3435
|
start(origin?: RunOrigin): Promise<void>;
|
|
2880
3436
|
/**
|
|
@@ -2884,6 +3440,18 @@ declare class TaskOrchestrator {
|
|
|
2884
3440
|
* for meanwhile.
|
|
2885
3441
|
*/
|
|
2886
3442
|
stop(reason?: 'user' | 'restart'): void;
|
|
3443
|
+
/**
|
|
3444
|
+
* Nothing claims a repair once the run has stopped, so what was owed one is
|
|
3445
|
+
* a conflict waiting on the user, listed with its options, not a task that
|
|
3446
|
+
* reads as never started.
|
|
3447
|
+
*/
|
|
3448
|
+
private withdrawRepairs;
|
|
3449
|
+
/**
|
|
3450
|
+
* A force start behind a dependency lifted a reverted task's hold for that
|
|
3451
|
+
* start alone, in the queue or left to the scheduler. With the start
|
|
3452
|
+
* withdrawn, the task stays what the user took back (ADR-0054).
|
|
3453
|
+
*/
|
|
3454
|
+
private withdrawQueuedStarts;
|
|
2887
3455
|
private chosenHoldsNow;
|
|
2888
3456
|
private restoreHolds;
|
|
2889
3457
|
private releaseUnchosenHolds;
|
|
@@ -2941,17 +3509,34 @@ declare class TaskOrchestrator {
|
|
|
2941
3509
|
* came from, which a repair follows on from.
|
|
2942
3510
|
*/
|
|
2943
3511
|
private applyLanding;
|
|
3512
|
+
/** Before anything the landing lets start: what a dependent reads of it should be there (ADR-0057 R6). A flat plan owes nothing, and waits on nothing. */
|
|
3513
|
+
private owedByLanding;
|
|
2944
3514
|
/**
|
|
2945
3515
|
* Work that did not land waits on the user — it never fails the task or
|
|
2946
3516
|
* blocks its dependents — unless its conflict is owed a repair, which takes
|
|
2947
3517
|
* the slot the ending attempt freed and never one more than the run allows.
|
|
2948
|
-
* A planner turn's start hold holds it as it holds any new spawn (ADR-0029)
|
|
2949
|
-
*
|
|
2950
|
-
*
|
|
3518
|
+
* A planner turn's start hold holds it as it holds any new spawn (ADR-0029),
|
|
3519
|
+
* and a usage limit does too: `reopen` spends a repair, so one the runner
|
|
3520
|
+
* would refuse is not tried. The repair follows on from the start whose work
|
|
3521
|
+
* it repairs: a Stop since that was admitted withdraws it.
|
|
2951
3522
|
*/
|
|
2952
3523
|
private settleUnlanded;
|
|
2953
3524
|
/** Start the repairs {@link settleUnlanded} left owed, as slots and any start hold allow. */
|
|
2954
3525
|
private startOwedRepairs;
|
|
3526
|
+
/**
|
|
3527
|
+
* A conflict ended some other way than through its resolver: the task
|
|
3528
|
+
* landed, was retried or skipped, or left the plan. The merge the resolver
|
|
3529
|
+
* was added for is no longer needed, so it goes with its link: skipped,
|
|
3530
|
+
* with why, and never started (ADR-0015).
|
|
3531
|
+
*/
|
|
3532
|
+
private retireResolvers;
|
|
3533
|
+
private retireResolver;
|
|
3534
|
+
/** A planner's remove reaches no {@link releaseTask}: what it took out of the plan since `before` ends its conflicts here. */
|
|
3535
|
+
private retireResolversLeft;
|
|
3536
|
+
/** A delegated task the edit took out leaves nothing naming its child's run, so that goes with it, once a child still stopping has (ADR-0055 D15). */
|
|
3537
|
+
private retireChildrenLeft;
|
|
3538
|
+
/** A control that would end a conflict waits for the resolver at work on it: a conflict has one worker (ADR-0015). */
|
|
3539
|
+
private refuseBesideResolver;
|
|
2955
3540
|
private landResolved;
|
|
2956
3541
|
/**
|
|
2957
3542
|
* Hold a task for as long as `landing` is merging its worktree. Its end lets
|
|
@@ -2962,6 +3547,10 @@ declare class TaskOrchestrator {
|
|
|
2962
3547
|
getReadyTasks(): Task[];
|
|
2963
3548
|
private readiness;
|
|
2964
3549
|
private mergesAutomatically;
|
|
3550
|
+
/** A Merge all is under way. */
|
|
3551
|
+
get isMerging(): boolean;
|
|
3552
|
+
/** A gate reached now is merged with nobody asked: the setting is on, and no merge has stopped it. */
|
|
3553
|
+
get mergesAtGates(): boolean;
|
|
2965
3554
|
/**
|
|
2966
3555
|
* The user changed the run settings under an open run (ADR-0030). The
|
|
2967
3556
|
* scheduler reads them at each decision it makes from them, so a merge gate
|
|
@@ -2996,6 +3585,7 @@ declare class TaskOrchestrator {
|
|
|
2996
3585
|
* Cancel a running (or scheduled) task: kill its session and return it to
|
|
2997
3586
|
* 'pending' — "not executed". The task is put on hold so the scheduler
|
|
2998
3587
|
* doesn't immediately restart it; Retry / Force Start release the hold.
|
|
3588
|
+
* A repair, running or owed a start, leaves its conflict waiting instead.
|
|
2999
3589
|
*
|
|
3000
3590
|
* The attempt's worktree is kept, as a stopped or failed one is: a runner is
|
|
3001
3591
|
* often cancelled because it looked stuck after doing the work, and Mark
|
|
@@ -3031,6 +3621,33 @@ declare class TaskOrchestrator {
|
|
|
3031
3621
|
* to waiting on their own, because the scheduler gates on `isCompleted`.
|
|
3032
3622
|
*/
|
|
3033
3623
|
markTaskIncomplete(taskId: string): Promise<void>;
|
|
3624
|
+
/**
|
|
3625
|
+
* What reverting a task would take, and what stands in its way, as far as
|
|
3626
|
+
* the plan can say (ADR-0054); {@link revertPreview} and the revert itself
|
|
3627
|
+
* ask git the rest.
|
|
3628
|
+
*/
|
|
3629
|
+
revertScope(taskId: string): RevertScope;
|
|
3630
|
+
/** What a revert of the task would do now: the tasks, newest landing first, or why it would not go ahead. */
|
|
3631
|
+
revertPreview(taskId: string): Promise<TaskRevertPreview>;
|
|
3632
|
+
/**
|
|
3633
|
+
* Revert the task's landed work, with its landed dependents, on the
|
|
3634
|
+
* integration branches (ADR-0054). No new start while it waits for its
|
|
3635
|
+
* turn and works: one that took its claim now would be cut from a tip about
|
|
3636
|
+
* to lose what it depends on, so the claim of anything depending on the work
|
|
3637
|
+
* is refused too, a start admitted before the revert with it. What it finds
|
|
3638
|
+
* in the way there is judged again: a Mark complete landing a dependent is
|
|
3639
|
+
* live like any other. Tasks not depending on it keep running.
|
|
3640
|
+
*/
|
|
3641
|
+
revertTask(taskId: string): Promise<IsolationRevertResult>;
|
|
3642
|
+
private revertRefusalNow;
|
|
3643
|
+
/**
|
|
3644
|
+
* Each reverted task goes back to not started, held like a stopped one so
|
|
3645
|
+
* the scheduler does not run it again, and starts over when retried: from
|
|
3646
|
+
* the current tip, which no longer holds its work. Its completion goes as
|
|
3647
|
+
* Mark not done takes one back; the logs of its attempts stay. A conflict it
|
|
3648
|
+
* held is over, so a resolver out to it goes too (ADR-0015).
|
|
3649
|
+
*/
|
|
3650
|
+
private takeBack;
|
|
3034
3651
|
/**
|
|
3035
3652
|
* Skip: end a task as `skipped`, with no verdict and nothing of its work
|
|
3036
3653
|
* landed. Its worktree is kept, as a failed attempt's is, so the user can
|
|
@@ -3047,8 +3664,10 @@ declare class TaskOrchestrator {
|
|
|
3047
3664
|
* the task ended in rather than a fresh one given its prompt again. The
|
|
3048
3665
|
* worktree keeps the same path, where the runner keeps its sessions, and
|
|
3049
3666
|
* restores the previous work so that session's memory matches its files.
|
|
3667
|
+
* `revives` is {@link claimRefusal}'s, read as the start is asked for: a dirty
|
|
3668
|
+
* tree's replay carries the first answer, not one read after a skip.
|
|
3050
3669
|
*/
|
|
3051
|
-
continueTask(taskId: string, message: string, origin?: RunOrigin): Promise<void>;
|
|
3670
|
+
continueTask(taskId: string, message: string, origin?: RunOrigin, revives?: boolean): Promise<void>;
|
|
3052
3671
|
/**
|
|
3053
3672
|
* Keep a task paused on its runner's usage limit from resuming on its own:
|
|
3054
3673
|
* it waits for a manual retry, as one whose reset time could not be read
|
|
@@ -3111,9 +3730,9 @@ declare class TaskOrchestrator {
|
|
|
3111
3730
|
* Reuses the scheduler's own claim so a force-started task gets the same
|
|
3112
3731
|
* augmented prompt, session tracking, and exit handling — callers must not
|
|
3113
3732
|
* re-spawn the runner themselves. No-op if the task is unknown, a user
|
|
3114
|
-
* task, or already running.
|
|
3733
|
+
* task, or already running. `revives` is as on {@link continueTask}.
|
|
3115
3734
|
*/
|
|
3116
|
-
forceStartTask(taskId: string, origin?: RunOrigin): Promise<string | undefined>;
|
|
3735
|
+
forceStartTask(taskId: string, origin?: RunOrigin, revives?: boolean): Promise<string | undefined>;
|
|
3117
3736
|
/**
|
|
3118
3737
|
* Start an approved task once its merge gate opens, never past it: a script
|
|
3119
3738
|
* task `run_script` added behind work not merged into the user's branch yet
|
|
@@ -3122,6 +3741,17 @@ declare class TaskOrchestrator {
|
|
|
3122
3741
|
* so it starts once Merge all has merged that work, and a Stop withdraws it.
|
|
3123
3742
|
*/
|
|
3124
3743
|
startAtGate(taskId: string): void;
|
|
3744
|
+
/** A start of this task waits in the queue, and starts with nobody asked once what holds it clears. */
|
|
3745
|
+
startQueuedFor(taskId: string): boolean;
|
|
3746
|
+
/**
|
|
3747
|
+
* Start a task the user's own act asked for, under the one start rule and
|
|
3748
|
+
* past none of it (ADR-0015). A scheduler driving the run claims it as it
|
|
3749
|
+
* would any task; otherwise it waits with the queued starts for a slot, a
|
|
3750
|
+
* start hold or a usage limit, says what holds it, and a Stop withdraws it.
|
|
3751
|
+
* A conflict repair is started the same way, and this is what a resolver
|
|
3752
|
+
* added outside a run has in place of one.
|
|
3753
|
+
*/
|
|
3754
|
+
startWhenAllowed(taskId: string): void;
|
|
3125
3755
|
/**
|
|
3126
3756
|
* A forced start, from its run opening to its claim. It is judged again once
|
|
3127
3757
|
* the run has opened, against the task as it stands then, which is what
|
|
@@ -3160,8 +3790,53 @@ declare class TaskOrchestrator {
|
|
|
3160
3790
|
* still under way read as `dependencies` rather than `queued`.
|
|
3161
3791
|
*/
|
|
3162
3792
|
private holdsQueued;
|
|
3793
|
+
/**
|
|
3794
|
+
* Whether a start nobody asked for has to wait for a slot, wherever in the
|
|
3795
|
+
* tree they are held. Asked with no claim to follow, so it reserves to be
|
|
3796
|
+
* refused: the refusal is what has a slot freed elsewhere tick this Session
|
|
3797
|
+
* (ADR-0059 L1).
|
|
3798
|
+
*/
|
|
3163
3799
|
private slotsFull;
|
|
3800
|
+
/** The kept resumes the tree has room for now. A Stop or a retry since has cancelled the rest. */
|
|
3801
|
+
private offerKeptResumes;
|
|
3802
|
+
/** A pool's tick: it has nobody to tell of a failure, so it is said. */
|
|
3803
|
+
offered(): Promise<void>;
|
|
3804
|
+
/** The task's live attempt holds a slot: every one does but a delegated task's (ADR-0055 D18). */
|
|
3805
|
+
holdsSlot(taskId: string): boolean;
|
|
3806
|
+
/** The task's live attempt waits on this Session's planner: what lets a turn pass the limit (ADR-0055 D18). */
|
|
3807
|
+
waitsOnPlanner(taskId: string): boolean;
|
|
3808
|
+
/** A subplanner's turn found its runner's limit, the account's and so the tree's (ADR-0055 D18). */
|
|
3809
|
+
plannerLimited(runner: string, at: Date): void;
|
|
3810
|
+
limitFoundElsewhere(runner: string, at: Date): void;
|
|
3811
|
+
/** A planner turn's lease (ADR-0059 L1): a subplanner's waits its turn for a slot, and a root's is never held (ADR-0055 D18). */
|
|
3812
|
+
reserveTurn(): {
|
|
3813
|
+
lease: ReservedLease;
|
|
3814
|
+
} | {
|
|
3815
|
+
refused: string;
|
|
3816
|
+
};
|
|
3817
|
+
/** The tree's pool, which a child joins (ADR-0055 D18). */
|
|
3818
|
+
get slotPool(): SlotPool;
|
|
3819
|
+
/** A runner let go for the task has not gone yet. */
|
|
3820
|
+
windingDown(taskId: string): boolean;
|
|
3821
|
+
/** Every runner this Session let go has gone. */
|
|
3822
|
+
woundDown(): Promise<void>;
|
|
3823
|
+
/** Nothing the run started is still going, so a close has nothing to wait for. */
|
|
3824
|
+
get leftNothing(): boolean;
|
|
3825
|
+
/** Every runner let go has gone, with what a Stop left to end after it and whatever a backend had running past one, and the run changes git no more. What a next attempt comes back to stays. */
|
|
3826
|
+
allGone(): Promise<void>;
|
|
3827
|
+
/** The Session is closing: the tree stops counting on it. */
|
|
3828
|
+
leaveTree(): void;
|
|
3829
|
+
/** What the run left past its worktrees, as a Clean up gives it up (ADR-0059 L6). */
|
|
3830
|
+
reclaimLeases(): Promise<void>;
|
|
3831
|
+
private leaseRequest;
|
|
3832
|
+
/** What a start of `task` reserves: a delegated task takes a node and no slot, or a parent at its limit deadlocks on the children that need them (ADR-0055 D18). */
|
|
3833
|
+
/** Whether a start of `task` is its child plan's: a delegated task's repair is a plain runner's, which holds a slot and spends tokens (ADR-0055 D14). */
|
|
3834
|
+
private startsChildPlan;
|
|
3835
|
+
private attemptRequest;
|
|
3164
3836
|
private sayQueuedAtGate;
|
|
3837
|
+
/** A start asked for under the whole rule that the rule holds back, in words the user can act on; a turn's hold ends by itself. */
|
|
3838
|
+
private sayQueuedHeld;
|
|
3839
|
+
private sayOnce;
|
|
3165
3840
|
private refuseOpsDuringMerge;
|
|
3166
3841
|
/**
|
|
3167
3842
|
* A force start passes a merge gate (ADR-0020), and the surface confirmed it
|
|
@@ -3175,6 +3850,29 @@ declare class TaskOrchestrator {
|
|
|
3175
3850
|
isAnyFailed(): boolean;
|
|
3176
3851
|
approveReview(origin?: RunOrigin): Promise<void>;
|
|
3177
3852
|
tick(): Promise<void>;
|
|
3853
|
+
/**
|
|
3854
|
+
* A tick or an attempt's end is under way, so the run may yet go on or end,
|
|
3855
|
+
* and tell its supervisor which. A child read in that gap has neither, and
|
|
3856
|
+
* would be taken for one that sits on nothing (ADR-0056 M8). Only a child is
|
|
3857
|
+
* read that way, so a flat run's ticks take the turns they always took. A
|
|
3858
|
+
* close waits one out, at any level: its next step may be a release.
|
|
3859
|
+
*/
|
|
3860
|
+
private deciding;
|
|
3861
|
+
/** `work`, unchanged, as a close waits for it. */
|
|
3862
|
+
private underWay;
|
|
3863
|
+
private ticked;
|
|
3864
|
+
/** Why what is ready cannot start, with nothing live to free room for it: no event will tick this again (ADR-0056 M5). Null otherwise. */
|
|
3865
|
+
get refusedStart(): string | null;
|
|
3866
|
+
/**
|
|
3867
|
+
* The run moves with nobody asked: something is at work, a reset resumes it,
|
|
3868
|
+
* or a slot elsewhere in the tree starts what is ready (ADR-0055 D18). What
|
|
3869
|
+
* tells a child that sits on nothing from one that waits (ADR-0056 M8).
|
|
3870
|
+
*/
|
|
3871
|
+
get movesUnasked(): boolean;
|
|
3872
|
+
/** What is ready now, for a reader that asks far more often than a tick does, so it logs nothing. */
|
|
3873
|
+
private readyNow;
|
|
3874
|
+
/** One of a tick's starters: takes the next of `waiting` as each start it made has attached. */
|
|
3875
|
+
private startReady;
|
|
3178
3876
|
/**
|
|
3179
3877
|
* The one step that decides, with nothing at work and nothing the scheduler
|
|
3180
3878
|
* can start, whether the run goes on, is held, waits on the user or is over
|
|
@@ -3182,9 +3880,18 @@ declare class TaskOrchestrator {
|
|
|
3182
3880
|
* only an end emits it. A run the scheduler is not driving — tasks started
|
|
3183
3881
|
* on their own — ends on a verdict; a cancel, Mark complete or failed spawn
|
|
3184
3882
|
* just closes it, so the next run decides its own mode rather than inherit
|
|
3185
|
-
* this one's.
|
|
3883
|
+
* this one's. A loop carried on outside a scheduled run holds that run open
|
|
3884
|
+
* as a scheduled one is held, on whatever the start rule waits for.
|
|
3186
3885
|
*/
|
|
3187
3886
|
private settleRun;
|
|
3887
|
+
/**
|
|
3888
|
+
* What holds this run back is another Session's, not the user's: a slot, or a
|
|
3889
|
+
* usage limit a sibling found. Nothing here will tick for it, and what frees
|
|
3890
|
+
* it does, so no child parks waiting on a user (ADR-0055 D18). A flat run has
|
|
3891
|
+
* no such wait: an idle Session of one has its slots free.
|
|
3892
|
+
*/
|
|
3893
|
+
private waitsOnTree;
|
|
3894
|
+
private waitOnUser;
|
|
3188
3895
|
/**
|
|
3189
3896
|
* A loop's check failed (ADR-0045). With `failed` evidence and rounds left,
|
|
3190
3897
|
* a round starts: its body runs again as new attempts, each from the
|
|
@@ -3192,7 +3899,9 @@ declare class TaskOrchestrator {
|
|
|
3192
3899
|
* the failure is the round's, not the task's. Approval is not spent by a
|
|
3193
3900
|
* run, so the plan's approval of the body covers every round. Out of
|
|
3194
3901
|
* rounds, the body still to run will not run. A body task the user skipped
|
|
3195
|
-
* has stopped the loop (L7): no round starts, and the skip stands.
|
|
3902
|
+
* has stopped the loop (L7): no round starts, and the skip stands. One they
|
|
3903
|
+
* reverted keeps its hold, which a round takes as any start does (L5, ADR-0054):
|
|
3904
|
+
* the rest of the body runs, and the loop waits for them to say.
|
|
3196
3905
|
*/
|
|
3197
3906
|
private startRound;
|
|
3198
3907
|
/**
|
|
@@ -3208,6 +3917,53 @@ declare class TaskOrchestrator {
|
|
|
3208
3917
|
* complete, a reload in between — resumes the loop alike.
|
|
3209
3918
|
*/
|
|
3210
3919
|
private repeatChecks;
|
|
3920
|
+
private repeatCheck;
|
|
3921
|
+
/**
|
|
3922
|
+
* Something will run this check between rounds without being asked: a
|
|
3923
|
+
* scheduler, the one a reset gives back, or its loop carried on (ADR-0045
|
|
3924
|
+
* L5). What the seam reads before it says so to anyone.
|
|
3925
|
+
*/
|
|
3926
|
+
loopRunsOn(checkId: string): boolean;
|
|
3927
|
+
/** A start of this task would be its loop's next round: between rounds, its body landed, and nothing else will run it. */
|
|
3928
|
+
private ownsNextRound;
|
|
3929
|
+
/** A check between rounds that nothing will run: it waits on a person, its failure no longer one its loop answers (ADR-0045 L5, ADR-0053). */
|
|
3930
|
+
loopStranded(taskId: string): boolean;
|
|
3931
|
+
/** A tick starts something: the scheduler the plan, or what is carried on, those tasks alone. */
|
|
3932
|
+
private get startsOnTick();
|
|
3933
|
+
/** What is owed with no scheduler: the loops carried on, and the checks of a delegated task that ended. */
|
|
3934
|
+
private carriedOn;
|
|
3935
|
+
/**
|
|
3936
|
+
* The carried loops with work owed now: a check between rounds whose loop
|
|
3937
|
+
* goes on, or a round waiting to start. None under a scheduler, which owes
|
|
3938
|
+
* them itself, or while a usage limit holds the run, which starts nothing.
|
|
3939
|
+
* One a body task stopped is not here until that task passes (L7).
|
|
3940
|
+
*/
|
|
3941
|
+
private loopsCarriedOn;
|
|
3942
|
+
/**
|
|
3943
|
+
* The checks of a delegated task that ended, ready to start. Whatever start
|
|
3944
|
+
* ended it, a run with no scheduler would otherwise close under them with
|
|
3945
|
+
* their merge still held (ADR-0055 D8, D9). None under a scheduler, which
|
|
3946
|
+
* owes them itself, or while a usage limit holds the run. One behind a
|
|
3947
|
+
* failure or other unfinished work is not here: nothing is moving towards it.
|
|
3948
|
+
*/
|
|
3949
|
+
private checksCarriedOn;
|
|
3950
|
+
/** A delegated task passed, and nothing scheduled follows it. A Stop since the start that landed it leaves its checks where they are: a resolver's landing outlives one, with this task waiting on the user and no attempt to stop. */
|
|
3951
|
+
private carryChecks;
|
|
3952
|
+
/**
|
|
3953
|
+
* The run that carried them is over, by a Stop or by what gives the run up
|
|
3954
|
+
* or clears it up: a retry of a body task that passes runs that task alone.
|
|
3955
|
+
*/
|
|
3956
|
+
private endCarriedLoops;
|
|
3957
|
+
/** What a tick may start with no scheduler: what is carried on, and nothing that depends on it. */
|
|
3958
|
+
carriedTasks(): Set<string>;
|
|
3959
|
+
/**
|
|
3960
|
+
* A carried task outside the user's approval record waits as any does
|
|
3961
|
+
* (ADR-0045, Consent): starting a delegated task consents to that task alone,
|
|
3962
|
+
* and a script check's consent is to its body (ADR-0035). Said here, once, as
|
|
3963
|
+
* well as listed: a run they started one task of says nothing else of why the
|
|
3964
|
+
* next step does not come.
|
|
3965
|
+
*/
|
|
3966
|
+
private sayUnapprovedInLoop;
|
|
3211
3967
|
/** Skipped work is not completed work, so a run with any says so rather than that everything completed. */
|
|
3212
3968
|
private sayFinished;
|
|
3213
3969
|
/** How a run that ended on failures ends: what it finished, what failed, and what that blocks. */
|
|
@@ -3222,11 +3978,23 @@ declare class TaskOrchestrator {
|
|
|
3222
3978
|
/**
|
|
3223
3979
|
* Why a start may not take its claim now, or null when it may: a Stop came
|
|
3224
3980
|
* since it was admitted (ADR-0029), the task left the plan or is being
|
|
3225
|
-
* marked complete,
|
|
3226
|
-
*
|
|
3227
|
-
*
|
|
3981
|
+
* marked complete, this node may start nothing (ADR-0055 D16, ADR-0056 M10), a resolver has its conflict, so a start of it would be a
|
|
3982
|
+
* second worker on it (ADR-0015), a revert is taking back work it depends on
|
|
3983
|
+
* or skipped it since (ADR-0054), it
|
|
3984
|
+
* is outside the user's approval record (ADR-0035), its node's budget has no
|
|
3985
|
+
* room for it (ADR-0056 M5), or its lease cannot be
|
|
3986
|
+
* reserved, every slot being taken (ADR-0059 L1). Read in the same
|
|
3987
|
+
* synchronous step as the claim it guards, so nothing can change in between.
|
|
3228
3988
|
*/
|
|
3229
3989
|
private claimRefusal;
|
|
3990
|
+
/**
|
|
3991
|
+
* All of {@link claimRefusal} short of the lease: what a refusal keeps nobody
|
|
3992
|
+
* for. Whatever else a start spends is checked here, since every attempt
|
|
3993
|
+
* passes it. `revives` is a start asked of a task already skipped, as a force
|
|
3994
|
+
* start or a continue may be: only that runs one again. A retry has made it
|
|
3995
|
+
* pending by the time it claims.
|
|
3996
|
+
*/
|
|
3997
|
+
private startRefusal;
|
|
3230
3998
|
/** An explicit start's refusal, before it changes anything: its caller's answer, as a {@link TaskControlError}. */
|
|
3231
3999
|
private refuseClaim;
|
|
3232
4000
|
/** An explicit start's claim, once {@link refuseClaim} let it through: its spawn, or the refusal as a rejection. */
|
|
@@ -3234,8 +4002,10 @@ declare class TaskOrchestrator {
|
|
|
3234
4002
|
/**
|
|
3235
4003
|
* The one claim every attempt start passes — the scheduler's, a run or force
|
|
3236
4004
|
* start, a retry's, a continue, a resume, a repair. Checked and taken in one
|
|
3237
|
-
* synchronous step ({@link
|
|
3238
|
-
* no other start can take the same task or slot.
|
|
4005
|
+
* synchronous step ({@link startRefusal}, the lease's `reserve`, then
|
|
4006
|
+
* {@link Attempts.start}), so no other start can take the same task or slot.
|
|
4007
|
+
* `reserve` rather than `refusal` answers for the slot, since being turned
|
|
4008
|
+
* down is what keeps this Session for the slot that frees (ADR-0059 L1).
|
|
3239
4009
|
* The task is read here, as it stands: a start that awaited first — its run
|
|
3240
4010
|
* opening, the user's answer — runs what the plan holds now, not what it
|
|
3241
4011
|
* held when it was asked for. A task already claimed is not claimed again:
|
|
@@ -3247,9 +4017,10 @@ declare class TaskOrchestrator {
|
|
|
3247
4017
|
/**
|
|
3248
4018
|
* Replay the start a dirty tree turned away. `stash` puts the user's tracked
|
|
3249
4019
|
* changes on the git stash first, so the run isolates; `shared` runs this one
|
|
3250
|
-
* run in the workspace root, knowingly
|
|
4020
|
+
* run in the workspace root, knowingly; `reread` reads the tree again, which
|
|
4021
|
+
* may turn the start away again.
|
|
3251
4022
|
*/
|
|
3252
|
-
continueBlockedRun(how: 'stash' | 'shared'): Promise<void>;
|
|
4023
|
+
continueBlockedRun(how: 'stash' | 'shared' | 'reread'): Promise<void>;
|
|
3253
4024
|
}
|
|
3254
4025
|
|
|
3255
4026
|
/** One call at the command seam, as every route words it (ADR-0029). Task references are resolved here. */
|
|
@@ -3293,6 +4064,7 @@ type ExecutionCommand = {
|
|
|
3293
4064
|
/** Merge all: the run's landed work into the user's branch (ADR-0013). */
|
|
3294
4065
|
| {
|
|
3295
4066
|
command: 'merge_all';
|
|
4067
|
+
pastChecks?: true;
|
|
3296
4068
|
}
|
|
3297
4069
|
/** End a task as skipped: nothing it did lands, and its dependents go ahead without it once the work it waited on is done. `reason` is required of anyone but the user. */
|
|
3298
4070
|
| {
|
|
@@ -3325,6 +4097,18 @@ type ExecutionCommand = {
|
|
|
3325
4097
|
confirmed?: boolean;
|
|
3326
4098
|
seen?: TaskStatus;
|
|
3327
4099
|
}
|
|
4100
|
+
/**
|
|
4101
|
+
* The user takes a task's landed work off the integration branch, before
|
|
4102
|
+
* Merge all, with its landed dependents (ADR-0054). Needs `confirmed`, their
|
|
4103
|
+
* yes to what the preview listed; `seen` is the task ids it listed, and a
|
|
4104
|
+
* set that changed since is refused.
|
|
4105
|
+
*/
|
|
4106
|
+
| {
|
|
4107
|
+
command: 'revert_task';
|
|
4108
|
+
task: string;
|
|
4109
|
+
confirmed?: boolean;
|
|
4110
|
+
seen?: string[];
|
|
4111
|
+
}
|
|
3328
4112
|
/** Stop a structured task's running turn, keeping its session: it then waits for the user's message. */
|
|
3329
4113
|
| {
|
|
3330
4114
|
command: 'interrupt_task';
|
|
@@ -3357,6 +4141,7 @@ type ExecutionCommand = {
|
|
|
3357
4141
|
task: string;
|
|
3358
4142
|
answer: 'approve' | 'reject';
|
|
3359
4143
|
reason?: string;
|
|
4144
|
+
raiseTokens?: number;
|
|
3360
4145
|
}
|
|
3361
4146
|
/** The user signs off the plan's review: every task in it is approved, as executing it approves them, and it runs. */
|
|
3362
4147
|
| {
|
|
@@ -3398,6 +4183,16 @@ type CommandPayload =
|
|
|
3398
4183
|
| {
|
|
3399
4184
|
kind: 'merge';
|
|
3400
4185
|
result: IsolationMergeResult;
|
|
4186
|
+
}
|
|
4187
|
+
/** The user's `revert_task`, reverted or stopped: which tasks, or the task and files, or the commands that do it by hand. */
|
|
4188
|
+
| {
|
|
4189
|
+
kind: 'revert';
|
|
4190
|
+
result: IsolationRevertResult;
|
|
4191
|
+
}
|
|
4192
|
+
/** The user's `merge_all` asked first: what it would merge past are these checks, named as the plan names them, and `pastChecks` is the yes (ADR-0055 D9). */
|
|
4193
|
+
| {
|
|
4194
|
+
kind: 'merge_hold';
|
|
4195
|
+
checks: string[];
|
|
3401
4196
|
};
|
|
3402
4197
|
/**
|
|
3403
4198
|
* What a call came to: `message` is written for the caller, a model included,
|
|
@@ -3429,19 +4224,6 @@ type Consent = {
|
|
|
3429
4224
|
* body is never covered.
|
|
3430
4225
|
*/
|
|
3431
4226
|
type EffectAllowlist = (body: ScriptBody) => string | null;
|
|
3432
|
-
/**
|
|
3433
|
-
* What a supervisor at `level` may do. The mandate (#23) replaces this check;
|
|
3434
|
-
* nothing above it moves.
|
|
3435
|
-
*/
|
|
3436
|
-
type SupervisorPolicy = (level: SupervisorLevel, command: ExecutionCommandName) => Consent;
|
|
3437
|
-
/**
|
|
3438
|
-
* The supervisor levels (ADR-0029). Off: it does not act. Watch: it reads and
|
|
3439
|
-
* suggests, and every execution command it calls is refused. Act: every
|
|
3440
|
-
* command runs without asking — choosing Act is the consent — inside the loop
|
|
3441
|
-
* guards; what a command may never do, like allowing an approval, is still
|
|
3442
|
-
* refused by the command itself.
|
|
3443
|
-
*/
|
|
3444
|
-
declare const SUPERVISOR_LEVELS: SupervisorPolicy;
|
|
3445
4227
|
/**
|
|
3446
4228
|
* A check that stops an actor spinning (ADR-0029's loop guards): the trip —
|
|
3447
4229
|
* the note naming the guard and what would be accepted, and what the user is
|
|
@@ -3470,6 +4252,8 @@ interface ExecutionHost {
|
|
|
3470
4252
|
waitsForApproval(taskId: string): boolean;
|
|
3471
4253
|
/** A start the user consented to approves these tasks, before it acts. */
|
|
3472
4254
|
approve(taskIds: readonly string[]): void;
|
|
4255
|
+
/** A start under Full with autorun makes the plan approved, as autorun's own start does, so nothing later in the session is refused for it (ADR-0030). */
|
|
4256
|
+
approvePlan(): void;
|
|
3473
4257
|
/** Full autonomy: starts follow plan approval without a question. */
|
|
3474
4258
|
autonomous(): boolean;
|
|
3475
4259
|
/** The user's autorun setting, as it is now (ADR-0030). */
|
|
@@ -3480,17 +4264,35 @@ interface ExecutionHost {
|
|
|
3480
4264
|
startsHeld(): boolean;
|
|
3481
4265
|
/** Work is running right now. */
|
|
3482
4266
|
hasLiveWork(): boolean;
|
|
4267
|
+
/** A usage limit holds the run: what it paused resumes at the reset. */
|
|
4268
|
+
runHeld(): boolean;
|
|
4269
|
+
/** A scheduled run is open, driving the plan or held by a usage limit that gives it back, whether or not anything is live. */
|
|
4270
|
+
scheduledRun(): boolean;
|
|
3483
4271
|
/** Something will start without being asked again: a start admitted and not yet claimed, or a scheduled resume. */
|
|
3484
4272
|
startsPending(): boolean;
|
|
4273
|
+
/** A plan the turn in flight submitted, whose start autorun makes as the turn ends (ADR-0030): a start on its way that no run holds yet. */
|
|
4274
|
+
submittedStartWaits(): boolean;
|
|
4275
|
+
/** A loop is carried on, one a body task stopped included; see {@link TaskOrchestrator.loopCarried}. */
|
|
4276
|
+
loopCarried(): boolean;
|
|
4277
|
+
/** A run with nothing starting that something still resumes: a usage limit's reset, or a retry of a failure; see {@link TaskOrchestrator.awaitsResume}. */
|
|
4278
|
+
awaitsResume(): boolean;
|
|
4279
|
+
/** Something will run this loop's check between rounds without being asked; see {@link TaskOrchestrator.loopRunsOn}. */
|
|
4280
|
+
loopRunsOn(taskId: string): boolean;
|
|
3485
4281
|
/** Something could move a task on without being asked: a start, an attempt in any phase, the scheduler or a usage-limit hold. */
|
|
3486
4282
|
advancesOnItsOwn(): boolean;
|
|
3487
4283
|
/** Admit a start that waits before it claims; see {@link StartAdmission}. */
|
|
3488
4284
|
admitStart(): StartAdmission;
|
|
3489
4285
|
/** The task's attempt is live: starting, running or landing. */
|
|
3490
4286
|
running(taskId: string): boolean;
|
|
4287
|
+
/** Its live attempt holds a slot, as a delegated task's does not (ADR-0055 D18). */
|
|
4288
|
+
holdsSlot(taskId: string): boolean;
|
|
4289
|
+
/** A conflict repair of the task will start by itself: there is a start to withdraw (ADR-0015). */
|
|
4290
|
+
repairOwed(taskId: string): boolean;
|
|
3491
4291
|
maxParallel(): number;
|
|
3492
4292
|
/** The run waits on the user to stash or skip isolation before anything starts. */
|
|
3493
4293
|
runBlocked(): boolean;
|
|
4294
|
+
/** Why nothing may start here, as every surface says it: another host holds the session (ADR-0049). */
|
|
4295
|
+
heldRefusal(): string | null;
|
|
3494
4296
|
/**
|
|
3495
4297
|
* Every reason the task cannot start now, from the scheduler's one start
|
|
3496
4298
|
* rule (ADR-0034). Takes the task, not its id: the one the seam located.
|
|
@@ -3507,15 +4309,29 @@ interface ExecutionHost {
|
|
|
3507
4309
|
* `left` still wait. Answers the line that says so.
|
|
3508
4310
|
*/
|
|
3509
4311
|
joinRun(approved: number, left: number): Promise<string>;
|
|
4312
|
+
/** The fresh chance the user's Execute gives what failed, for work it takes in (ADR-0053); none while the scheduler drives the run. */
|
|
4313
|
+
readyFailed(): void;
|
|
3510
4314
|
startTask(taskId: string, actor: ExecutionActor): Promise<void>;
|
|
3511
4315
|
/** Force start the task; answers the line saying it waits for its dependencies, when it was queued behind them rather than started. */
|
|
3512
4316
|
forceStart(taskId: string): Promise<string | undefined>;
|
|
3513
4317
|
markComplete(taskId: string): Promise<void>;
|
|
3514
4318
|
markNotDone(taskId: string): Promise<void>;
|
|
4319
|
+
/** What reverting the task would take, as far as the plan can say; see {@link TaskOrchestrator.revertScope}. */
|
|
4320
|
+
revertScope(taskId: string): RevertScope;
|
|
4321
|
+
/** Revert the task's landed work, through the queue it shares with landings. */
|
|
4322
|
+
revertTask(taskId: string): Promise<IsolationRevertResult>;
|
|
3515
4323
|
interrupt(taskId: string): Promise<void>;
|
|
3516
|
-
|
|
3517
|
-
|
|
4324
|
+
/** `actor` is who stopped it: the user's stop holds the supervisor back from it (ADR-0029). */
|
|
4325
|
+
stopTask(taskId: string, actor: ExecutionActor): Promise<void>;
|
|
4326
|
+
/** `actor` is who stopped it: the user's Stop stands the supervisor down (ADR-0029). */
|
|
4327
|
+
stopRun(actor: ExecutionActor): void;
|
|
4328
|
+
/** The user's Stop found nothing to stop: what was admitted before it is withdrawn all the same. */
|
|
4329
|
+
stopAsked(): void;
|
|
4330
|
+
/** A start cleared its last check and is about to act; the user's ends their Stop (ADR-0029). */
|
|
4331
|
+
startAsked(actor: ExecutionActor): void;
|
|
3518
4332
|
retryTask(taskId: string, actor: ExecutionActor): Promise<void>;
|
|
4333
|
+
/** Whether the task is a delegated task's check (ADR-0055 D8). */
|
|
4334
|
+
checksDelegatedTask(taskId: string): boolean;
|
|
3519
4335
|
/** End the task as skipped, landing nothing of it; see {@link TaskOrchestrator.skipTask}. */
|
|
3520
4336
|
skipTask(taskId: string, reason: string | undefined, actor: ExecutionActor): Promise<void>;
|
|
3521
4337
|
continueTask(taskId: string, message: string, actor: ExecutionActor): Promise<void>;
|
|
@@ -3532,7 +4348,11 @@ interface ExecutionHost {
|
|
|
3532
4348
|
cancelResume(taskId: string): Promise<boolean>;
|
|
3533
4349
|
/** The task waits at a checkpoint, and a runner is left to hear the answer. */
|
|
3534
4350
|
awaitsCheckpoint(taskId: string): boolean;
|
|
3535
|
-
answerCheckpoint(taskId: string, approve: boolean, reason?: string): void;
|
|
4351
|
+
answerCheckpoint(taskId: string, approve: boolean, reason?: string, note?: string): void;
|
|
4352
|
+
/** The checks that hold every merge but the user's (ADR-0055 D9), each as its row names it. */
|
|
4353
|
+
mergeHold(): readonly string[];
|
|
4354
|
+
/** A raise for a delegated task's child, from what this node has left (ADR-0056 M5). Null when it took; otherwise why not. */
|
|
4355
|
+
raiseChild(taskId: string, tokens: number): Promise<string | null>;
|
|
3536
4356
|
/** Sign off the review: the plan is the user's, and runs. */
|
|
3537
4357
|
approveReview(): Promise<void>;
|
|
3538
4358
|
/** Answer a runner's request, as its card does; false once it was answered or withdrawn. */
|
|
@@ -3568,6 +4388,12 @@ interface ExecutionHost {
|
|
|
3568
4388
|
awaitEnd(taskId: string, ms: number, signal?: AbortSignal): Promise<void>;
|
|
3569
4389
|
/** The task's result is owed to the planner, in a turn acting for whoever started it (ADR-0037, R2, R3). */
|
|
3570
4390
|
owe(taskId: string, to: TaskReportTo): void;
|
|
4391
|
+
/** What waits on a person now, derived afresh (ADR-0053). */
|
|
4392
|
+
escalations(): readonly Escalation[];
|
|
4393
|
+
/** Add the task that merges a conflicted task's branch by hand; false when it has no conflict left. */
|
|
4394
|
+
resolveConflict(taskId: string): Promise<boolean>;
|
|
4395
|
+
/** Replay the run a dirty checkout turned away, stashing first or for this run without isolation. */
|
|
4396
|
+
continueRun(how: 'stash' | 'shared'): Promise<void>;
|
|
3571
4397
|
/** The end of a task's output, as a planner turn is told it; see {@link taskReport}. */
|
|
3572
4398
|
reportTail(taskId: string): string | undefined;
|
|
3573
4399
|
}
|
|
@@ -3575,7 +4401,8 @@ interface ExecutionCommandsDeps {
|
|
|
3575
4401
|
host: ExecutionHost;
|
|
3576
4402
|
/** The approval card channel a Guarded start asks through. */
|
|
3577
4403
|
consent: Pick<IApproval, 'request'>;
|
|
3578
|
-
|
|
4404
|
+
/** What this node may do unasked, read at each check (ADR-0056 M1); a root with nothing past what the host says unless set. */
|
|
4405
|
+
authority?: NodeAuthority;
|
|
3579
4406
|
guards?: readonly LoopGuard[];
|
|
3580
4407
|
/** What pre-approves a script's effect (ADR-0035); nothing does unless set. */
|
|
3581
4408
|
effects?: EffectAllowlist;
|
|
@@ -3595,7 +4422,7 @@ interface ExecutionCommandsDeps {
|
|
|
3595
4422
|
declare class ExecutionCommands {
|
|
3596
4423
|
private readonly deps;
|
|
3597
4424
|
private readonly host;
|
|
3598
|
-
private readonly
|
|
4425
|
+
private readonly authority;
|
|
3599
4426
|
private readonly guards;
|
|
3600
4427
|
private readonly effects;
|
|
3601
4428
|
private readonly now;
|
|
@@ -3619,6 +4446,15 @@ declare class ExecutionCommands {
|
|
|
3619
4446
|
* committed, its own edits in the turn included (ADR-0022 P2).
|
|
3620
4447
|
*/
|
|
3621
4448
|
run(asked: ExecutionCommand, actor: ExecutionActor, signal?: AbortSignal): Promise<CommandOutcome>;
|
|
4449
|
+
/**
|
|
4450
|
+
* The user's answer to an escalation (ADR-0053): the list derived afresh,
|
|
4451
|
+
* and the option chosen dispatched to the existing command for that wait, as
|
|
4452
|
+
* the user, so every check it has still applies and this adds no authority.
|
|
4453
|
+
* It takes no actor because it is the user's alone: no planner tool reaches
|
|
4454
|
+
* it, and the supervisor keeps its own tools. `confirmed` is the user's yes to
|
|
4455
|
+
* an option's `confirm`, which a choice cannot imply.
|
|
4456
|
+
*/
|
|
4457
|
+
answerEscalation(id: string, option: string, note?: string, confirmed?: boolean, raiseTokens?: number): Promise<CommandOutcome>;
|
|
3622
4458
|
/** A valid, consented call, from the user's answer where one is needed to the act and its record. */
|
|
3623
4459
|
private carryOut;
|
|
3624
4460
|
/**
|
|
@@ -3641,28 +4477,32 @@ declare class ExecutionCommands {
|
|
|
3641
4477
|
private startScript;
|
|
3642
4478
|
/**
|
|
3643
4479
|
* Why a script task cannot start as `run_script` would start it, but for its
|
|
3644
|
-
* merge gate, at which it waits:
|
|
3645
|
-
* finished, a Merge all under way, every
|
|
4480
|
+
* merge gate, at which it waits: another host holding the session, a
|
|
4481
|
+
* dependency that failed or has not finished, a Merge all under way, every
|
|
4482
|
+
* slot taken. Null when it can.
|
|
3646
4483
|
*/
|
|
3647
4484
|
private scriptUnready;
|
|
3648
4485
|
/**
|
|
3649
|
-
* Who may run a script
|
|
3650
|
-
*
|
|
3651
|
-
*
|
|
3652
|
-
*
|
|
3653
|
-
* supervisor's level decides for it first: at Watch it is refused,
|
|
3654
|
-
* suggest it instead, covered or not; at Act it runs, the task it adds
|
|
3655
|
-
* being approved (ADR-0029).
|
|
4486
|
+
* Who may run a script, as ADR-0035's table says. An effect the user's
|
|
4487
|
+
* allowlist covers runs in every row but one, and is recorded by its rule.
|
|
4488
|
+
* In the user's turn: otherwise autorun in Full runs it, on a first plan as
|
|
4489
|
+
* on an approved one (ADR-0030), and failing that they are asked on the
|
|
4490
|
+
* card. The supervisor's level decides for it first: at Watch it is refused,
|
|
4491
|
+
* to suggest it instead, covered or not; at Act it runs, the task it adds
|
|
4492
|
+
* being approved (ADR-0029). A subplanner's is its grants alone (ADR-0056 M6).
|
|
3656
4493
|
*/
|
|
3657
4494
|
private scriptConsent;
|
|
3658
4495
|
/**
|
|
3659
|
-
* Of the tasks a planner edit
|
|
3660
|
-
*
|
|
3661
|
-
*
|
|
3662
|
-
*
|
|
3663
|
-
*
|
|
4496
|
+
* Of the tasks a planner edit wrote, the ones autorun approves as the edit
|
|
4497
|
+
* commits. Under Full every one of them, a rewritten script's new body
|
|
4498
|
+
* included, for the user's turn and a supervisor at Act alike. Otherwise only
|
|
4499
|
+
* in the user's turn, and all but a script task, which runs unasked only
|
|
4500
|
+
* where `run_script` would run it unasked (ADR-0035), so under Guarded it
|
|
4501
|
+
* waits for the user unless their effect allowlist covers it. Its row shows
|
|
4502
|
+
* the body verbatim, and starting it is their consent. Below the root this
|
|
4503
|
+
* is the `approve` grant (ADR-0056 M6).
|
|
3664
4504
|
*/
|
|
3665
|
-
autorunApproves(written: readonly Readonly<Task>[]): string[];
|
|
4505
|
+
autorunApproves(actor: ExecutionActor, written: readonly Readonly<Task>[]): string[];
|
|
3666
4506
|
/**
|
|
3667
4507
|
* A task `run_script` answered for before it ended has ended: its result
|
|
3668
4508
|
* joins the timeline beside its start, with who asked and how it was
|
|
@@ -3674,16 +4514,22 @@ declare class ExecutionCommands {
|
|
|
3674
4514
|
* The tasks a start approves, read from the plan as it stands at the
|
|
3675
4515
|
* command's last check. Autorun starts a plan as the user's standing
|
|
3676
4516
|
* instruction, so its start approves what it runs as the user's does; so
|
|
3677
|
-
* does a start under
|
|
3678
|
-
*
|
|
4517
|
+
* does a start under Full with autorun. Under Guarded it leaves a script task
|
|
4518
|
+
* the commit left unapproved: that waits for the user (ADR-0035). A yes on
|
|
4519
|
+
* the card approves the tasks the card named, and no others.
|
|
3679
4520
|
*/
|
|
3680
4521
|
private consented;
|
|
3681
4522
|
/**
|
|
3682
|
-
* With autorun on and Full, a planner turn
|
|
3683
|
-
*
|
|
3684
|
-
*
|
|
4523
|
+
* With autorun on and Full, nobody is asked: a planner turn, or a supervisor
|
|
4524
|
+
* its level lets act, may start anything, on a first plan as on an approved
|
|
4525
|
+
* one (ADR-0030). Read at each start, so switching either off stops it at
|
|
4526
|
+
* once. Below Act the level has refused the call before this is read. A
|
|
4527
|
+
* subplanner has nobody to ask, so `approve` alone says it: its `autonomy`
|
|
4528
|
+
* says what its runners may do, not whether a person is asked (ADR-0056 M7).
|
|
3685
4529
|
*/
|
|
3686
|
-
private
|
|
4530
|
+
private startsUnattended;
|
|
4531
|
+
/** The mandate that answers for `actor` now: read at each check, so a change reaches the next one (ADR-0056 M1). */
|
|
4532
|
+
private mandateOf;
|
|
3687
4533
|
/**
|
|
3688
4534
|
* Guarded means "ask the user first": a planner start in the user's own
|
|
3689
4535
|
* turn asks, so tasks they have not approved go into the question rather
|
|
@@ -3692,12 +4538,23 @@ declare class ExecutionCommands {
|
|
|
3692
4538
|
*/
|
|
3693
4539
|
private asksToApprove;
|
|
3694
4540
|
/**
|
|
3695
|
-
* Who may do what
|
|
3696
|
-
* consent, and their own controls are theirs alone; a
|
|
3697
|
-
*
|
|
3698
|
-
*
|
|
4541
|
+
* Who may do what, in the one place it is decided (ADR-0056 M6): the user's
|
|
4542
|
+
* own call needs no consent, and their own controls are theirs alone; a turn
|
|
4543
|
+
* the user opened keeps ADR-0029's table, since a person needs no mandate: it
|
|
4544
|
+
* may always end or steer work, and starts it only as the autonomy level says.
|
|
4545
|
+
* The supervisor's level decides for it through its mandate, and a subplanner
|
|
4546
|
+
* has its grants alone, allow or refuse: nobody is there to ask.
|
|
4547
|
+
*/
|
|
4548
|
+
consent(actor: ExecutionActor, command: ExecutionCommandName): Consent;
|
|
4549
|
+
private supervisorConsent;
|
|
4550
|
+
private grantConsent;
|
|
4551
|
+
/**
|
|
4552
|
+
* Autorun is the user's standing instruction, so at the root it is not held
|
|
4553
|
+
* to a level: Watch has no `control`, and autorun still starts its plan. Below
|
|
4554
|
+
* the root there is no user behind it, and `approve` and `control` narrow it
|
|
4555
|
+
* (ADR-0056 M6).
|
|
3699
4556
|
*/
|
|
3700
|
-
private
|
|
4557
|
+
private autorunConsent;
|
|
3701
4558
|
/**
|
|
3702
4559
|
* A checkpoint asks a person for judgement on the work, so the user answers
|
|
3703
4560
|
* it from the task's card; the supervisor may only at Act, in a wake-up turn
|
|
@@ -3712,8 +4569,16 @@ declare class ExecutionCommands {
|
|
|
3712
4569
|
*/
|
|
3713
4570
|
private prepare;
|
|
3714
4571
|
private prepareRunPlan;
|
|
4572
|
+
/**
|
|
4573
|
+
* What a planner is told of its `run_plan`: it leaves a failure as it is
|
|
4574
|
+
* (ADR-0053), so the line says so, and where nothing was left to start the
|
|
4575
|
+
* run has ended again and the line does not say it runs.
|
|
4576
|
+
*/
|
|
4577
|
+
private runningLine;
|
|
3715
4578
|
/** A start of one task: `run_task`, or a fresh `retry_task`, which also takes a task that failed or waits on the user. */
|
|
3716
4579
|
private prepareStart;
|
|
4580
|
+
/** Why the work this task builds on keeps a start of it, a fresh one or a continue, from running now; null when it does not. */
|
|
4581
|
+
private heldBehind;
|
|
3717
4582
|
/**
|
|
3718
4583
|
* The user's force start goes past what the scheduler waits for, so only
|
|
3719
4584
|
* what no start could get past is refused here; the start rule decides the
|
|
@@ -3745,6 +4610,13 @@ declare class ExecutionCommands {
|
|
|
3745
4610
|
private overriddenBy;
|
|
3746
4611
|
private prepareMarkComplete;
|
|
3747
4612
|
private prepareMarkNotDone;
|
|
4613
|
+
/**
|
|
4614
|
+
* A revert asks nothing of the run, so unlike an override it waits for no
|
|
4615
|
+
* task that does not depend on the work (ADR-0054). What only git can say —
|
|
4616
|
+
* that it is in the user's branch, that it conflicts — it says as it runs,
|
|
4617
|
+
* in its turn on the queue.
|
|
4618
|
+
*/
|
|
4619
|
+
private prepareRevert;
|
|
3748
4620
|
private prepareInterrupt;
|
|
3749
4621
|
private prepareCancelResume;
|
|
3750
4622
|
private prepareCheckpoint;
|
|
@@ -3756,6 +4628,8 @@ declare class ExecutionCommands {
|
|
|
3756
4628
|
*/
|
|
3757
4629
|
private prepareResume;
|
|
3758
4630
|
private prepareStop;
|
|
4631
|
+
/** What a refused Stop of a conflicted task can do instead: nothing runs it, so there is something else to press. */
|
|
4632
|
+
private conflictNext;
|
|
3759
4633
|
private prepareStopRun;
|
|
3760
4634
|
private prepareMessage;
|
|
3761
4635
|
/** A message queued behind the running turn, sent now or taken back; one delivered meanwhile is past either. */
|
|
@@ -3774,9 +4648,11 @@ declare class ExecutionCommands {
|
|
|
3774
4648
|
*/
|
|
3775
4649
|
private skippedRefusal;
|
|
3776
4650
|
/**
|
|
3777
|
-
* Why a loop's check between rounds is not started from the seam:
|
|
3778
|
-
*
|
|
3779
|
-
*
|
|
4651
|
+
* Why a loop's check between rounds is not started from the seam: something
|
|
4652
|
+
* will run it, once its body has landed, or nothing will and its body has
|
|
4653
|
+
* yet to land (ADR-0045 L5). Each says only what is true of it. Null for any
|
|
4654
|
+
* other task, and for a check whose fix has landed that nothing else will
|
|
4655
|
+
* run, which a start runs as its next round rather than leave it stranded.
|
|
3780
4656
|
*/
|
|
3781
4657
|
private betweenRounds;
|
|
3782
4658
|
/**
|
|
@@ -3956,12 +4832,26 @@ interface PlanChangeScope {
|
|
|
3956
4832
|
catalog(runners: RunnerId[]): AssignmentCatalog & {
|
|
3957
4833
|
runnerModes?: Record<RunnerId, RunnerModeInfo[]>;
|
|
3958
4834
|
};
|
|
4835
|
+
/**
|
|
4836
|
+
* The node a change is made on, with what it holds now and how far below the
|
|
4837
|
+
* root it stands, read as each check runs (ADR-0056 M4). Absent or undefined,
|
|
4838
|
+
* nothing may delegate: a one-shot planner has no node, and a build that does
|
|
4839
|
+
* not offer delegation reads no mandate for it.
|
|
4840
|
+
*/
|
|
4841
|
+
node?(): {
|
|
4842
|
+
mandate: Mandate;
|
|
4843
|
+
level: number;
|
|
4844
|
+
} | undefined;
|
|
4845
|
+
/** Whether a script can run sealed here (ADR-0036 S6): a change that brings a read-only one waits on this, as an attached skill waits on its lookup. */
|
|
4846
|
+
canSeal?(): Promise<boolean>;
|
|
3959
4847
|
/** Where attached skill names are looked up; absent, none are. */
|
|
3960
4848
|
skills?(): SkillLookup;
|
|
3961
4849
|
/** The handles the open turn's committed edits gave, each with its task's id, for a later batch to name them by (ADR-0022 P2). */
|
|
3962
4850
|
handles?(): ReadonlyMap<string, string>;
|
|
3963
4851
|
/** A further refusal of what the change leaves: the supervisor's oscillation guard (ADR-0029). */
|
|
3964
4852
|
guard?(before: readonly Task[], after: readonly Task[]): string | undefined;
|
|
4853
|
+
/** The node, below the root: a child's change is held to its mandate, where a commit would otherwise approve with no command (ADR-0056 M6). Absent, or undefined, at the root. */
|
|
4854
|
+
child?(): NodeAuthority | undefined;
|
|
3965
4855
|
}
|
|
3966
4856
|
/** What a whole plan's JSON is held to as it is submitted. */
|
|
3967
4857
|
interface PlanIntake {
|
|
@@ -3994,10 +4884,41 @@ declare class PlanChangeCheck {
|
|
|
3994
4884
|
checkNow<P extends CheckPhase>(change: PlannerChange<P>, phase: P): CheckedChange;
|
|
3995
4885
|
/** A plan's JSON read into tasks as it is submitted; nothing in it reads the plan. */
|
|
3996
4886
|
private read;
|
|
4887
|
+
/** Whether this node may write a delegated task: read on every route, since a parse that took one anyway would only be refused later (ADR-0055 D21). */
|
|
4888
|
+
private delegation;
|
|
4889
|
+
/** Only such a change waits on the probe, so a flat plan's check takes the turns it always took. */
|
|
4890
|
+
private bringsSealedScript;
|
|
3997
4891
|
private rules;
|
|
4892
|
+
/** What a child's mandate leaves out of this change: `replan` for any, and `research` for a research task it brings. */
|
|
4893
|
+
private ungranted;
|
|
4894
|
+
/**
|
|
4895
|
+
* What a change leaves past this node's limits (ADR-0055 D2, D19): each
|
|
4896
|
+
* delegated task it wrote narrowed as it is written (ADR-0056 M4), so a plan
|
|
4897
|
+
* never holds what its carve would refuse, and a child held to what a child
|
|
4898
|
+
* plan may be. Only what this change wrote: what stands in the plan is not
|
|
4899
|
+
* this edit's to answer for. A root plan has no task limit, so a flat run
|
|
4900
|
+
* does not change.
|
|
4901
|
+
*/
|
|
4902
|
+
private pastMandate;
|
|
3998
4903
|
private refused;
|
|
3999
4904
|
}
|
|
4000
4905
|
|
|
4906
|
+
/** What a planner that may delegate is told of its limits (ADR-0055 D19). */
|
|
4907
|
+
interface PlannerDelegation {
|
|
4908
|
+
tokens: number;
|
|
4909
|
+
delegatedTasks: number;
|
|
4910
|
+
/** What a delegated task of this plan can ask for past the floor. */
|
|
4911
|
+
grantable: readonly string[];
|
|
4912
|
+
}
|
|
4913
|
+
/** What a subplanner is told of what it was given (ADR-0055 D4). */
|
|
4914
|
+
interface SubplannerBrief {
|
|
4915
|
+
/** Its own and its ancestors': a change to one fails its verdict (D7). */
|
|
4916
|
+
protectedPaths: readonly string[];
|
|
4917
|
+
readOnly: boolean;
|
|
4918
|
+
/** The runner it plans on. */
|
|
4919
|
+
runner: RunnerId;
|
|
4920
|
+
}
|
|
4921
|
+
|
|
4001
4922
|
/**
|
|
4002
4923
|
* How much of its model's window an API planner's next call may fill. The
|
|
4003
4924
|
* check runs before every call, against the model configured at that moment,
|
|
@@ -4086,6 +5007,8 @@ interface CliAgentAiServiceDeps extends Partial<AgentProcessDeps> {
|
|
|
4086
5007
|
projectServerApprovals?: ProjectServerApprovals;
|
|
4087
5008
|
/** What the planner is shown of its context and budgets at the start of each turn. */
|
|
4088
5009
|
turnBudgets?: TurnBudgets;
|
|
5010
|
+
/** Open the execution lease of the turn a process starts for (ADR-0059 L1); absent, it runs at `workspaceRoot`. */
|
|
5011
|
+
openLease?: (signal: AbortSignal) => Promise<OpenLease> | undefined;
|
|
4089
5012
|
}
|
|
4090
5013
|
/**
|
|
4091
5014
|
* A coding agent driven as Ordewell's planner (ADR-0009).
|
|
@@ -4112,6 +5035,7 @@ declare class CliAgentAiService implements IAiService {
|
|
|
4112
5035
|
private readonly mcpServer;
|
|
4113
5036
|
private readonly turnBudgets;
|
|
4114
5037
|
private readonly projectServerApprovals;
|
|
5038
|
+
private readonly openLease;
|
|
4115
5039
|
private activeAbort;
|
|
4116
5040
|
/** See {@link compactions}. */
|
|
4117
5041
|
private compacted;
|
|
@@ -4132,6 +5056,7 @@ declare class CliAgentAiService implements IAiService {
|
|
|
4132
5056
|
nativeSessionId(): string | null;
|
|
4133
5057
|
/** The compactions the agents reported of their own context, never a subagent's or another thread's: their adapters drop those (ADR-0012 T10). */
|
|
4134
5058
|
compactions(): number;
|
|
5059
|
+
promptCacheTtlMs(): number | undefined;
|
|
4135
5060
|
heldSecrets(): readonly string[];
|
|
4136
5061
|
restart(): void;
|
|
4137
5062
|
reset(): void;
|
|
@@ -4304,7 +5229,17 @@ interface LandedHistory {
|
|
|
4304
5229
|
*/
|
|
4305
5230
|
interface PlannerToolsOffer {
|
|
4306
5231
|
sessionId: string;
|
|
5232
|
+
/** The tools a child's grants leave out of its list, fixed as its session starts (ADR-0056 M6); the root's list is not filtered. */
|
|
5233
|
+
withheld?: readonly string[];
|
|
4307
5234
|
handler: PlannerToolHandler;
|
|
5235
|
+
/** Its `submit_plan` takes a delegated task (ADR-0055 D1). */
|
|
5236
|
+
delegates?: boolean;
|
|
5237
|
+
/** A subplanner's: its token serves `task_complete` and `checkpoint` too, for the handler's `taskComplete` and `checkpoint` (D5). */
|
|
5238
|
+
subplanner?: boolean;
|
|
5239
|
+
/** Its harness's own subagents are withheld: nothing refuses what they spend, so a subplanner has them only with `research` (ADR-0056 M6). */
|
|
5240
|
+
noSubagents?: true;
|
|
5241
|
+
/** What a subplanner's process loads of the user's setup: its tasks' setting holds for it too (ADR-0057 R11). */
|
|
5242
|
+
runnerConfig?: TaskRunnerConfig;
|
|
4308
5243
|
}
|
|
4309
5244
|
/**
|
|
4310
5245
|
* Everything the conversation loop needs to start planning (ADR-0002).
|
|
@@ -4345,6 +5280,10 @@ interface ConversationRequest {
|
|
|
4345
5280
|
*/
|
|
4346
5281
|
initialMessage?: string;
|
|
4347
5282
|
plannerTools?: PlannerToolsOffer;
|
|
5283
|
+
/** Teaches the planner delegation, only where its mandate holds `delegate` (ADR-0055 D21). */
|
|
5284
|
+
delegation?: PlannerDelegation;
|
|
5285
|
+
/** The prompt is a subplanner's, whose parent stands where the user does (ADR-0055 D4). */
|
|
5286
|
+
subplanner?: SubplannerBrief;
|
|
4348
5287
|
/**
|
|
4349
5288
|
* The session's notice channel, for a warning the planner's surface should
|
|
4350
5289
|
* show once (ADR-0036 N4: the native-shell setting is on but the harness is
|
|
@@ -4501,6 +5440,8 @@ interface IAiService {
|
|
|
4501
5440
|
* T10). Absent where nothing compacts a context in place.
|
|
4502
5441
|
*/
|
|
4503
5442
|
compactions?(): number;
|
|
5443
|
+
/** How long this planner's prompt cache lasts, as its connector states it; absent when it states none (ADR-0057 R4). */
|
|
5444
|
+
promptCacheTtlMs?(): number | undefined;
|
|
4504
5445
|
/**
|
|
4505
5446
|
* Optional: what automatic compaction does for the planner's model now
|
|
4506
5447
|
* (ADR-0002) — on, off in the settings file, or off for want of a known
|
|
@@ -4684,6 +5625,14 @@ declare class PlannerTurn {
|
|
|
4684
5625
|
}
|
|
4685
5626
|
/** What a planner turn may change: the whole plan, or tasks through edits. */
|
|
4686
5627
|
type PlanChange = 'plan' | 'edit';
|
|
5628
|
+
/** A wake-up turn's brief, as `PlannerBriefing` sends it: whole to a context that does not hold it, else a line on a change (ADR-0057 R5). */
|
|
5629
|
+
interface WakeBrief {
|
|
5630
|
+
/** Which brief this is: a level's, or a report turn's. */
|
|
5631
|
+
key: string;
|
|
5632
|
+
whole: string;
|
|
5633
|
+
/** All a context holding {@link whole} needs told, and all that may differ between two wake-ups of one brief. */
|
|
5634
|
+
line: string;
|
|
5635
|
+
}
|
|
4687
5636
|
/**
|
|
4688
5637
|
* A wake-up turn (ADR-0029): a supervisor's turn on wake-up digests alone, no
|
|
4689
5638
|
* user message in it. What it may do is its level's, decided by the host.
|
|
@@ -4698,7 +5647,7 @@ interface WakeUpTurn {
|
|
|
4698
5647
|
*/
|
|
4699
5648
|
refused(change: PlanChange): string | undefined;
|
|
4700
5649
|
/** Told to the model after the digests and never saved, like the plan block: who it is in this turn, and what it may do. */
|
|
4701
|
-
brief?:
|
|
5650
|
+
brief?: WakeBrief;
|
|
4702
5651
|
/**
|
|
4703
5652
|
* Who the turn acts for at the command seam, read at each call; absent, the
|
|
4704
5653
|
* supervisor at the run's level. A turn on a report owed to the user's turn
|
|
@@ -4747,6 +5696,8 @@ interface PlannerConversationHost {
|
|
|
4747
5696
|
goal(): string;
|
|
4748
5697
|
aiService(): IAiService;
|
|
4749
5698
|
onProgress(progress: ResearchProgress): void;
|
|
5699
|
+
/** The planner is a subplanner: its prompt told it the catalog, and a plan that has settled leaves it only its report (ADR-0057 R11). */
|
|
5700
|
+
subplanner?(): boolean;
|
|
4750
5701
|
/** Fresh discovery, allowlist-filtered the way the system prompt shows it. */
|
|
4751
5702
|
opening(runners: RunnerId[]): Promise<ConversationOpening>;
|
|
4752
5703
|
/** What the per-turn catalog block and every read draw from, as of now. */
|
|
@@ -4789,10 +5740,12 @@ interface PlannerConversationHost {
|
|
|
4789
5740
|
capturePrd(text: string): void;
|
|
4790
5741
|
/** The planner turn was stopped or abandoned: whatever it is waiting on (a parked approval) will never be answered. */
|
|
4791
5742
|
turnAborted(): void;
|
|
4792
|
-
/** A planner turn is about to take the conversation, which nothing holds now. */
|
|
5743
|
+
/** A planner turn is about to take the conversation, which nothing holds now. Throws why it may not. */
|
|
4793
5744
|
turnClaiming?(): void;
|
|
4794
5745
|
/** A planner turn let the conversation go, so the next one may take it. */
|
|
4795
5746
|
turnReleased?(): void;
|
|
5747
|
+
/** A turn was let go without ending: abandoned with its plan, or hung. */
|
|
5748
|
+
turnDropped?(): void;
|
|
4796
5749
|
/**
|
|
4797
5750
|
* A turn ended on the planner's usage limit, which it reported as `said`:
|
|
4798
5751
|
* what is sent again, and when. `answered`: a planner tool's change in the
|
|
@@ -4920,7 +5873,10 @@ declare class PlannerConversation {
|
|
|
4920
5873
|
private readonly briefing;
|
|
4921
5874
|
private readonly blocks;
|
|
4922
5875
|
private live;
|
|
5876
|
+
private readonly idling;
|
|
4923
5877
|
private openTurn;
|
|
5878
|
+
/** When the live context's newest turn opened; null with no live context. */
|
|
5879
|
+
private requestedAt;
|
|
4924
5880
|
/**
|
|
4925
5881
|
* What an API planner's chat condenses its context through during a turn
|
|
4926
5882
|
* (ADR-0002): the open turn, the history that landed before it, and the
|
|
@@ -4929,12 +5885,24 @@ declare class PlannerConversation {
|
|
|
4929
5885
|
private readonly compaction;
|
|
4930
5886
|
constructor(host: PlannerConversationHost);
|
|
4931
5887
|
get transcript(): readonly ConversationMessage[];
|
|
5888
|
+
/**
|
|
5889
|
+
* When the planner's prefix was last sent, as its provider counts a prompt
|
|
5890
|
+
* cache's life: from the start of a request (ADR-0057 R4). The turn's opening
|
|
5891
|
+
* stands for it: a turn's later calls keep the prefix warm for longer, so
|
|
5892
|
+
* this can only say a wake is due earlier than it had to be. Null with no live
|
|
5893
|
+
* context, whose next turn is a replay.
|
|
5894
|
+
*/
|
|
5895
|
+
get lastRequestAt(): number | null;
|
|
4932
5896
|
/** Whether a planner turn holds the conversation. */
|
|
4933
5897
|
get isTurnInFlight(): boolean;
|
|
5898
|
+
/** Resolves once no turn holds the conversation: what a subtree's stop waits on (ADR-0055 D16). */
|
|
5899
|
+
idle(): Promise<void>;
|
|
5900
|
+
private settleIdle;
|
|
4934
5901
|
/** Stop the planner turn in flight; it settles as stopped. False when none is. */
|
|
4935
5902
|
stopTurn(by?: 'force_send'): boolean;
|
|
4936
5903
|
/**
|
|
4937
|
-
* Drop the planner turn in flight together with the plan it was answering
|
|
5904
|
+
* Drop the planner turn in flight together with the plan it was answering,
|
|
5905
|
+
* or the session another host took from under it:
|
|
4938
5906
|
* it is stopped, whatever it settles is discarded, and the conversation is
|
|
4939
5907
|
* free at once rather than when the abandoned turn finishes unwinding.
|
|
4940
5908
|
*/
|
|
@@ -5314,7 +6282,12 @@ declare class PlannerConversation {
|
|
|
5314
6282
|
* whole block or what changed (ADR-0012 T10).
|
|
5315
6283
|
*/
|
|
5316
6284
|
private planView;
|
|
5317
|
-
/**
|
|
6285
|
+
/**
|
|
6286
|
+
* One line per task, subtasks indented under their parent, with stable
|
|
6287
|
+
* references — null until the plan has tasks. Past a size only the tasks a
|
|
6288
|
+
* planner acts on get a line (`planWindow`); what a line waits for costs a
|
|
6289
|
+
* start-rule walk, so the rest are not walked.
|
|
6290
|
+
*/
|
|
5318
6291
|
private planRows;
|
|
5319
6292
|
}
|
|
5320
6293
|
|
|
@@ -5377,93 +6350,6 @@ declare function resolveTaskRef<T extends RefTask<T>>(tasks: readonly T[], ref:
|
|
|
5377
6350
|
*/
|
|
5378
6351
|
declare function resolveUserTaskRef<T extends RefTask<T>>(tasks: readonly T[], ref: string | number): T | undefined;
|
|
5379
6352
|
|
|
5380
|
-
interface SessionMeta {
|
|
5381
|
-
id: string;
|
|
5382
|
-
goal: string;
|
|
5383
|
-
runners: RunnerId[];
|
|
5384
|
-
taskCount: number;
|
|
5385
|
-
status: PlanStatus;
|
|
5386
|
-
createdAt: string;
|
|
5387
|
-
updatedAt: string;
|
|
5388
|
-
}
|
|
5389
|
-
interface SessionData {
|
|
5390
|
-
meta: SessionMeta;
|
|
5391
|
-
/** The full plan state — including conversationHistory, prdMarkdown, and queuedMessages. */
|
|
5392
|
-
plan: LegacyPlanState;
|
|
5393
|
-
}
|
|
5394
|
-
|
|
5395
|
-
/**
|
|
5396
|
-
* The bridge between "core needs an answer" and "a human somewhere is looking
|
|
5397
|
-
* at a UI". Core cannot prompt: the human may be at a browser, a TUI, a CLI
|
|
5398
|
-
* stream, or a VS Code webview, and on the web server they are on the far end
|
|
5399
|
-
* of a socket. So the Session parks a promise here, announces the request
|
|
5400
|
-
* through the normal broadcast seam, and every surface answers through the
|
|
5401
|
-
* same `resolve(id, granted)` call.
|
|
5402
|
-
*
|
|
5403
|
-
* Timeouts are load-bearing rather than defensive: a planner turn that blocks
|
|
5404
|
-
* forever on an unanswered prompt would hang the whole research loop with no
|
|
5405
|
-
* visible cause. On expiry the request resolves to denied and the model gets a
|
|
5406
|
-
* normal, actionable tool result. A task runner's request is the exception
|
|
5407
|
-
* (ADR-0018, A1): the runner is parked on it rather than a research loop, and
|
|
5408
|
-
* it waits for a person — or the supervisor — however long that takes.
|
|
5409
|
-
*/
|
|
5410
|
-
interface PendingApproval {
|
|
5411
|
-
id: string;
|
|
5412
|
-
request: ApprovalRequest;
|
|
5413
|
-
createdAt: string;
|
|
5414
|
-
}
|
|
5415
|
-
interface PendingApprovalsOptions {
|
|
5416
|
-
/** Denies and resolves after this long with no answer. Default 5 minutes. */
|
|
5417
|
-
timeoutMs?: number;
|
|
5418
|
-
/** Announce a new request to the surfaces. */
|
|
5419
|
-
onRequest?: (pending: PendingApproval) => void;
|
|
5420
|
-
/** Announce that a request is no longer actionable (answered or expired). */
|
|
5421
|
-
onSettled?: (id: string, granted: boolean, settled: {
|
|
5422
|
-
request: ApprovalRequest;
|
|
5423
|
-
decision: ApprovalDecision;
|
|
5424
|
-
}) => void;
|
|
5425
|
-
}
|
|
5426
|
-
interface AskOptions {
|
|
5427
|
-
/**
|
|
5428
|
-
* An id the caller already announced the request under. One still in use is
|
|
5429
|
-
* refused — denied at once — rather than overwriting the request that has it.
|
|
5430
|
-
*/
|
|
5431
|
-
id?: string;
|
|
5432
|
-
/** Wait for an answer however long it takes. */
|
|
5433
|
-
noTimeout?: boolean;
|
|
5434
|
-
/**
|
|
5435
|
-
* Given the answer as the request settles, before anything awaiting the
|
|
5436
|
-
* promise runs: a caller about to tear down what asked (a runner being
|
|
5437
|
-
* stopped) must deliver the answer before it goes.
|
|
5438
|
-
*/
|
|
5439
|
-
onDecision?: (decision: ApprovalDecision) => void;
|
|
5440
|
-
}
|
|
5441
|
-
declare class PendingApprovals {
|
|
5442
|
-
private readonly opts;
|
|
5443
|
-
private readonly entries;
|
|
5444
|
-
private readonly listeners;
|
|
5445
|
-
constructor(opts?: PendingApprovalsOptions);
|
|
5446
|
-
/** Hear each new request once it is announced — the supervisor wakes on a runner's (ADR-0029). */
|
|
5447
|
-
listen(listener: (pending: PendingApproval) => void): () => void;
|
|
5448
|
-
/** Park a request and return the promise the approval policy awaits. */
|
|
5449
|
-
ask(request: ApprovalRequest, options?: AskOptions): Promise<boolean>;
|
|
5450
|
-
/** Park a request whose answer is more than yes or no. */
|
|
5451
|
-
decide(request: ApprovalRequest, options?: AskOptions): Promise<ApprovalDecision>;
|
|
5452
|
-
/**
|
|
5453
|
-
* Answer one request. Returns false when the id is unknown or already
|
|
5454
|
-
* settled. "Allow for this task" on a request that did not offer it is a
|
|
5455
|
-
* plain allow: no grant is made that the requester never proposed.
|
|
5456
|
-
*/
|
|
5457
|
-
resolve(id: string, answer: ApprovalAnswer): boolean;
|
|
5458
|
-
/** Everything still awaiting an answer — replayed to a surface that connects late. */
|
|
5459
|
-
outstanding(): PendingApproval[];
|
|
5460
|
-
/**
|
|
5461
|
-
* Deny everything in flight, or only the requests `which` picks. Called on
|
|
5462
|
-
* abort and on session reset.
|
|
5463
|
-
*/
|
|
5464
|
-
clear(which?: (request: ApprovalRequest) => boolean, note?: string): void;
|
|
5465
|
-
}
|
|
5466
|
-
|
|
5467
6353
|
/** One repo that kept "Merge all" from touching anything, as part of one line. */
|
|
5468
6354
|
declare function blockNotice({ repo, reason, files, expected, actual, rebasing }: IsolationMergeBlock): string;
|
|
5469
6355
|
/** Every repo's reason, in the order "Merge all" named them, so a surface can list them or join them. */
|
|
@@ -5525,9 +6411,9 @@ interface IsolationPreviewNotice {
|
|
|
5525
6411
|
declare function describeIsolationPreview(preview: IsolationPreview): IsolationPreviewNotice;
|
|
5526
6412
|
|
|
5527
6413
|
/**
|
|
5528
|
-
* Pure
|
|
5529
|
-
*
|
|
5530
|
-
*
|
|
6414
|
+
* Pure helper so a browser surface can format a conflict's files without
|
|
6415
|
+
* pulling `isolationRecord` — and its `path` import — into a webview bundle.
|
|
6416
|
+
* Kept out of `isolationRecord.ts` for exactly that reason.
|
|
5531
6417
|
*/
|
|
5532
6418
|
declare function capConflictFiles(files: string[], max?: number): string;
|
|
5533
6419
|
|
|
@@ -5598,6 +6484,12 @@ declare function repoResultLines(handoff: {
|
|
|
5598
6484
|
landed: readonly unknown[];
|
|
5599
6485
|
}[];
|
|
5600
6486
|
}): string[];
|
|
6487
|
+
/**
|
|
6488
|
+
* What a Merge all asks the user to confirm when a delegated task's check has
|
|
6489
|
+
* not passed (ADR-0055 D9), the checks named as the plan names them. Every
|
|
6490
|
+
* surface asks with these words, and the inbox's option carries them.
|
|
6491
|
+
*/
|
|
6492
|
+
declare function mergePastChecksConfirmation(checks: readonly string[]): string;
|
|
5601
6493
|
|
|
5602
6494
|
/** What the user last picked for one planner backend. */
|
|
5603
6495
|
interface PlannerModelChoice {
|
|
@@ -5722,6 +6614,11 @@ interface GlobalRunSettings {
|
|
|
5722
6614
|
supervisorRetryLimit: number;
|
|
5723
6615
|
/** Reads a wake-up turn may make, in place of a user message's caps. */
|
|
5724
6616
|
wakeUpReadBudget: number;
|
|
6617
|
+
/**
|
|
6618
|
+
* The token budget of a delegation tree (ADR-0055 D21, ADR-0056 M5); 0 is
|
|
6619
|
+
* delegation off. One value, so delegation is never on with no budget.
|
|
6620
|
+
*/
|
|
6621
|
+
delegationTokens: number;
|
|
5725
6622
|
}
|
|
5726
6623
|
declare const RUN_SETTINGS_DEFAULTS: Readonly<GlobalRunSettings>;
|
|
5727
6624
|
declare class RunSettingsError extends Error {
|
|
@@ -5747,12 +6644,26 @@ interface UserSettings {
|
|
|
5747
6644
|
autorun?: boolean;
|
|
5748
6645
|
supervisorRetryLimit?: number;
|
|
5749
6646
|
wakeUpReadBudget?: number;
|
|
6647
|
+
delegationTokens?: number;
|
|
5750
6648
|
/**
|
|
5751
6649
|
* Whether an API planner prunes its own context ahead of a call that would
|
|
5752
6650
|
* pass 90% of its model's window. Absent means on. Set in the file only:
|
|
5753
6651
|
* no surface offers it.
|
|
5754
6652
|
*/
|
|
5755
6653
|
plannerAutoCompaction?: boolean;
|
|
6654
|
+
/**
|
|
6655
|
+
* What a task runner loads of the user's own setup: all of it (`user`) or
|
|
6656
|
+
* what a task needs (`minimal`). Absent means `user`. Set in the file only:
|
|
6657
|
+
* no surface offers it.
|
|
6658
|
+
*/
|
|
6659
|
+
taskRunnerConfig?: TaskRunnerConfig;
|
|
6660
|
+
/**
|
|
6661
|
+
* Run tasks in containers (ADR-0059 L5), as `containerSettings` reads it:
|
|
6662
|
+
* absent means local worktrees. Kept as written, since one it cannot use must
|
|
6663
|
+
* refuse a task, not fall back to the host. Set in the file only: no surface
|
|
6664
|
+
* offers it.
|
|
6665
|
+
*/
|
|
6666
|
+
containers?: unknown;
|
|
5756
6667
|
}
|
|
5757
6668
|
/**
|
|
5758
6669
|
* The model allowlist, remembered planner models and enabled runners are shared
|
|
@@ -5953,7 +6864,9 @@ type DaemonErrorCode = 'session_not_found' | 'task_not_found' | 'no_plan' | 'alr
|
|
|
5953
6864
|
/** The selected planner cannot plan yet (no key, no base URL, no model); `plannerNotReady` says which. */
|
|
5954
6865
|
| 'planner_not_ready'
|
|
5955
6866
|
/** The request asked for something the plan, task or conversation does not allow. */
|
|
5956
|
-
| 'refused' | 'checkpoint_not_waiting'
|
|
6867
|
+
| 'refused' | 'checkpoint_not_waiting'
|
|
6868
|
+
/** Merge all would merge work no check has passed; the message names the checks, and a surface asks before sending `pastChecks` (ADR-0055 D9). */
|
|
6869
|
+
| 'merge_past_check' | 'approval_not_outstanding'
|
|
5957
6870
|
/** Another live Ordewell host runs this session (ADR-0049); `sessionHeld` names it. */
|
|
5958
6871
|
| 'session_held';
|
|
5959
6872
|
/** The body of every non-2xx answer a route gives. */
|
|
@@ -5997,6 +6910,24 @@ interface ExecuteCommandResponse {
|
|
|
5997
6910
|
message: string;
|
|
5998
6911
|
payload?: CommandPayload;
|
|
5999
6912
|
}
|
|
6913
|
+
/**
|
|
6914
|
+
* `GET /api/plans/:id/escalations`: what waits on a person now (ADR-0053). A
|
|
6915
|
+
* client holding a socket has the same list on every status update.
|
|
6916
|
+
*/
|
|
6917
|
+
interface EscalationsResponse {
|
|
6918
|
+
escalations: Escalation[];
|
|
6919
|
+
}
|
|
6920
|
+
/**
|
|
6921
|
+
* The body of `POST /api/plans/:id/escalations/answer`, run as the user, and
|
|
6922
|
+
* answered as `execute-command` answers. `confirmed` is the user's yes to the
|
|
6923
|
+
* option's `confirm`.
|
|
6924
|
+
*/
|
|
6925
|
+
interface AnswerEscalationRequest {
|
|
6926
|
+
id: string;
|
|
6927
|
+
option: string;
|
|
6928
|
+
note?: string;
|
|
6929
|
+
confirmed?: boolean;
|
|
6930
|
+
}
|
|
6000
6931
|
/**
|
|
6001
6932
|
* A plan as the planner routes return it: the session's plan state, not the
|
|
6002
6933
|
* `SerializedPlan` a websocket `plan_generated` carries. The two differ —
|
|
@@ -6057,6 +6988,8 @@ interface MergeGateEntry {
|
|
|
6057
6988
|
interface MergeGateResponse {
|
|
6058
6989
|
mergeGate: MergeGateEntry[];
|
|
6059
6990
|
}
|
|
6991
|
+
/** A revert that would not go ahead is an answer, not a failure, so it comes back 200 with why (ADR-0054). */
|
|
6992
|
+
type TaskRevertPreviewResponse = TaskRevertPreview;
|
|
6060
6993
|
interface IsolationDiffResponse {
|
|
6061
6994
|
diff: string;
|
|
6062
6995
|
}
|
|
@@ -6582,6 +7515,8 @@ interface TaskLogView extends BlockList {
|
|
|
6582
7515
|
readonly queued: readonly QueuedTaskMessage[];
|
|
6583
7516
|
/** A turn is running. */
|
|
6584
7517
|
readonly working: boolean;
|
|
7518
|
+
/** When the open turn began (ISO), for a surface to count from; absent between turns and for a log saved before it was kept (#81). */
|
|
7519
|
+
readonly turnStartedAt?: string;
|
|
6585
7520
|
/** How the last turn ended; absent before the first one does. */
|
|
6586
7521
|
readonly lastTurnEnd?: StructuredTurnEnd;
|
|
6587
7522
|
/** What the runner reported over the attempt, subagents included. */
|
|
@@ -6608,6 +7543,70 @@ declare function reduceTaskLog(view: TaskLogView, event: TaskLogEvent): TaskLogV
|
|
|
6608
7543
|
/** A whole attempt's events, folded from the start — what a reload shows. */
|
|
6609
7544
|
declare function replayTaskLog(events: readonly TaskLogEvent[], from?: TaskLogView): TaskLogView;
|
|
6610
7545
|
|
|
7546
|
+
/** What the label reads: a `TaskLogView`'s blocks, which is all a webview holds of one. */
|
|
7547
|
+
type LoggedBlocks = {
|
|
7548
|
+
readonly blocks: readonly DisplayBlock[];
|
|
7549
|
+
readonly turnStartedAt?: string;
|
|
7550
|
+
};
|
|
7551
|
+
/** What {@link taskActivity} reads of a log: the view's turn flag, and whether the log is an attempt the runner is no longer in. */
|
|
7552
|
+
type LoggedTurn = LoggedBlocks & {
|
|
7553
|
+
/** A turn is open in the log, as its `turn_start` said; a log that streams without one has open blocks but this unset. Absent where a surface holds no such flag, which reads as open. */
|
|
7554
|
+
readonly working?: boolean;
|
|
7555
|
+
/** How the last turn ended, as the view says; set means the log has seen a turn end, so what it left open is not a turn. */
|
|
7556
|
+
readonly lastTurnEnd?: StructuredTurnEnd;
|
|
7557
|
+
/** The log is an earlier attempt, browsed: whatever it left open ended with it. */
|
|
7558
|
+
readonly archived?: boolean;
|
|
7559
|
+
};
|
|
7560
|
+
/**
|
|
7561
|
+
* What a task's runner is busy with, from its log: the latest block still
|
|
7562
|
+
* open decides, since that is what the runner is doing now. Several running
|
|
7563
|
+
* subagents are counted rather than named, as no one of them is the task's
|
|
7564
|
+
* latest work. The label holds runner output — a surface sanitizes it.
|
|
7565
|
+
*/
|
|
7566
|
+
declare function activityLabel(view: LoggedBlocks): string;
|
|
7567
|
+
/** The line above a composer: `busy` animates, and a quiet task's does not. */
|
|
7568
|
+
interface TaskActivity {
|
|
7569
|
+
label: string;
|
|
7570
|
+
busy: boolean;
|
|
7571
|
+
/** When the open turn began (ISO): a surface counts from it on its own ticks (#81). Absent for a log saved before turns were dated. */
|
|
7572
|
+
since?: string;
|
|
7573
|
+
}
|
|
7574
|
+
/**
|
|
7575
|
+
* The activity line of an open task log, or null when it has none to show: a
|
|
7576
|
+
* task not running, and one waiting on a runner request, whose card in the log
|
|
7577
|
+
* already asks the user. A running task whose runner has gone quiet is named
|
|
7578
|
+
* as the plan pane names it and is never `busy`, so a runner that is not
|
|
7579
|
+
* producing anything cannot look as if it were. Nor can a runner between
|
|
7580
|
+
* turns: `busy` needs an open turn, a running subagent that outlived it, or,
|
|
7581
|
+
* in a log that has seen no turn end, a block still open (a stream whose
|
|
7582
|
+
* `turn_start` this view never saw).
|
|
7583
|
+
* A browsed earlier attempt has no line, whatever its log was left open on.
|
|
7584
|
+
* A script task has no exception here, on any surface: it runs no model, but
|
|
7585
|
+
* its log is what it printed, so a step still open is one running.
|
|
7586
|
+
*/
|
|
7587
|
+
declare function taskActivity(view: LoggedTurn, task: {
|
|
7588
|
+
status: string;
|
|
7589
|
+
idleSince?: string | null;
|
|
7590
|
+
awaitingApproval?: number;
|
|
7591
|
+
}): TaskActivity | null;
|
|
7592
|
+
|
|
7593
|
+
/**
|
|
7594
|
+
* How long something has run, for an activity line: whole seconds (`42s`),
|
|
7595
|
+
* then minutes and zero-padded seconds (`3m 05s`), then from an hour hours and
|
|
7596
|
+
* zero-padded minutes (`1h 05m`), since seconds mean nothing by then. A
|
|
7597
|
+
* fraction of a unit is dropped, not rounded up, so a time never reads ahead
|
|
7598
|
+
* of the clock. Returns '' for a negative or non-finite input: a start time
|
|
7599
|
+
* ahead of the reader's clock (skew between hosts) is not a duration to show.
|
|
7600
|
+
*/
|
|
7601
|
+
declare function formatElapsed(ms: number): string;
|
|
7602
|
+
/**
|
|
7603
|
+
* The time from `startedAt` (ISO) to `now` (epoch ms), formatted. The clock is
|
|
7604
|
+
* the caller's, so a surface counts on a tick it already draws and a test
|
|
7605
|
+
* fixes it. '' when there is nothing to show: no start (a log saved before
|
|
7606
|
+
* turns were dated) or one that cannot be read.
|
|
7607
|
+
*/
|
|
7608
|
+
declare function elapsedSince(startedAt: string | undefined, now: number): string;
|
|
7609
|
+
|
|
6611
7610
|
/**
|
|
6612
7611
|
* The one-line head of a command row, shared by every surface: the tool's name
|
|
6613
7612
|
* and the argument that says what the call is about.
|
|
@@ -6717,6 +7716,8 @@ declare function aheadOfDraft(text: string, draft: string): string;
|
|
|
6717
7716
|
interface TurnGate {
|
|
6718
7717
|
readonly open: string | null;
|
|
6719
7718
|
readonly stopped: string | null;
|
|
7719
|
+
/** When the open turn began (ISO), for its elapsed time (#81); absent when none is open or its daemon did not say. */
|
|
7720
|
+
readonly openedAt?: string;
|
|
6720
7721
|
}
|
|
6721
7722
|
declare const NO_TURN: TurnGate;
|
|
6722
7723
|
interface GatedConversation {
|
|
@@ -6735,6 +7736,13 @@ declare function followTurn(view: ConversationView, gate: TurnGate, input: Conve
|
|
|
6735
7736
|
* turn's late output never lands. Nothing changes when no turn is open.
|
|
6736
7737
|
*/
|
|
6737
7738
|
declare function stopTurn(view: ConversationView, gate: TurnGate): GatedConversation;
|
|
7739
|
+
/**
|
|
7740
|
+
* The turn is over without its `planner_turn_ended` having been heard: its
|
|
7741
|
+
* call failed or returned the plan. The open turn and its start go, so the
|
|
7742
|
+
* next turn does not count from this one's; a stop still standing stays, as
|
|
7743
|
+
* the stopped turn's stragglers have not stopped.
|
|
7744
|
+
*/
|
|
7745
|
+
declare function closeTurn(gate: TurnGate): TurnGate;
|
|
6738
7746
|
|
|
6739
7747
|
/**
|
|
6740
7748
|
* Whether the conversation holds anything the collapsed view hides — thinking,
|
|
@@ -6859,11 +7867,15 @@ declare function taskStatusKind(task: {
|
|
|
6859
7867
|
status: string;
|
|
6860
7868
|
idleSince?: string | null;
|
|
6861
7869
|
}): TaskStatusKind;
|
|
7870
|
+
/** The word for a running task whose runner has printed nothing for a while (`quiet`). */
|
|
7871
|
+
declare const STALLED_LABEL = "Stalled";
|
|
6862
7872
|
/** What an awaiting_user task waits on (ADR-0018, W1); null when no reason was saved. */
|
|
6863
7873
|
declare function awaitingLabel(task: {
|
|
6864
7874
|
status: string;
|
|
6865
7875
|
awaitingReason?: AwaitingReason;
|
|
6866
7876
|
}): string | null;
|
|
7877
|
+
/** A conflict repair that will start by itself (ADR-0015): progress, in words that ask nothing of the user. */
|
|
7878
|
+
declare function repairWaitLabel(wait: RepairWait): string;
|
|
6867
7879
|
/** "Blocked by #1, #2.1": the failed tasks a blocked task waits on, by reference (ADR-0034). */
|
|
6868
7880
|
declare function blockedByLabel(refs: readonly string[]): string;
|
|
6869
7881
|
/** "On hold: could not connect to Ordewell's tools; start it again": why a task is out of the scheduler. */
|
|
@@ -6974,6 +7986,8 @@ interface ActionSubject {
|
|
|
6974
7986
|
resumeAt?: string | null;
|
|
6975
7987
|
/** Its last attempt left a runner session to continue (ADR-0018, K1). */
|
|
6976
7988
|
continuable?: boolean;
|
|
7989
|
+
/** A conflict repair of it will start by itself, which Stop withdraws (ADR-0015). */
|
|
7990
|
+
repairWaits?: unknown;
|
|
6977
7991
|
}
|
|
6978
7992
|
/** The actions a task's row offers while a plan runs, in the order they are laid out. */
|
|
6979
7993
|
declare function taskRowActions(task: ActionSubject, placement?: TaskRowPlacement): TaskRowAction[];
|
|
@@ -7014,6 +8028,48 @@ declare function confirmedOverride(command: ExecutionCommand, seen?: TaskStatus)
|
|
|
7014
8028
|
/** Change versus ops can still be flipped (ADR-0020): an AI task that has not started. */
|
|
7015
8029
|
declare function opsEditable(task: ActionSubject): boolean;
|
|
7016
8030
|
|
|
8031
|
+
/**
|
|
8032
|
+
* What a delegated task's row says (ADR-0055 D16, D20), in sentence case, each
|
|
8033
|
+
* part null where there is nothing to say. Surfaces pick the glyphs and the
|
|
8034
|
+
* layout, and derive none of the facts.
|
|
8035
|
+
*/
|
|
8036
|
+
interface TaskRowDelegated {
|
|
8037
|
+
goal: string | null;
|
|
8038
|
+
/** "1.3M of 2M tokens left". */
|
|
8039
|
+
tokens: string | null;
|
|
8040
|
+
/** "2 of 4 done, 1 running". */
|
|
8041
|
+
counts: string | null;
|
|
8042
|
+
/** That a Stop is still winding the subtree down. */
|
|
8043
|
+
stopping: string | null;
|
|
8044
|
+
}
|
|
8045
|
+
declare const STOPPING_LABEL = "Stopping: its child plan is still winding down.";
|
|
8046
|
+
declare function delegatedRowView(task: {
|
|
8047
|
+
type: string;
|
|
8048
|
+
goal?: string;
|
|
8049
|
+
delegation?: DelegatedRow;
|
|
8050
|
+
handoff?: HandoffDigest;
|
|
8051
|
+
}): TaskRowDelegated | null;
|
|
8052
|
+
/** One finding of a delegated task's report, as a surface draws it. */
|
|
8053
|
+
interface SubtreeItemView {
|
|
8054
|
+
/** The task and finding that name it, as a reader says them; null for a subplanner's own, which names no task. */
|
|
8055
|
+
reference: string | null;
|
|
8056
|
+
/** "F1 · Major · title". */
|
|
8057
|
+
heading: string;
|
|
8058
|
+
detail?: string;
|
|
8059
|
+
}
|
|
8060
|
+
/** What a delegated task's report adds to a handoff (ADR-0057 R2), worded once for every surface. */
|
|
8061
|
+
interface SubtreeView {
|
|
8062
|
+
/** "3 done, 1 failed · 3 commits · 1.2M tokens · 1 major, 2 minor findings below". */
|
|
8063
|
+
summary: string;
|
|
8064
|
+
/** Changed outside its declared scope, or null (ADR-0056 M7). */
|
|
8065
|
+
outsideScope: string | null;
|
|
8066
|
+
/** What the parent must decide. */
|
|
8067
|
+
open: SubtreeItemView[];
|
|
8068
|
+
/** What the subplanner passed up. */
|
|
8069
|
+
promoted: SubtreeItemView[];
|
|
8070
|
+
}
|
|
8071
|
+
declare function subtreeView(subtree: SubtreeReport): SubtreeView;
|
|
8072
|
+
|
|
7017
8073
|
/**
|
|
7018
8074
|
* Where a loop's check stands, for the words a surface puts on its row
|
|
7019
8075
|
* (ADR-0045): derived from the check's status, verdict and round, as a block
|
|
@@ -7102,8 +8158,13 @@ interface TaskRowSubject {
|
|
|
7102
8158
|
outcome: string;
|
|
7103
8159
|
reported?: string;
|
|
7104
8160
|
} | null;
|
|
8161
|
+
/** Between rounds with nothing to run it: only the run knows that, so it is told (ADR-0045 L5). */
|
|
8162
|
+
loopStranded?: boolean;
|
|
7105
8163
|
/** The latest attempt's handoff as the plan keeps it (ADR-0047); a row shows it without opening the task. */
|
|
7106
8164
|
handoff?: HandoffDigest;
|
|
8165
|
+
/** A delegated task's goal, and its row's live facts (ADR-0055 D20). */
|
|
8166
|
+
goal?: string;
|
|
8167
|
+
delegation?: DelegatedRow;
|
|
7107
8168
|
}
|
|
7108
8169
|
interface TaskRowIsolation {
|
|
7109
8170
|
state: TaskIsolationState;
|
|
@@ -7115,6 +8176,11 @@ interface TaskRowIsolation {
|
|
|
7115
8176
|
limit: number;
|
|
7116
8177
|
};
|
|
7117
8178
|
repairedFiles?: string[];
|
|
8179
|
+
/** Core's word that its landing can be reverted (ADR-0054); a surface offers the action only then. */
|
|
8180
|
+
revertible?: true;
|
|
8181
|
+
repairWaits?: RepairWait;
|
|
8182
|
+
/** The task added to resolve its conflict, by id. */
|
|
8183
|
+
resolver?: string;
|
|
7118
8184
|
}
|
|
7119
8185
|
/**
|
|
7120
8186
|
* The plan a row labels its references against: the tree, so a subtask's
|
|
@@ -7160,7 +8226,7 @@ interface TaskRowContext {
|
|
|
7160
8226
|
* or a script task (ADR-0035): an ops task by nature, drawn with its body and
|
|
7161
8227
|
* with no prompt, runner or model to edit.
|
|
7162
8228
|
*/
|
|
7163
|
-
type TaskRowKind = 'ai' | 'user' | 'ops' | 'script';
|
|
8229
|
+
type TaskRowKind = 'ai' | 'user' | 'ops' | 'script' | 'delegated';
|
|
7164
8230
|
/** The task's whole spend (see `taskUsageSummary`); `attempt` is the latest one, 0 before any reported. */
|
|
7165
8231
|
interface TaskRowUsage extends Pick<TaskUsageSummary, 'totals' | 'contextFill'> {
|
|
7166
8232
|
attempt: number;
|
|
@@ -7202,6 +8268,8 @@ type TaskRowLoop = {
|
|
|
7202
8268
|
round: number | null;
|
|
7203
8269
|
};
|
|
7204
8270
|
interface TaskRowView {
|
|
8271
|
+
/** A delegated task's goal, budget left, child counts and Stop (ADR-0055 D20); null on any other task. */
|
|
8272
|
+
delegated: TaskRowDelegated | null;
|
|
7205
8273
|
usage: TaskRowUsage | null;
|
|
7206
8274
|
/** "2", or "2.1" for a subtask. */
|
|
7207
8275
|
orderLabel: string;
|
|
@@ -7237,10 +8305,16 @@ interface TaskRowView {
|
|
|
7237
8305
|
autonomous: boolean;
|
|
7238
8306
|
/** The repos its isolated work changed, by path; empty for a group of one. */
|
|
7239
8307
|
repos: string[];
|
|
7240
|
-
/** Integration stopped on a conflict: the one isolation state that needs the user. */
|
|
8308
|
+
/** Integration stopped on a conflict: the one isolation state that needs the user. `resolver` is the task, by reference, that has it; then a second is not offered. */
|
|
7241
8309
|
conflict: {
|
|
7242
8310
|
repo: string | null;
|
|
7243
8311
|
files: string | null;
|
|
8312
|
+
resolver: string | null;
|
|
8313
|
+
} | null;
|
|
8314
|
+
/** A conflict repair that starts by itself once what it waits for clears (ADR-0015): `label` says what, in sentence case. Progress, so `conflict` is null. */
|
|
8315
|
+
repairWaiting: {
|
|
8316
|
+
label: string;
|
|
8317
|
+
files: string | null;
|
|
7244
8318
|
} | null;
|
|
7245
8319
|
/** A conflict repair in flight (ADR-0015) — progress, not a blocker. */
|
|
7246
8320
|
repairing: {
|
|
@@ -7273,6 +8347,8 @@ interface TaskRowView {
|
|
|
7273
8347
|
dependencies: string[];
|
|
7274
8348
|
/** What the row offers while a plan runs. */
|
|
7275
8349
|
actions: TaskRowAction[];
|
|
8350
|
+
/** Its landed work can be reverted before Merge all (ADR-0054): a surface offers Revert only then, and core's preview says the rest. */
|
|
8351
|
+
revertible: boolean;
|
|
7276
8352
|
/** The one mark its toggle sets. */
|
|
7277
8353
|
mark: 'complete' | 'uncomplete';
|
|
7278
8354
|
opsEditable: boolean;
|
|
@@ -7309,6 +8385,7 @@ declare function loopRowParts(loop: TaskRowLoop): string[];
|
|
|
7309
8385
|
*/
|
|
7310
8386
|
interface TaskLogHeaderTask {
|
|
7311
8387
|
status: string;
|
|
8388
|
+
type?: string;
|
|
7312
8389
|
awaitingReason?: AwaitingReason;
|
|
7313
8390
|
skipReason?: string;
|
|
7314
8391
|
resumeAt?: string | null;
|
|
@@ -7316,6 +8393,8 @@ interface TaskLogHeaderTask {
|
|
|
7316
8393
|
idleSince?: string | null;
|
|
7317
8394
|
/** Its last attempt left a runner session the task's composer can continue (ADR-0018, K1). */
|
|
7318
8395
|
continuable?: boolean;
|
|
8396
|
+
/** A conflict repair of it starts by itself once this clears (ADR-0015). */
|
|
8397
|
+
repairWaits?: RepairWait;
|
|
7319
8398
|
attemptUsage?: readonly AttemptUsage[];
|
|
7320
8399
|
}
|
|
7321
8400
|
/**
|
|
@@ -7353,7 +8432,7 @@ interface TaskLogHeaderView {
|
|
|
7353
8432
|
/** The commands the attempt on screen loaded (#66): the last `runner_loaded` block of its log. */
|
|
7354
8433
|
declare function taskLogCommands(view: Pick<TaskLogView, 'blocks'>): readonly RunnerCommand[];
|
|
7355
8434
|
/** Whether an opened task's composer continues it rather than messaging its turn (ADR-0018, K1). */
|
|
7356
|
-
declare function logContinues(task: Pick<TaskLogHeaderTask, 'status' | 'awaitingReason' | 'continuable'>): boolean;
|
|
8435
|
+
declare function logContinues(task: Pick<TaskLogHeaderTask, 'type' | 'status' | 'awaitingReason' | 'continuable'>): boolean;
|
|
7357
8436
|
/** Whether the composer resumes it now, once the user says the limit has reset; a subset of `logContinues`. */
|
|
7358
8437
|
declare function logResumes(task: Pick<TaskLogHeaderTask, 'status' | 'awaitingReason' | 'continuable'>): boolean;
|
|
7359
8438
|
/**
|
|
@@ -7404,6 +8483,21 @@ type OverrideDirection = 'complete' | 'uncomplete';
|
|
|
7404
8483
|
* completion, never the work or what already ran on it.
|
|
7405
8484
|
*/
|
|
7406
8485
|
declare function manualOverrideConfirmation(direction: OverrideDirection, label: string): string;
|
|
8486
|
+
/** What a revert does (ADR-0054), told with the list of tasks it takes: the same words on every surface. */
|
|
8487
|
+
declare const revertEffect = "Its landed work comes off the integration branch, newest first, and each task listed is held as not started until you retry it. Nothing in your own branch changes.";
|
|
8488
|
+
/** How a revert's confirmation calls a task: a subtask's order alone would name a top-level task. */
|
|
8489
|
+
declare function revertTaskRef(task: {
|
|
8490
|
+
order: number;
|
|
8491
|
+
ref?: string;
|
|
8492
|
+
}): string;
|
|
8493
|
+
/** One task of a revert's confirmation: `dependent` is one that goes with the task the user chose. */
|
|
8494
|
+
declare function revertListLine(task: {
|
|
8495
|
+
order: number;
|
|
8496
|
+
ref?: string;
|
|
8497
|
+
title: string;
|
|
8498
|
+
repos: readonly string[];
|
|
8499
|
+
dependent: boolean;
|
|
8500
|
+
}): string;
|
|
7407
8501
|
/** Why a manual override waits for the run to stop (ADR-0029); `label` names the task. */
|
|
7408
8502
|
declare function manualOverrideStopFirst(direction: OverrideDirection, label: string): string;
|
|
7409
8503
|
interface NewTaskFields {
|
|
@@ -7433,11 +8527,18 @@ declare const automergeSummary: (run: GlobalRunSettings) => string;
|
|
|
7433
8527
|
declare const PLANNED_WITH_LABEL = "Planned-with line in commits Ordewell writes";
|
|
7434
8528
|
declare const trailerSummary: (run: GlobalRunSettings) => string;
|
|
7435
8529
|
declare const autorunSummary: (run: GlobalRunSettings) => string;
|
|
8530
|
+
declare const delegationSummary: (run: GlobalRunSettings) => string;
|
|
8531
|
+
/** Whether any surface offers the delegation setting, and whether a planner may write a delegated task. */
|
|
8532
|
+
declare const DELEGATION_OFFERED: boolean;
|
|
7436
8533
|
declare const ACT_RISK = "Tasks it adds run too, ops tasks included, which can act on real systems unattended.";
|
|
7437
|
-
declare const AUTORUN_RISK = "Plans start without review, ops tasks included, which can act on real systems unattended. In Full
|
|
8534
|
+
declare const AUTORUN_RISK = "Plans start without review, ops tasks included, which can act on real systems unattended. In Full nobody is asked at all: the planner may start anything, script tasks included, from a plan no person read.";
|
|
8535
|
+
/** What turning delegation on accepts below the root, as Act and autorun accept it at the root (ADR-0056 M9). A container is not named as a remedy: only its own setting runs one, a child's tasks included (ADR-0059). */
|
|
8536
|
+
declare const DELEGATION_RISK = "A subplanner approves and runs its own plan, and no person reads it. Its change tasks keep the network they have in a flat run, so an instruction injected into something a subplanner read can become a plan nobody read, and run with that network. Delegation starts no container of its own: containers are opt-in, and only that setting runs a child's tasks in one.";
|
|
7438
8537
|
/** `on`/`off` as a switch's value; null for anything else. */
|
|
7439
8538
|
declare function parseSwitch(arg: string): boolean | null;
|
|
8539
|
+
/** A delegation setting as typed: `off`, which is 0, or the tree's budget in tokens; null for anything else. */
|
|
8540
|
+
declare function parseDelegation(arg: string): number | null;
|
|
7440
8541
|
/** A whole number at least `min`, as typed; null for anything else. */
|
|
7441
8542
|
declare function parseCount(arg: string | undefined, min: number): number | null;
|
|
7442
8543
|
|
|
7443
|
-
export { type DiffRowKind as $, ACT_RISK as A, type BlockingSubject as B, CHAT_COMMANDS as C, type CommandBlock as D, type CommandDescriptor as E, type CommandOutcome as F, type CommandPayload as G, type CommandStatus as H, type CommandsResponse as I, type CompactionBlock as J, type CompactionStatus as K, type Consent as L, type ContextCondenseRequest as M, ConversationBusyError as N, type ConversationCompactResponse as O, type ConversationCompaction as P, ConversationEditError as Q, type ConversationForkResponse as R, type ConversationInput as S, type ConversationRequest as T, type ConversationRewindResponse as U, type ConversationTurn as V, type ConversationView as W, DEFAULT_WEB_READ_BUDGET as X, type DaemonErrorCode as Y, type DecideOptions as Z, type DiffRow as _, AUTORUN_RISK as a, type PendingApproval as a$, type DiffStat as a0, type DisplayBlock as a1, EMPTY_CONVERSATION as a2, EMPTY_HOLD as a3, EMPTY_RUN as a4, EMPTY_TASK_LOG as a5, EMPTY_TASK_LOG_FOLLOW as a6, type ErrorBody as a7, type ExecuteCommandResponse as a8, type ExecuteResponse as a9, type LiveTail as aA, type LiveTailOptions as aB, type LocalEntry as aC, type LoopCheckFacts as aD, type LoopCheckState as aE, type LoopGuard as aF, type MappedTool as aG, type MarkdownToken as aH, type MergeGateEntry as aI, type MergeGateResponse as aJ, type MergeWordingHandoff as aK, type MessageBlock as aL, type MessageRole as aM, type ModelsResponse as aN, NOT_STARTED as aO, NO_TURN as aP, type NewTaskFields as aQ, type NotificationAction as aR, OUTPUT_LINES_DEFAULT as aS, OUTPUT_LINES_MAX as aT, type OkResponse as aU, type OpRef as aV, type OpRefusal as aW, type OrchestratorObserver as aX, type OutputPreview as aY, type OverrideDirection as aZ, PLANNED_WITH_LABEL as a_, type ExecutionCommand as aa, ExecutionCommands as ab, type ExecutionHost as ac, type ExecutionSummary as ad, type GatedConversation as ae, type GeneratePlanResponse as af, type GlobalRunSettings as ag, HEADLESS_CLI_COMMANDS as ah, type HandoffBlock as ai, type HandoffForkRepo as aj, type HandoffPeekSubject as ak, type IAiService as al, IDLE_ACTIVITY as am, type INotification as an, type IWebFetcher as ao, type IsolationDiffResponse as ap, type IsolationMergeResponse as aq, type IsolationPreviewNotice as ar, type IsolationPreviewResponse as as, IsolationRunController as at, LEASE_HEARTBEAT_MS as au, LEASE_STALE_MS as av, LeaseHost as aw, type LeaseHostKind as ax, type LeaseHostOptions as ay, type LiveOutputLookup as az, type AccountLimitBucket as b, type SessionData as b$, PendingApprovals as b0, type PendingApprovalsOptions as b1, type PlanBlock as b2, type PlanBlocks as b3, type PlanIntake as b4, type PlanMarkerStatus as b5, type PlanResponse as b6, type PlanSnapshot as b7, PlanStore as b8, type PlannerCommandSyntax as b9, type RewindTarget as bA, type RewindTargetsResponse as bB, type RunActivity as bC, type RunInput as bD, type RunMergeView as bE, RunSettingsError as bF, type RunSnapshotFrame as bG, type RunTask as bH, type RunTaskStatus as bI, type RunView as bJ, type RunnerAuth as bK, type RunnerAuthExec as bL, type RunnerAuthExecOptions as bM, type RunnerAuthExecResult as bN, type RunnerCatalog as bO, type RunnerLoadedBlock as bP, type RunnersResponse as bQ, STOPPED_BEFORE_START as bR, SUPERVISOR_LEVELS as bS, SUPERVISOR_LEVEL_LABEL as bT, type SerializedConversationMessage as bU, type SerializedPendingTurn as bV, type SerializedPlan as bW, type SerializedTask as bX, type SerializedTaskStatus as bY, type ServerInfoResponse as bZ, type SessionBroadcaster as b_, type PlannerContextDeps as ba, type PlannerContextStatus as bb, PlannerConversation as bc, type PlannerConversationHost as bd, type PlannerModelCandidate as be, type PlannerModelChoice as bf, PlannerModelMemory as bg, type PlannerModelRecall as bh, type PlannerModelStore as bi, type PlannerModes as bj, type PlannerNotReady as bk, PlannerNotReadyError as bl, type PlannerReadinessConfig as bm, type PlannerSubmission as bn, PlannerTurnDiscardedError as bo, PlannerTurnStoppedError as bp, PlannerUsageLimitError as bq, type PrdResponse as br, type PromptHold as bs, REPORT_PREVIEW_LINES as bt, RUN_SETTINGS_DEFAULTS as bu, type ReadRunnerAuthOptions as bv, type RefTask as bw, ResearchTasks as bx, type ResolveAll as by, type ResolveConflictResponse as bz, type AccountLimitSnapshot as c, type TaskRowPlacement as c$, type SessionFrame as c0, type SessionHeld as c1, SessionHeldError as c2, type SessionLease as c3, type SessionLeaseRecord as c4, type SessionListResponse as c5, type SessionMessage as c6, type SessionMeta as c7, type SessionNotice as c8, type SessionResponse as c9, type TaskLogBatch as cA, type TaskLogEvent as cB, type TaskLogFollow as cC, type TaskLogFollowInput as cD, type TaskLogHeaderKind as cE, type TaskLogHeaderTask as cF, type TaskLogHeaderUsage as cG, type TaskLogHeaderView as cH, type TaskLogResponse as cI, type TaskLogView as cJ, type TaskMessageResponse as cK, type TaskOp as cL, TaskOrchestrator as cM, type TaskOrchestratorDeps as cN, type TaskOrchestratorOptions as cO, type TaskOutputSource as cP, type TaskPlacement as cQ, type TaskQuery as cR, type TaskQueryCatalog as cS, type TaskQueryField as cT, type TaskRef as cU, type TaskRowAction as cV, type TaskRowContext as cW, type TaskRowHandoff as cX, type TaskRowIsolation as cY, type TaskRowKind as cZ, type TaskRowLoop as c_, type SettingsResponse as ca, SettingsService as cb, type SettingsUpdateResponse as cc, type SkillInvocation as cd, type SkillLoadBlock as ce, type SkillToken as cf, type StartAdmission as cg, type StopResponse as ch, type StreamStamp as ci, type SubagentBlock as cj, type SubagentChild as ck, type SubagentStatus as cl, type SupervisorPolicy as cm, type SurfacePlan as cn, type SurfacePlanState as co, type SurfaceTask as cp, TASK_QUERY_ANSWER_MAX_CHARS as cq, TASK_QUERY_ANSWER_OR_OPS as cr, TASK_QUERY_FIELDS as cs, TASK_QUERY_PROTOCOL as ct, TASK_QUERY_REMINDER as cu, TERMINAL_UI_COMMANDS as cv, type TakenPrompt as cw, type TaskAction as cx, type TaskAttemptSnapshot as cy, type TaskLogAttemptsResponse as cz, type AccountLimitStatus as d, describeMergeResult as d$, type TaskRowSubject as d0, type TaskRowUsage as d1, type TaskRowView as d2, type TaskRunFacts as d3, type TaskStatusKind as d4, type ThinkingDisplayBlock as d5, type ToolBlock as d6, type ToolHeadline as d7, type ToolStatus as d8, type TreeTask as d9, assignmentIssueText as dA, attachingLabel as dB, automergeSummary as dC, autorunSummary as dD, awaitingLabel as dE, blockNotice as dF, blockNotices as dG, blockedByLabel as dH, blockingFailures as dI, canMergeTasks as dJ, canSetDependencies as dK, canSplitTask as dL, capConflictFiles as dM, cardEditNeedsUnstarted as dN, cardEditable as dO, checkoutRule as dP, classifyOutcome as dQ, coalesceTaskLog as dR, compactionText as dS, confirmedOverride as dT, createAiService as dU, dependencyCandidates as dV, dependentsNotice as dW, dependentsOf as dX, describeHeld as dY, describeHolder as dZ, describeIsolationPreview as d_, TurnBudgets as da, type TurnGate as db, type UsageBlock as dc, type UserSettings as dd, WAITS_FOR_APPROVAL_LABEL as de, type WakeUpItem as df, type WebRead as dg, type WebReadDecision as dh, type WebReadOptions as di, WebReadPolicy as dj, type Worded as dk, type WorkspacesResponse as dl, abbreviateHome as dm, accountLimitPercentText as dn, accountLimitWindowLabel as dp, accountLimitsOf as dq, accountLimitsText as dr, accountLimitsTitle as ds, aheadOfDraft as dt, applyTaskOps as du, approvalKindText as dv, approvalLabel as dw, approvalStatusText as dx, assignedRunnerOf as dy, assignmentIssue as dz, type AccountLimitWindow as e, ranSealed as e$, describePlannerNotReady as e0, diffRows as e1, diffStat as e2, diffSummary as e3, digestTaskLog as e4, drainNext as e5, editableWhileRunning as e6, executionSummary as e7, followTaskLog as e8, followTurn as e9, mapAgentTool as eA, markAction as eB, markdownHtml as eC, markdownTokens as eD, mergeOutcome as eE, mergeTarget as eF, namedRepos as eG, newTaskFields as eH, noExecutorRefusal as eI, normalizeAgentArgs as eJ, opRefusalText as eK, opsEditable as eL, outputLines as eM, outputPreview as eN, overrideNeedsConfirmation as eO, parseCount as eP, parseSwitch as eQ, parseTaskOpsJson as eR, parseTaskQueryJson as eS, pastGateConfirmation as eT, planBlocks as eU, planMarkerParts as eV, plannerMessage as eW, plannerNotReady as eX, plannerNotReadyFor as eY, plannerTranscript as eZ, processLeaseHost as e_, fromTranscript as ea, getSettingsPath as eb, handoffBaseLine as ec, handoffBranchName as ed, handoffFindingsText as ee, handoffPeekParts as ef, hasAccountLimits as eg, hasHiddenDetail as eh, hasLongReport as ei, holdLabel as ej, holdPrompt as ek, isFileEditTool as el, isRepoGroup as em, isTaskRunning as en, lastServedModel as eo, loadedSkillTokens as ep, logContinues as eq, logResumes as er, loopBodyLabel as es, loopBodyRound as et, loopCheckLabel as eu, loopCheckState as ev, loopLeaveNotice as ew, loopRowParts as ex, manualOverrideConfirmation as ey, manualOverrideStopFirst as ez, type AccountLimitsFrame as f, truncateCheckpointSummary as f$, readRunnerAuth as f0, receiptLabel as f1, reconcileApprovals as f2, recordRunnerAuth as f3, recordedRunnerAuth as f4, reduceConversation as f5, reduceRun as f6, reduceTaskLog as f7, renderTaskQueryAnswer as f8, repairedLanded as f9, supervisorSummary as fA, surfacePlan as fB, surfacePlanState as fC, takeAt as fD, taskActionCommand as fE, taskChatAvailable as fF, taskLogCommands as fG, taskLogForSurface as fH, taskLogHeaderView as fI, taskOrderLabel as fJ, taskPlacement as fK, taskQuerySignature as fL, taskRef as fM, taskRefOf as fN, taskRowActions as fO, taskRowView as fP, taskStartedNotice as fQ, taskStatusKind as fR, textHasTaskOps as fS, textHasTaskQuery as fT, titledRefs as fU, titledTaskRef as fV, titledTaskRefOf as fW, toTaskLogEvent as fX, toolHeadline as fY, trailerSummary as fZ, trimToolOutput as f_, repairedNotice as fa, repeatingChecks as fb, replayTaskLog as fc, repoBaseLine as fd, repoResultLines as fe, reposWithWork as ff, resetRunnerAuth as fg, resolveSkillInvocation as fh, resolveTaskRef as fi, resolveUserTaskRef as fj, resumeLabel as fk, resumeTime as fl, runHoldsEditors as fm, runSettingsOf as fn, runnerToolSubject as fo, scriptExitText as fp, scriptRunText as fq, secondsText as fr, serializePlan as fs, serializeTask as ft, serializeTaskStatus as fu, skillTokens as fv, skippedLabel as fw, stopTurn as fx, subtreeIds as fy, summarizeToolCall as fz, type AccountLimitsMessage as g, unsendAll as g0, unsendLatest as g1, wakeUpItems as g2, walkPlan as g3, withoutSealedMark as g4, workspaceEnvOf as g5, type AdoptSessionResponse as h, type ApplyTaskOpsResult as i, type ApprovalAnswerResponse as j, type ApprovalBlock as k, type ApprovalRequestMessage as l, type ApprovalStatus as m, type ApprovalsResponse as n, type ApproveReviewResponse as o, type AskOptions as p, type AssignmentCatalog as q, type AssignmentIssue as r, type AssignmentScope as s, type AssignmentWriter as t, type AutoMergeTrigger as u, CHECKPOINT_TRUNCATE_LENGTH as v, type CancelPlanningResponse as w, type CancelResumeResponse as x, CliAgentAiService as y, type CliAgentAiServiceDeps as z };
|
|
8544
|
+
export { DELEGATION_RISK as $, ACT_RISK as A, type BlockingSubject as B, CHAT_COMMANDS as C, CliAgentAiService as D, type CliAgentAiServiceDeps as E, type CommandBlock as F, type CommandDescriptor as G, type CommandOutcome as H, type CommandPayload as I, type CommandStatus as J, type CommandsResponse as K, type CompactionBlock as L, type CompactionStatus as M, type Consent as N, type ContextCondenseRequest as O, ConversationBusyError as P, type ConversationCompactResponse as Q, type ConversationCompaction as R, ConversationEditError as S, type ConversationForkResponse as T, type ConversationInput as U, type ConversationRequest as V, type ConversationRewindResponse as W, type ConversationTurn as X, type ConversationView as Y, DEFAULT_WEB_READ_BUDGET as Z, DELEGATION_OFFERED as _, AUTORUN_RISK as a, type NodeBudget as a$, type DaemonErrorCode as a0, type DecideOptions as a1, type DiffRow as a2, type DiffRowKind as a3, type DiffStat as a4, type DisplayBlock as a5, EMPTY_CONVERSATION as a6, EMPTY_HOLD as a7, EMPTY_RUN as a8, EMPTY_TASK_LOG as a9, type IsolationMergeResponse as aA, type IsolationPreviewNotice as aB, type IsolationPreviewResponse as aC, LEASE_HEARTBEAT_MS as aD, LEASE_STALE_MS as aE, LeaseHost as aF, type LeaseHostKind as aG, type LeaseHostOptions as aH, type LiveOutputLookup as aI, type LiveTail as aJ, type LiveTailOptions as aK, type LocalEntry as aL, type LoopCheckFacts as aM, type LoopCheckState as aN, type LoopGuard as aO, type MappedTool as aP, type MarkdownToken as aQ, type MergeGateEntry as aR, type MergeGateResponse as aS, type MergeWordingHandoff as aT, type MessageBlock as aU, type MessageRole as aV, type ModelsResponse as aW, NOT_STARTED as aX, NO_TURN as aY, type NewTaskFields as aZ, NodeBoard as a_, EMPTY_TASK_LOG_FOLLOW as aa, type ErrorBody as ab, type Escalation as ac, type EscalationInput as ad, type EscalationKind as ae, type EscalationOption as af, type EscalationOptionId as ag, type EscalationRun as ah, type EscalationsResponse as ai, type ExecuteCommandResponse as aj, type ExecuteResponse as ak, type ExecutionCommand as al, ExecutionCommands as am, type ExecutionHost as an, type ExecutionSummary as ao, type GatedConversation as ap, type GeneratePlanResponse as aq, type GlobalRunSettings as ar, HEADLESS_CLI_COMMANDS as as, type HandoffBlock as at, type HandoffForkRepo as au, type HandoffPeekSubject as av, type IAiService as aw, IDLE_ACTIVITY as ax, type IWebFetcher as ay, type IsolationDiffResponse as az, type AccountLimitBucket as b, type RunnerCatalog as b$, OUTPUT_LINES_DEFAULT as b0, OUTPUT_LINES_MAX as b1, type OkResponse as b2, type OpRef as b3, type OpRefusal as b4, type OrchestratorObserver as b5, type OutputPreview as b6, type OverrideDirection as b7, PLANNED_WITH_LABEL as b8, type PendingApproval as b9, type PrdResponse as bA, type PromptHold as bB, REPORT_PREVIEW_LINES as bC, RUN_SETTINGS_DEFAULTS as bD, type ReadRunnerAuthOptions as bE, type RefTask as bF, ResearchTasks as bG, type ResolveAll as bH, type ResolveConflictResponse as bI, type RevertPreviewTask as bJ, type RevertRefusal as bK, type RevertRefusalReason as bL, type RevertScope as bM, type RewindTarget as bN, type RewindTargetsResponse as bO, type RunActivity as bP, type RunInput as bQ, type RunMergeView as bR, RunSettingsError as bS, type RunSnapshotFrame as bT, type RunTask as bU, type RunTaskStatus as bV, type RunView as bW, type RunnerAuth as bX, type RunnerAuthExec as bY, type RunnerAuthExecOptions as bZ, type RunnerAuthExecResult as b_, PendingApprovals as ba, type PendingApprovalsOptions as bb, type PlanBlock as bc, type PlanBlocks as bd, type PlanIntake as be, type PlanMarkerStatus as bf, type PlanResponse as bg, type PlanSnapshot as bh, PlanStore as bi, type PlannerCommandSyntax as bj, type PlannerContextDeps as bk, type PlannerContextStatus as bl, PlannerConversation as bm, type PlannerConversationHost as bn, type PlannerModelCandidate as bo, type PlannerModelChoice as bp, PlannerModelMemory as bq, type PlannerModelRecall as br, type PlannerModelStore as bs, type PlannerNotReady as bt, PlannerNotReadyError as bu, type PlannerReadinessConfig as bv, type PlannerSubmission as bw, PlannerTurnDiscardedError as bx, PlannerTurnStoppedError as by, PlannerUsageLimitError as bz, type AccountLimitSnapshot as c, type TaskMessageResponse as c$, type RunnerLoadedBlock as c0, type RunnersResponse as c1, STALLED_LABEL as c2, STOPPED_BEFORE_START as c3, STOPPING_LABEL as c4, SUPERVISOR_LEVEL_LABEL as c5, type SerializedConversationMessage as c6, type SerializedPendingTurn as c7, type SerializedPlan as c8, type SerializedTask as c9, Subtree as cA, type SubtreeItemView as cB, type SubtreeView as cC, type SurfacePlan as cD, type SurfacePlanState as cE, type SurfaceTask as cF, TASK_QUERY_ANSWER_MAX_CHARS as cG, TASK_QUERY_ANSWER_OR_OPS as cH, TASK_QUERY_FIELDS as cI, TASK_QUERY_PROTOCOL as cJ, TASK_QUERY_REMINDER as cK, TERMINAL_UI_COMMANDS as cL, type TakenPrompt as cM, type TaskAction as cN, type TaskActivity as cO, type TaskAttemptSnapshot as cP, type TaskLogAttemptsResponse as cQ, type TaskLogBatch as cR, type TaskLogEvent as cS, type TaskLogFollow as cT, type TaskLogFollowInput as cU, type TaskLogHeaderKind as cV, type TaskLogHeaderTask as cW, type TaskLogHeaderUsage as cX, type TaskLogHeaderView as cY, type TaskLogResponse as cZ, type TaskLogView as c_, type SerializedTaskStatus as ca, type ServerInfoResponse as cb, type SessionBroadcaster as cc, type SessionFrame as cd, type SessionHeld as ce, SessionHeldError as cf, type SessionLease as cg, type SessionLeaseRecord as ch, type SessionListResponse as ci, type SessionMessage as cj, type SessionNotice as ck, type SessionResponse as cl, type SettingsResponse as cm, SettingsService as cn, type SettingsUpdateResponse as co, type SkillInvocation as cp, type SkillLoadBlock as cq, type SkillToken as cr, SlotPool as cs, type StartAdmission as ct, type StopResponse as cu, type StreamStamp as cv, type SubagentBlock as cw, type SubagentChild as cx, type SubagentStatus as cy, type SubplannerBrief as cz, type AccountLimitStatus as d, blockNotice as d$, type TaskOp as d0, TaskOrchestrator as d1, type TaskOrchestratorDeps as d2, type TaskOrchestratorOptions as d3, type TaskOutputSource as d4, type TaskPlacement as d5, type TaskQuery as d6, type TaskQueryCatalog as d7, type TaskQueryField as d8, type TaskRef as d9, WAITS_FOR_APPROVAL_LABEL as dA, type WakeUpItem as dB, type WebRead as dC, type WebReadDecision as dD, type WebReadOptions as dE, WebReadPolicy as dF, type Worded as dG, type WorkspacesResponse as dH, abbreviateHome as dI, accountLimitPercentText as dJ, accountLimitWindowLabel as dK, accountLimitsOf as dL, accountLimitsText as dM, accountLimitsTitle as dN, activityLabel as dO, aheadOfDraft as dP, applyTaskOps as dQ, approvalKindText as dR, approvalLabel as dS, approvalStatusText as dT, assignedRunnerOf as dU, assignmentIssue as dV, assignmentIssueText as dW, attachingLabel as dX, automergeSummary as dY, autorunSummary as dZ, awaitingLabel as d_, type TaskRevertPreview as da, type TaskRevertPreviewResponse as db, type TaskRowAction as dc, type TaskRowContext as dd, type TaskRowDelegated as de, type TaskRowHandoff as df, type TaskRowIsolation as dg, type TaskRowKind as dh, type TaskRowLoop as di, type TaskRowPlacement as dj, type TaskRowSubject as dk, type TaskRowUsage as dl, type TaskRowView as dm, type TaskRunFacts as dn, type TaskStatusKind as dp, type ThinkingDisplayBlock as dq, type ToolBlock as dr, type ToolHeadline as ds, type ToolStatus as dt, TreeLedger as du, type TreeTask as dv, TurnBudgets as dw, type TurnGate as dx, type UsageBlock as dy, type UserSettings as dz, type AccountLimitWindow as e, manualOverrideStopFirst as e$, blockNotices as e0, blockedByLabel as e1, blockingFailures as e2, canMergeTasks as e3, canSetDependencies as e4, canSplitTask as e5, capConflictFiles as e6, cardEditNeedsUnstarted as e7, cardEditable as e8, checkoutRule as e9, followTurn as eA, formatElapsed as eB, fromTranscript as eC, getSettingsPath as eD, handoffBaseLine as eE, handoffBranchName as eF, handoffFindingsText as eG, handoffPeekParts as eH, hasAccountLimits as eI, hasHiddenDetail as eJ, hasLongReport as eK, holdLabel as eL, holdPrompt as eM, isFileEditTool as eN, isRepoGroup as eO, isTaskRunning as eP, lastServedModel as eQ, loadedSkillTokens as eR, logContinues as eS, logResumes as eT, loopBodyLabel as eU, loopBodyRound as eV, loopCheckLabel as eW, loopCheckState as eX, loopLeaveNotice as eY, loopRowParts as eZ, manualOverrideConfirmation as e_, classifyOutcome as ea, closeTurn as eb, coalesceTaskLog as ec, compactionText as ed, confirmedOverride as ee, createAiService as ef, delegatedRowView as eg, delegationSummary as eh, dependencyCandidates as ei, dependentsNotice as ej, dependentsOf as ek, describeHeld as el, describeHolder as em, describeIsolationPreview as en, describeMergeResult as eo, describePlannerNotReady as ep, diffRows as eq, diffStat as er, diffSummary as es, digestTaskLog as et, drainNext as eu, editableWhileRunning as ev, elapsedSince as ew, escalations as ex, executionSummary as ey, followTaskLog as ez, type AccountLimitsFrame as f, serializeTask as f$, mapAgentTool as f0, markAction as f1, markdownHtml as f2, markdownTokens as f3, mergeOutcome as f4, mergePastChecksConfirmation as f5, mergeTarget as f6, namedRepos as f7, newTaskFields as f8, noExecutorRefusal as f9, reduceRun as fA, reduceTaskLog as fB, renderTaskQueryAnswer as fC, repairWaitLabel as fD, repairedLanded as fE, repairedNotice as fF, repeatingChecks as fG, replayTaskLog as fH, repoBaseLine as fI, repoResultLines as fJ, reposWithWork as fK, resetRunnerAuth as fL, resolveSkillInvocation as fM, resolveTaskRef as fN, resolveUserTaskRef as fO, resumeLabel as fP, resumeTime as fQ, revertEffect as fR, revertListLine as fS, revertTaskRef as fT, runHoldsEditors as fU, runSettingsOf as fV, runnerToolSubject as fW, scriptExitText as fX, scriptRunText as fY, secondsText as fZ, serializePlan as f_, normalizeAgentArgs as fa, opRefusalText as fb, opsEditable as fc, outputLines as fd, outputPreview as fe, overrideNeedsConfirmation as ff, parseCount as fg, parseDelegation as fh, parseSwitch as fi, parseTaskOpsJson as fj, parseTaskQueryJson as fk, pastGateConfirmation as fl, planBlocks as fm, planMarkerParts as fn, plannerMessage as fo, plannerNotReady as fp, plannerNotReadyFor as fq, plannerTranscript as fr, processLeaseHost as fs, ranSealed as ft, readRunnerAuth as fu, receiptLabel as fv, reconcileApprovals as fw, recordRunnerAuth as fx, recordedRunnerAuth as fy, reduceConversation as fz, type AccountLimitsMessage as g, serializeTaskStatus as g0, skillTokens as g1, skippedLabel as g2, stopTurn as g3, subtreeIds as g4, subtreeView as g5, summarizeToolCall as g6, supervisorSummary as g7, surfacePlan as g8, surfacePlanState as g9, unsendAll as gA, unsendLatest as gB, wakeUpItems as gC, walkPlan as gD, withoutSealedMark as gE, workspaceEnvOf as gF, takeAt as ga, taskActionCommand as gb, taskActivity as gc, taskChatAvailable as gd, taskLogCommands as ge, taskLogForSurface as gf, taskLogHeaderView as gg, taskOrderLabel as gh, taskPlacement as gi, taskQuerySignature as gj, taskRef as gk, taskRefOf as gl, taskRowActions as gm, taskRowView as gn, taskStartedNotice as go, taskStatusKind as gp, textHasTaskOps as gq, textHasTaskQuery as gr, titledRefs as gs, titledTaskRef as gt, titledTaskRefOf as gu, toTaskLogEvent as gv, toolHeadline as gw, trailerSummary as gx, trimToolOutput as gy, truncateCheckpointSummary as gz, type AdoptSessionResponse as h, type AnswerEscalationRequest as i, type ApplyTaskOpsResult as j, type ApprovalAnswerResponse as k, type ApprovalBlock as l, type ApprovalRequestMessage as m, type ApprovalStatus as n, type ApprovalsResponse as o, type ApproveReviewResponse as p, type AskOptions as q, type AssignmentCatalog as r, type AssignmentIssue as s, type AssignmentScope as t, type AssignmentWriter as u, type AutoMergeTrigger as v, CHECKPOINT_TRUNCATE_LENGTH as w, type CancelPlanningResponse as x, type CancelResumeResponse as y, type Carved as z };
|