@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
|
@@ -5,9 +5,14 @@ declare const SEVERITY_LABEL: Record<FindingSeverity, string>;
|
|
|
5
5
|
declare function severityLabel(severity: FindingSeverity): string;
|
|
6
6
|
/** The worst severity among `findings`, or null for none: what a compact row says at a glance. */
|
|
7
7
|
declare function worstSeverity(findings: readonly Pick<HandoffFinding, 'severity'>[]): FindingSeverity | null;
|
|
8
|
+
/** The root's plan: the node a pinned reference is under until a plan below names its own (ADR-0057 R1). */
|
|
9
|
+
declare const ROOT_NODE = "root";
|
|
8
10
|
/**
|
|
9
11
|
* A typed reference a reader can check rather than trust. A `task` names the
|
|
10
12
|
* task by id once the call is accepted, and `finding` one of its findings.
|
|
13
|
+
* `node` and `attempt` pin it (ADR-0057 R1): F numbers restart per attempt, so
|
|
14
|
+
* a finding is named only with the attempt it belongs to. One saved before
|
|
15
|
+
* pinning has neither, and reads the latest attempt as it always did.
|
|
11
16
|
* `resolved` is read-time metadata: the author cannot vouch for resolution,
|
|
12
17
|
* so the completion schema strips it and the saved handoff carries no check.
|
|
13
18
|
*/
|
|
@@ -21,14 +26,23 @@ type HandoffEvidence = {
|
|
|
21
26
|
sha: string;
|
|
22
27
|
repo?: string;
|
|
23
28
|
resolved?: boolean;
|
|
24
|
-
} | {
|
|
25
|
-
kind: 'task';
|
|
26
|
-
task: string;
|
|
27
|
-
finding?: string;
|
|
28
|
-
} | {
|
|
29
|
+
} | TaskEvidence | {
|
|
29
30
|
kind: 'url';
|
|
30
31
|
url: string;
|
|
31
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* `label` is how the task's own plan names it, kept once a reference has
|
|
35
|
+
* crossed a level: a reader in another plan has no plan to name it from, and a
|
|
36
|
+
* task id can repeat between plans, so no plan names one that has it.
|
|
37
|
+
*/
|
|
38
|
+
interface TaskEvidence {
|
|
39
|
+
kind: 'task';
|
|
40
|
+
node?: string;
|
|
41
|
+
task: string;
|
|
42
|
+
attempt?: number;
|
|
43
|
+
finding?: string;
|
|
44
|
+
label?: string;
|
|
45
|
+
}
|
|
32
46
|
/**
|
|
33
47
|
* What a saved patch does not carry as the task's worktree held it
|
|
34
48
|
* (ADR-0050): `excluded`, a symbolic link or a submodule, never carried;
|
|
@@ -85,6 +99,41 @@ interface HandoffCommit {
|
|
|
85
99
|
subject: string;
|
|
86
100
|
body?: string;
|
|
87
101
|
}
|
|
102
|
+
/** A finding as it crossed a level (ADR-0057 R2): its author's words, by the reference that names it. A subplanner's own has none. */
|
|
103
|
+
interface ReportItem {
|
|
104
|
+
ref?: TaskEvidence;
|
|
105
|
+
finding: HandoffFinding;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* What a delegated task's report carries past any task's (ADR-0057 R2). All of
|
|
109
|
+
* it comes from Ordewell, the findings by reference, so what a subplanner left
|
|
110
|
+
* out shows and it cannot have reworded what it passes on. It is read once, as
|
|
111
|
+
* the report is taken, so the renderer stays a pure function of the digest:
|
|
112
|
+
* references are pinned, so the words cannot have moved.
|
|
113
|
+
*/
|
|
114
|
+
interface SubtreeReport {
|
|
115
|
+
/** The child plan's node: what a read of this report's subtree starts from. */
|
|
116
|
+
node: string;
|
|
117
|
+
counts: {
|
|
118
|
+
done: number;
|
|
119
|
+
failed: number;
|
|
120
|
+
blocked: number;
|
|
121
|
+
skipped: number;
|
|
122
|
+
commits: number;
|
|
123
|
+
tokens: number;
|
|
124
|
+
};
|
|
125
|
+
/** Every finding below, by severity, read from the latest attempt of each task. */
|
|
126
|
+
findings: Record<FindingSeverity, number>;
|
|
127
|
+
/** What the parent must decide. */
|
|
128
|
+
open: ReportItem[];
|
|
129
|
+
/** What the subplanner passed up. */
|
|
130
|
+
promoted: ReportItem[];
|
|
131
|
+
/** What its branch changed outside its declared scope, first paths and how many (ADR-0056 M7). */
|
|
132
|
+
outsideScope?: {
|
|
133
|
+
paths: string[];
|
|
134
|
+
count: number;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
88
137
|
/** What the plan keeps on a task: enough for a surface or a dependent's prompt without reading a log. */
|
|
89
138
|
interface HandoffDigest {
|
|
90
139
|
commit?: HandoffCommit;
|
|
@@ -93,6 +142,12 @@ interface HandoffDigest {
|
|
|
93
142
|
findings: HandoffFinding[];
|
|
94
143
|
findingCount: number;
|
|
95
144
|
artifacts?: HandoffArtifact[];
|
|
145
|
+
/** The attempt it is from, which a reference to it is pinned to (ADR-0057 R1); absent on a plan saved before it was kept. */
|
|
146
|
+
attempt?: number;
|
|
147
|
+
/** A delegated task's: what Ordewell derived of its subtree. */
|
|
148
|
+
subtree?: SubtreeReport;
|
|
149
|
+
/** A delegated task's words with no {@link subtree} to say whose they are: a repair's, or a report that never opened a child. */
|
|
150
|
+
held?: true;
|
|
96
151
|
}
|
|
97
152
|
/** The whole handoff, as the attempt's log keeps it. */
|
|
98
153
|
interface StoredHandoff extends HandoffDigest {
|
|
@@ -107,6 +162,7 @@ interface Handoff {
|
|
|
107
162
|
findings?: Omit<HandoffFinding, 'id'>[];
|
|
108
163
|
artifacts?: HandoffArtifact[];
|
|
109
164
|
report?: string;
|
|
165
|
+
subtree?: SubtreeReport;
|
|
110
166
|
}
|
|
111
167
|
/** The most a report keeps: whole findings fit, and a runaway one does not bloat the files that hold it. */
|
|
112
168
|
declare const REPORT_MAX_CHARS = 20000;
|
|
@@ -119,6 +175,7 @@ declare const HANDOFF_LIMITS: {
|
|
|
119
175
|
readonly commitSubject: 100;
|
|
120
176
|
readonly commitBody: 500;
|
|
121
177
|
readonly findings: 50;
|
|
178
|
+
readonly promoted: 8;
|
|
122
179
|
readonly title: 200;
|
|
123
180
|
readonly detail: 2000;
|
|
124
181
|
readonly reference: 2000;
|
|
@@ -144,7 +201,50 @@ declare function handoffDigest(handoff: StoredHandoff): HandoffDigest;
|
|
|
144
201
|
type HandoffTaskName = (taskId: string) => string | undefined;
|
|
145
202
|
/** A handoff with the tasks it cites named by their references in `plan`, as a reader names them. */
|
|
146
203
|
declare function namedHandoff<H extends HandoffDigest>(plan: readonly Task[], handoff: H): H;
|
|
147
|
-
/** A
|
|
204
|
+
/** A task reference as a reader writes it and an author may: `#4@2/F3`, `#4/F3`, `#4@2` or `#4` (ADR-0057 R1). */
|
|
205
|
+
interface WrittenTaskRef {
|
|
206
|
+
task: string;
|
|
207
|
+
attempt?: number;
|
|
208
|
+
finding?: string;
|
|
209
|
+
}
|
|
210
|
+
/** The plan a written reference names below this one, `3/2:#4@2/F3`, and the rest as a plan reads it (ADR-0057 R1). */
|
|
211
|
+
declare function parsePlanPath(written: string): {
|
|
212
|
+
path: string;
|
|
213
|
+
rest: string;
|
|
214
|
+
} | undefined;
|
|
215
|
+
/** A node's path as a reader writes it: `root/3/2` is `3/2`. */
|
|
216
|
+
declare function nodeText(node: string): string;
|
|
217
|
+
/**
|
|
218
|
+
* The parts of a written reference, its task as written. What this cuts off
|
|
219
|
+
* is no part of `TaskRefs`' grammar, which stays as it was; a caller tries the
|
|
220
|
+
* text whole first, since a title may end in anything.
|
|
221
|
+
*/
|
|
222
|
+
declare function parseFindingRef(written: string): WrittenTaskRef;
|
|
223
|
+
/**
|
|
224
|
+
* A written reference resolved in a plan, its pin apart. The text is tried
|
|
225
|
+
* whole first: a title may end in anything, and a task it names stands as it
|
|
226
|
+
* always did. Undefined when it names no task there.
|
|
227
|
+
*/
|
|
228
|
+
declare function resolveWrittenRef(plan: readonly Task[], written: string): (Omit<WrittenTaskRef, 'task'> & {
|
|
229
|
+
task: Task;
|
|
230
|
+
}) | undefined;
|
|
231
|
+
/**
|
|
232
|
+
* The attempt of a removed task a reference naming no task in the plan reaches,
|
|
233
|
+
* by the id it renders with: a removed task keeps its log (ADR-0057 R1). The
|
|
234
|
+
* graph no longer reaches that task, so a citation does: a handoff in the
|
|
235
|
+
* reader's readable set must cite the attempt, since a task cannot read work it
|
|
236
|
+
* was never given (ADR-0047). A citation saved unpinned cites the latest, and a
|
|
237
|
+
* reference naming no attempt takes the newest one cited. `asked` is an attempt
|
|
238
|
+
* given apart from the text. Undefined when nothing it may read cites one.
|
|
239
|
+
*/
|
|
240
|
+
declare function removedAttempt(plan: readonly Task[], readable: ReadonlySet<string>, logs: HandoffLogs, written: string, asked?: number): {
|
|
241
|
+
taskId: string;
|
|
242
|
+
attempt: number;
|
|
243
|
+
finding?: string;
|
|
244
|
+
} | undefined;
|
|
245
|
+
/** The pinned reference as text: `#4@2/F3` (ADR-0057 R1); `task` is how the reader names it. */
|
|
246
|
+
declare function findingRefText(task: string, ref: Pick<WrittenTaskRef, 'attempt' | 'finding'>): string;
|
|
247
|
+
/** A typed reference as a reader says it: `src/a.ts:42`, `commit abc`, `#2@1/F1`, a URL, a saved patch. */
|
|
148
248
|
declare function handoffReferenceText(ref: HandoffArtifact, taskName?: HandoffTaskName): string;
|
|
149
249
|
/** A size as a reader takes it in: bytes, KB or MB. */
|
|
150
250
|
declare function byteSize(bytes: number): string;
|
|
@@ -195,8 +295,20 @@ declare function savedPatchView(handoff: HandoffDigest | undefined): PatchView |
|
|
|
195
295
|
declare function findingLines(f: HandoffFinding, taskName?: HandoffTaskName): string[];
|
|
196
296
|
/** A handoff's artifacts as one line, or none when it lists none. */
|
|
197
297
|
declare function artifactLines(handoff: HandoffDigest, taskName?: HandoffTaskName): string[];
|
|
298
|
+
/** A delegated task's words as its parent's update holds them, every line indented, so none can pass for a line of Ordewell's (ADR-0057 R3). */
|
|
299
|
+
declare function heldWords(text: string): string[];
|
|
300
|
+
/** The same handoff, marked as a delegated task's where no report already says so: a mark that travels with it to whatever renders it. */
|
|
301
|
+
declare function heldHandoff<H extends HandoffDigest>(task: {
|
|
302
|
+
type?: string;
|
|
303
|
+
}, handoff: H): H;
|
|
198
304
|
/** A handoff's opening as text: its commit, subject then body, then the summary. */
|
|
199
305
|
declare function openingLines(handoff: HandoffDigest): string[];
|
|
306
|
+
/**
|
|
307
|
+
* How another task's words are introduced wherever they cross into a prompt
|
|
308
|
+
* or a run update (ADR-0057 R3): whose they are, and that they are data. On
|
|
309
|
+
* every wake and every dependency, so it stays this short.
|
|
310
|
+
*/
|
|
311
|
+
declare function wordsFrom(what: string, whose: string): string;
|
|
200
312
|
/** Each pushed handoff's text ceiling, excluding artifacts (ADR-0047). */
|
|
201
313
|
declare const HANDOFF_PUSH_CHARS = 4000;
|
|
202
314
|
/** Shared push rendering: reserve the closing pointer before accepting each whole finding. */
|
|
@@ -239,17 +351,56 @@ type HandoffCheck<H> = {
|
|
|
239
351
|
ok: false;
|
|
240
352
|
refusal: string;
|
|
241
353
|
};
|
|
354
|
+
/** What the session's saved logs say of a task's attempts, for a reference to be pinned against (ADR-0057 R1). */
|
|
355
|
+
interface HandoffLogs {
|
|
356
|
+
/** The attempts of a task that have a saved log, oldest first. */
|
|
357
|
+
attempts(taskId: string): readonly number[];
|
|
358
|
+
/** The handoff one attempt ended with, if its log holds one. */
|
|
359
|
+
handoff(taskId: string, attempt: number): HandoffDigest | undefined;
|
|
360
|
+
}
|
|
361
|
+
interface HandoffPins {
|
|
362
|
+
/** The saved logs; without them a reference pins to what the plan's digest says, or stays unpinned. */
|
|
363
|
+
logs?: HandoffLogs;
|
|
364
|
+
/** The attempt making the call: what a task naming itself is pinned to. */
|
|
365
|
+
attempt?: number;
|
|
366
|
+
/** The plan these references are pinned under. Absent, the root's. */
|
|
367
|
+
node?: string;
|
|
368
|
+
/** What the producer may cite in `plan`, for one the plan's graph cannot give it: a subplanner, the plan below its own delegated task, is in none of its tasks' graphs. */
|
|
369
|
+
readable?: ReadonlySet<string>;
|
|
370
|
+
/** The plan at a path below this one that the producer may read; undefined for one it may not, or that is not there. */
|
|
371
|
+
below?: (path: string) => BelowPlan | undefined;
|
|
372
|
+
/** The handoff goes up a level, so what it cites keeps the name its plan gives it. */
|
|
373
|
+
crossing?: true;
|
|
374
|
+
}
|
|
375
|
+
/** A plan of the subtree, as a reference reads it. */
|
|
376
|
+
interface BelowPlan {
|
|
377
|
+
node: string;
|
|
378
|
+
tasks: readonly Task[];
|
|
379
|
+
logs: HandoffLogs;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* One written reference pinned, in the producer's plan or a plan below it:
|
|
383
|
+
* the text is tried whole first, since a title may read like a path.
|
|
384
|
+
*/
|
|
385
|
+
declare function pinReference(plan: readonly Task[], producerId: string, pins: HandoffPins, ref: TaskEvidence, field: string, findings: number, refuse: (why: string) => void): TaskEvidence | undefined;
|
|
242
386
|
/**
|
|
243
387
|
* Check the references a handoff makes, at the call (ADR-0047): a `task`
|
|
244
388
|
* must be one the producer may read and a finding of it one that exists, and
|
|
245
389
|
* a `url` must be http or https, so no surface renders a `javascript:` link.
|
|
246
390
|
* A `file` or `commit` is a claim about a tree Ordewell may not see, so it is
|
|
247
391
|
* taken as given. An accepted handoff names each task by its id, which a
|
|
248
|
-
* later edit of the plan does not renumber
|
|
249
|
-
|
|
250
|
-
|
|
392
|
+
* later edit of the plan does not renumber, and the attempt it read, so a
|
|
393
|
+
* retry or a loop round that numbers its findings anew leaves it meaning what
|
|
394
|
+
* it meant (ADR-0057 R1). A task with nothing to say its attempt by stays
|
|
395
|
+
* unpinned, and reads the latest, as a reference saved before pinning does. A
|
|
396
|
+
* removed task may be cited where a handoff the producer may read cites it, so
|
|
397
|
+
* what it read can be passed on ({@link removedAttempt}).
|
|
398
|
+
*/
|
|
399
|
+
declare function checkHandoff<H extends Handoff>(handoff: H, producerId: string, plan: readonly Task[], pins?: HandoffPins): HandoffCheck<H>;
|
|
251
400
|
|
|
252
401
|
interface TaskDiffRead {
|
|
402
|
+
/** Only the changed paths, joined by NUL: what a verdict reads (ADR-0055 D6). */
|
|
403
|
+
names?: boolean;
|
|
253
404
|
repo?: string;
|
|
254
405
|
path?: string;
|
|
255
406
|
}
|
|
@@ -403,6 +554,8 @@ interface IsolationTaskRecord {
|
|
|
403
554
|
status: IsolationTaskStatus;
|
|
404
555
|
/** Keyed by repo path. */
|
|
405
556
|
repos: Record<string, IsolationTaskRepo>;
|
|
557
|
+
/** The child session whose code root this worktree is (ADR-0055 D11): what stops a prune taking it from under that child (D17). */
|
|
558
|
+
childSession?: string;
|
|
406
559
|
/** Unrecovered branches from a conflict fallback, so a later continue cannot forget them. */
|
|
407
560
|
continuationWork?: PreservedWork[];
|
|
408
561
|
/** The repo whose merge stopped the task from landing, while `status` is `conflict` or `failed`. */
|
|
@@ -445,10 +598,12 @@ interface IsolationTaskRecord {
|
|
|
445
598
|
*/
|
|
446
599
|
readOnly?: true;
|
|
447
600
|
/**
|
|
448
|
-
* Set once the task's landed work is
|
|
449
|
-
* it
|
|
450
|
-
*
|
|
451
|
-
* gate waits for (ADR-0020).
|
|
601
|
+
* Set once the task's landed work is merged into the user's branch in every
|
|
602
|
+
* repo it landed in, by Merge all or by hand — never by a checkout that only
|
|
603
|
+
* stands on the integration branch (ADR-0054) — or can no longer be merged
|
|
604
|
+
* there, its integration branch gone. What a merge gate waits for (ADR-0020).
|
|
605
|
+
* Git's answer as last read, so it goes when the user takes the merge back
|
|
606
|
+
* out; it goes with the record too, so a revert asks git of each merge instead.
|
|
452
607
|
*/
|
|
453
608
|
inHead?: true;
|
|
454
609
|
}
|
|
@@ -462,6 +617,16 @@ interface IsolationLanding {
|
|
|
462
617
|
taskId: string;
|
|
463
618
|
/** Keyed by repo path. */
|
|
464
619
|
tips: Record<string, string>;
|
|
620
|
+
/**
|
|
621
|
+
* Set when this is a revert rather than a landing (ADR-0054), by repo path:
|
|
622
|
+
* what a rollback has to find on that repo's tip to take it off again.
|
|
623
|
+
*/
|
|
624
|
+
reverts?: Record<string, IsolationRepoRevert>;
|
|
625
|
+
}
|
|
626
|
+
/** A revert's share of one repo, saved so that it can tell its own commits from anyone else's. */
|
|
627
|
+
interface IsolationRepoRevert {
|
|
628
|
+
/** The commits it has made, oldest first, each saved before the branch moves onto it. */
|
|
629
|
+
commits: string[];
|
|
465
630
|
}
|
|
466
631
|
/**
|
|
467
632
|
* One repository of the group (ADR-0014). Every git operation on it runs in
|
|
@@ -491,7 +656,13 @@ interface IsolationRepo {
|
|
|
491
656
|
*/
|
|
492
657
|
interface IsolationRun {
|
|
493
658
|
id: string;
|
|
659
|
+
/** The code root: what git reads for the run's repos, branch and base (ADR-0055 D11). */
|
|
494
660
|
workspaceRoot: string;
|
|
661
|
+
/**
|
|
662
|
+
* A child run's state root, the root Session's workspace: where its worktrees
|
|
663
|
+
* and Ordewell's own files go. Absent on a flat run, whose workspace is both.
|
|
664
|
+
*/
|
|
665
|
+
stateRoot?: string;
|
|
495
666
|
repos: IsolationRepo[];
|
|
496
667
|
/**
|
|
497
668
|
* Workspace paths outside every isolated repo, linked live into each task
|
|
@@ -511,6 +682,51 @@ interface IsolationRun {
|
|
|
511
682
|
* names exactly what to return each repo's integration branch to.
|
|
512
683
|
*/
|
|
513
684
|
landing?: IsolationLanding;
|
|
685
|
+
/**
|
|
686
|
+
* Every merge that landed a task, by task id and repo, oldest first. A
|
|
687
|
+
* continue or a retry lands a task again under a new record, so no record
|
|
688
|
+
* holds them all, and a revert takes them all back (ADR-0054). A run saved
|
|
689
|
+
* before these were kept has only each record's `landedTip`.
|
|
690
|
+
*/
|
|
691
|
+
landings?: Record<string, Record<string, string[]>>;
|
|
692
|
+
/**
|
|
693
|
+
* Set on a run started with {@link landings} kept from its first merge. A
|
|
694
|
+
* run saved before that can hold merges no record names, so a revert cannot
|
|
695
|
+
* take the absence of a task's landings as proof it landed nothing.
|
|
696
|
+
*/
|
|
697
|
+
keepsEveryLanding?: true;
|
|
698
|
+
/**
|
|
699
|
+
* Task branch tips another task's merge brought in, by task id and repo: a
|
|
700
|
+
* resolver's merge carrying a conflicted task's work. No merge of that task
|
|
701
|
+
* holds this work, and a later attempt's record says nothing of it, so
|
|
702
|
+
* neither task can be reverted (ADR-0054). A tip git could not say of when
|
|
703
|
+
* that merge landed is here too. Set on every run as it starts, empty
|
|
704
|
+
* included: a run without it is older, what its merges carried is unknown,
|
|
705
|
+
* and every revert of it is refused.
|
|
706
|
+
*/
|
|
707
|
+
carried?: Record<string, Record<string, string[]>>;
|
|
708
|
+
/**
|
|
709
|
+
* What each task in {@link landings} or {@link carried} landed as: all a
|
|
710
|
+
* revert has to name it by once a retry has dropped its record and left its
|
|
711
|
+
* merges on the branch.
|
|
712
|
+
*/
|
|
713
|
+
landedTasks?: Record<string, LandedTask>;
|
|
714
|
+
/**
|
|
715
|
+
* What each task depended on when its worktree was cut and when it landed,
|
|
716
|
+
* directly or not, by task id, across every attempt. A plan edit takes a link
|
|
717
|
+
* while a worktree stays cut from what it stood on, and leaving the plan takes
|
|
718
|
+
* a task's dependencies with it, and those of the tasks that named it, while
|
|
719
|
+
* its merges stay on the branch, so this is what finds a dependent the plan
|
|
720
|
+
* has lost, at work or landed. A landed task the plan no longer has and this
|
|
721
|
+
* does not name refuses every revert of the run (ADR-0054).
|
|
722
|
+
*/
|
|
723
|
+
landedOn?: Record<string, string[]>;
|
|
724
|
+
/**
|
|
725
|
+
* A task's revert was committed on this run (ADR-0054): the integration
|
|
726
|
+
* branch holds commits no record names, so the run carries on even with no
|
|
727
|
+
* record left, and a retry starts from its tip.
|
|
728
|
+
*/
|
|
729
|
+
reverted?: true;
|
|
514
730
|
}
|
|
515
731
|
/**
|
|
516
732
|
* What a plan persists of isolated execution (`LegacyPlanState.isolation`): its
|
|
@@ -530,8 +746,13 @@ interface PlanIsolation {
|
|
|
530
746
|
* that has an isolation run.
|
|
531
747
|
*/
|
|
532
748
|
type TaskIsolationState = 'none' | 'active' | 'integrated' | 'conflict' | 'repairing' | 'kept';
|
|
533
|
-
|
|
749
|
+
/** What a conflict repair that will start by itself waits for (ADR-0015). */
|
|
750
|
+
type RepairWait = 'slot' | 'planner' | 'usage-limit';
|
|
751
|
+
type TaskIsolation =
|
|
752
|
+
/** `revertible`: no record, but merges of an earlier attempt are still on the branch. */
|
|
753
|
+
{
|
|
534
754
|
state: 'none';
|
|
755
|
+
revertible?: true;
|
|
535
756
|
} | {
|
|
536
757
|
state: Exclude<TaskIsolationState, 'none'>;
|
|
537
758
|
branch: string;
|
|
@@ -549,6 +770,12 @@ type TaskIsolation = {
|
|
|
549
770
|
};
|
|
550
771
|
/** What {@link IsolationTaskRecord.repairedFiles} says. */
|
|
551
772
|
repairedFiles?: string[];
|
|
773
|
+
/** Its landing has a merge of its own and is not in the user's branch: what a surface offers a revert on (ADR-0054). */
|
|
774
|
+
revertible?: true;
|
|
775
|
+
/** A `conflict` whose repair starts by itself once this clears: progress, not a conflict to act on (ADR-0015). Said by the scheduler, not the record. */
|
|
776
|
+
repairWaits?: RepairWait;
|
|
777
|
+
/** A `conflict` a task was added to resolve, by id: its one worker (ADR-0015). */
|
|
778
|
+
resolver?: string;
|
|
552
779
|
};
|
|
553
780
|
interface IsolationLandedTask {
|
|
554
781
|
taskId: string;
|
|
@@ -693,6 +920,87 @@ type PreviousWork = {
|
|
|
693
920
|
};
|
|
694
921
|
/** A task as a removal names it. */
|
|
695
922
|
type IsolationTaskRef = Pick<IsolationTaskRecord, 'taskId' | 'order' | 'title'>;
|
|
923
|
+
/** A task as its landings name it, and what the commit that reverts one is worded from. */
|
|
924
|
+
type LandedTask = IsolationTaskRef & Pick<IsolationTaskRecord, 'commit'>;
|
|
925
|
+
/** A task a revert acts on, with the repos its landing changed. */
|
|
926
|
+
interface IsolationRevertTask extends IsolationTaskRef {
|
|
927
|
+
repos: string[];
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* What undoes a task's landing once something of the user's holds it: a command
|
|
931
|
+
* for them to run, which Ordewell shows and never runs (ADR-0054).
|
|
932
|
+
*/
|
|
933
|
+
interface RevertCommand {
|
|
934
|
+
task: IsolationTaskRef;
|
|
935
|
+
repo: string;
|
|
936
|
+
/** The task's merge commit, which `heldBy` holds. */
|
|
937
|
+
commit: string;
|
|
938
|
+
/** Ready to type at the workspace root. */
|
|
939
|
+
command: string;
|
|
940
|
+
/** What holds it and stops a revert: local branches by name, and 'HEAD' for a detached HEAD. */
|
|
941
|
+
heldBy: string[];
|
|
942
|
+
/** Whether the user's own branch is among them; if not, `heldBy` may be only a review. */
|
|
943
|
+
merged: boolean;
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* What git says of the landed work a revert would take, newest landing first.
|
|
947
|
+
* `inBranch`: the part something of the user's holds, which no revert touches;
|
|
948
|
+
* newest first too, the order to run the commands in. `no-own-merge`: a task's
|
|
949
|
+
* work came in through another's merge, a conflict resolver's, so no merge of
|
|
950
|
+
* its own can undo it. `git`: git could not read what the record names, or say
|
|
951
|
+
* what holds it.
|
|
952
|
+
*/
|
|
953
|
+
type LandedWork = {
|
|
954
|
+
ok: true;
|
|
955
|
+
tasks: IsolationRevertTask[];
|
|
956
|
+
inBranch: RevertCommand[];
|
|
957
|
+
} | {
|
|
958
|
+
ok: false;
|
|
959
|
+
reason: 'no-own-merge' | 'checked-out' | 'git';
|
|
960
|
+
error: string;
|
|
961
|
+
};
|
|
962
|
+
/** What {@link IWorktreeIsolation.revert} asks of its caller, in its turn. */
|
|
963
|
+
interface RevertWatch {
|
|
964
|
+
/** Why the revert may no longer go ahead, read once it has its turn and again with its commits made, which it then rolls back; null when it may. */
|
|
965
|
+
refusal: () => string | null;
|
|
966
|
+
/** Called once the tips are recorded and before the first commit, as a landing's `persist` is, and again as each commit is made. */
|
|
967
|
+
persist: () => void;
|
|
968
|
+
/** Called in the one synchronous step that lets the records go, so a save never sees them gone with the tasks not yet back. */
|
|
969
|
+
settled: (taskIds: readonly string[]) => void;
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* How a revert ended (ADR-0054). Anything but `reverted` left every integration
|
|
973
|
+
* branch where it was, except a `failed` that says so: tips git would not put
|
|
974
|
+
* back stay recorded on the run, which holds landings and Merge all off them.
|
|
975
|
+
*
|
|
976
|
+
* - `reverted`: `tasks`, newest landing first, in every repo each changed.
|
|
977
|
+
* - `in-branch`: something of the user's holds part of it: `commands` undo it there.
|
|
978
|
+
* - `refused`: {@link RevertWatch.refusal} said no, or git found work with no
|
|
979
|
+
* merge of its own, or the integration branch checked out where a revert
|
|
980
|
+
* cannot commit to it.
|
|
981
|
+
* - `conflict`: reverting `task` conflicted in `repo`, over `files`.
|
|
982
|
+
* - `failed`: git stopped it; `error` says on what.
|
|
983
|
+
*/
|
|
984
|
+
type IsolationRevertResult = {
|
|
985
|
+
outcome: 'reverted';
|
|
986
|
+
tasks: IsolationRevertTask[];
|
|
987
|
+
} | {
|
|
988
|
+
outcome: 'in-branch';
|
|
989
|
+
commands: RevertCommand[];
|
|
990
|
+
} | {
|
|
991
|
+
outcome: 'refused';
|
|
992
|
+
reason: string;
|
|
993
|
+
} | {
|
|
994
|
+
outcome: 'conflict';
|
|
995
|
+
task: IsolationTaskRef;
|
|
996
|
+
repo: string;
|
|
997
|
+
files: string[];
|
|
998
|
+
} | {
|
|
999
|
+
outcome: 'failed';
|
|
1000
|
+
error: string;
|
|
1001
|
+
task?: IsolationTaskRef;
|
|
1002
|
+
repo?: string;
|
|
1003
|
+
};
|
|
696
1004
|
/**
|
|
697
1005
|
* Work a removal found that had not landed — edits never committed, or
|
|
698
1006
|
* commits only the task's branch carried — committed and kept on `branch`,
|
|
@@ -744,6 +1052,8 @@ interface IWorktreeIsolation {
|
|
|
744
1052
|
* each, and the config enabled; otherwise the reason it is not.
|
|
745
1053
|
*/
|
|
746
1054
|
isActive(workspaceRoot: string): Promise<IsolationAvailability>;
|
|
1055
|
+
/** What the git on this machine holds back, as the line the user is told; null when it does everything, or there is no git to speak of. */
|
|
1056
|
+
gitShortfall(): Promise<string | null>;
|
|
747
1057
|
/**
|
|
748
1058
|
* Put the tracked changes of every dirty repo of the group on its git stash,
|
|
749
1059
|
* the user's way out of a `dirty` refusal. Untracked files stay: they never
|
|
@@ -753,9 +1063,11 @@ interface IWorktreeIsolation {
|
|
|
753
1063
|
/**
|
|
754
1064
|
* Mint a run: resolve each repo's base ref to a commit now, and share the
|
|
755
1065
|
* repos that cannot be isolated. Only meaningful after `isActive` said yes;
|
|
756
|
-
* throws when no repo of the group can be isolated after all.
|
|
1066
|
+
* throws when no repo of the group can be isolated after all. `stateRoot`
|
|
1067
|
+
* makes it a child's run (ADR-0055 D11), and it throws for a `workspaceRoot`
|
|
1068
|
+
* that is not a task's workspace under that root (D12).
|
|
757
1069
|
*/
|
|
758
|
-
startRun(workspaceRoot: string): Promise<IsolationRun>;
|
|
1070
|
+
startRun(workspaceRoot: string, stateRoot?: string): Promise<IsolationRun>;
|
|
759
1071
|
/**
|
|
760
1072
|
* Create the task workspace — one worktree per isolated repo from its
|
|
761
1073
|
* integration tip, the shared paths linked in — and return the cwd to spawn
|
|
@@ -784,6 +1096,13 @@ interface IWorktreeIsolation {
|
|
|
784
1096
|
* else: a task that fails stays `repairing` until released.
|
|
785
1097
|
*/
|
|
786
1098
|
verifyRepair(task: Task, run: IsolationRun): Promise<RepairEvidence>;
|
|
1099
|
+
/**
|
|
1100
|
+
* The paths a repair brings onto the integration tip, by their place in the
|
|
1101
|
+
* workspace: `repairBase` to the branch where the landing changed a repo, and
|
|
1102
|
+
* the task's tip to it where it did not, since a repair can still edit that
|
|
1103
|
+
* repo. Read after {@link verifyRepair} commits, before `integrate` moves the tip.
|
|
1104
|
+
*/
|
|
1105
|
+
repairPaths?(task: Task, run: IsolationRun): Promise<string[]>;
|
|
787
1106
|
/**
|
|
788
1107
|
* Land the task atomically across the repos it changed: commit each
|
|
789
1108
|
* worktree, then `git merge --no-ff` the task branch into each changed
|
|
@@ -806,6 +1125,22 @@ interface IWorktreeIsolation {
|
|
|
806
1125
|
* the runner made is never rewritten.
|
|
807
1126
|
*/
|
|
808
1127
|
integrate(task: Task, run: IsolationRun, persist?: () => void, commit?: HandoffCommit): Promise<IsolationOutcome>;
|
|
1128
|
+
/**
|
|
1129
|
+
* What git says of the tasks' landed work now. Reads only and takes no turn:
|
|
1130
|
+
* it answers a confirmation, and {@link revert} reads it all again in its own.
|
|
1131
|
+
*/
|
|
1132
|
+
readLanded(run: IsolationRun, taskIds: readonly string[]): Promise<LandedWork>;
|
|
1133
|
+
/**
|
|
1134
|
+
* Revert the tasks' landings on the integration branches (ADR-0054): one
|
|
1135
|
+
* revert commit per landing, newest first, in every repo each changed or in
|
|
1136
|
+
* none. Takes its turn on the landing queue, so it never reads
|
|
1137
|
+
* a branch mid-landing, judges what it is asked again there, and writes only
|
|
1138
|
+
* to Ordewell's own branches. Each reverted task's record goes: its landing
|
|
1139
|
+
* no longer counts for anything. A record of a later attempt that did not
|
|
1140
|
+
* land stays for the worktree it holds, kept like a stopped one's. What
|
|
1141
|
+
* stops it puts every tip back.
|
|
1142
|
+
*/
|
|
1143
|
+
revert(run: IsolationRun, taskIds: readonly string[], watch: RevertWatch): Promise<IsolationRevertResult>;
|
|
809
1144
|
/**
|
|
810
1145
|
* `keep: false` removes the task's worktree, branch and record (retry, task
|
|
811
1146
|
* removal), keeping whatever had not landed on a branch first; a record
|
|
@@ -838,11 +1173,20 @@ interface IWorktreeIsolation {
|
|
|
838
1173
|
reviewDiff(run: IsolationRun): Promise<string>;
|
|
839
1174
|
taskDiff?(run: IsolationRun, taskId: string, options: TaskDiffRead): Promise<TaskDiffResult>;
|
|
840
1175
|
/**
|
|
841
|
-
*
|
|
842
|
-
*
|
|
843
|
-
*
|
|
844
|
-
*
|
|
845
|
-
*
|
|
1176
|
+
* The blob `file` holds on `branch`, relative to `root`, the workspace
|
|
1177
|
+
* (ADR-0057 R9): null where it holds none, undefined where nothing can be read.
|
|
1178
|
+
* Refs are shared across worktrees, so a child reads an ancestor's branch too.
|
|
1179
|
+
* A branch gone with its merged run reads as what `root` has checked out, which
|
|
1180
|
+
* is where it merged.
|
|
1181
|
+
*/
|
|
1182
|
+
blobOn?(root: string, branch: string, file: string): Promise<string | null | undefined>;
|
|
1183
|
+
/**
|
|
1184
|
+
* Read each landed task's mark again from git: on where the user's branch
|
|
1185
|
+
* contains its work in every repo it changed (`git merge-base --is-ancestor`),
|
|
1186
|
+
* off where it no longer does. Returns the ids whose mark changed. A review
|
|
1187
|
+
* checkout of the integration branch, detached or not, contains nothing
|
|
1188
|
+
* merged (ADR-0054). A repo whose integration branch is gone counts as
|
|
1189
|
+
* containing it: no Merge all could bring that work in.
|
|
846
1190
|
*/
|
|
847
1191
|
findInHead(run: IsolationRun): Promise<string[]>;
|
|
848
1192
|
/**
|
|
@@ -884,6 +1228,7 @@ interface IWorktreeIsolation {
|
|
|
884
1228
|
* Never a branch of `run` itself, one a worktree has checked out, or any
|
|
885
1229
|
* branch of a run that still has a worktree — that run may be live in
|
|
886
1230
|
* another plan. Tries every repo, then throws naming those where git failed.
|
|
1231
|
+
* A child's run sweeps nothing (ADR-0055 D11).
|
|
887
1232
|
*/
|
|
888
1233
|
sweep(run: IsolationRun): Promise<void>;
|
|
889
1234
|
}
|
|
@@ -985,6 +1330,12 @@ declare function partedPromptUsage(parts: {
|
|
|
985
1330
|
cacheRead?: number;
|
|
986
1331
|
cacheWrite?: number;
|
|
987
1332
|
}): Pick<UsageRecord, 'inputTokens' | 'cachedInputTokens'>;
|
|
1333
|
+
/**
|
|
1334
|
+
* What a budget counts (ADR-0056 M5), of a record or of totals alike: the same
|
|
1335
|
+
* tokens a total holds, input and output. `cachedInputTokens` is a share of the
|
|
1336
|
+
* input, so cache reads count, once.
|
|
1337
|
+
*/
|
|
1338
|
+
declare function spentTokens({ inputTokens, outputTokens }: Pick<UsageTotals, 'inputTokens' | 'outputTokens'>): number;
|
|
988
1339
|
declare function addUsage(totals: UsageTotals, record: UsageRecord): UsageTotals;
|
|
989
1340
|
/**
|
|
990
1341
|
* What the planner has consumed over a session (#49). `totals` includes every
|
|
@@ -1097,6 +1448,7 @@ interface PlanUsage {
|
|
|
1097
1448
|
}
|
|
1098
1449
|
declare function addUsageTotals(totals: UsageTotals, addition: UsageTotals): UsageTotals;
|
|
1099
1450
|
interface UsageTask {
|
|
1451
|
+
type?: string;
|
|
1100
1452
|
attemptUsage?: readonly AttemptUsage[];
|
|
1101
1453
|
subtasks?: readonly UsageTask[];
|
|
1102
1454
|
}
|
|
@@ -1112,7 +1464,7 @@ interface TaskUsageSummary {
|
|
|
1112
1464
|
attempts: number;
|
|
1113
1465
|
contextFill?: ContextFill;
|
|
1114
1466
|
}
|
|
1115
|
-
declare function taskUsageSummary(task: Pick<UsageTask, 'attemptUsage'>): TaskUsageSummary;
|
|
1467
|
+
declare function taskUsageSummary(task: Pick<UsageTask, 'attemptUsage' | 'type'>): TaskUsageSummary;
|
|
1116
1468
|
/** `950`, `1.5k`, `61k`, `261k`, `1.2M`. */
|
|
1117
1469
|
declare function formatTokenCount(n: number): string;
|
|
1118
1470
|
/** Two decimals from 1 up and up to four below it: a call can cost a fraction of a cent, a session several dollars. */
|
|
@@ -1153,7 +1505,7 @@ type SupervisorLevel = 'off' | 'watch' | 'act';
|
|
|
1153
1505
|
declare function isSupervisorLevel(value: unknown): value is SupervisorLevel;
|
|
1154
1506
|
/**
|
|
1155
1507
|
* Who asked the command seam for an action (ADR-0029): the user, a planner
|
|
1156
|
-
* turn the user started,
|
|
1508
|
+
* turn the user started, the supervisor at its level, autorun, or a subplanner.
|
|
1157
1509
|
*/
|
|
1158
1510
|
type ExecutionActor = {
|
|
1159
1511
|
kind: 'user';
|
|
@@ -1163,15 +1515,23 @@ type ExecutionActor = {
|
|
|
1163
1515
|
kind: 'supervisor';
|
|
1164
1516
|
level: SupervisorLevel;
|
|
1165
1517
|
}
|
|
1166
|
-
/** The user's standing instruction to start each plan the planner submits (ADR-0030). */
|
|
1518
|
+
/** The user's standing instruction to start each plan the planner submits (ADR-0030); `leavesFailed` is what failed in that reply, which it does not run again. */
|
|
1167
1519
|
| {
|
|
1168
1520
|
kind: 'autorun';
|
|
1521
|
+
leavesFailed?: ReadonlySet<string>;
|
|
1522
|
+
}
|
|
1523
|
+
/** Every turn of a child plan's planner (ADR-0056 M6): no person is there, so its grants alone answer. `depth` is its level, the root being 0. */
|
|
1524
|
+
| {
|
|
1525
|
+
kind: 'subplanner';
|
|
1526
|
+
depth: number;
|
|
1169
1527
|
};
|
|
1170
|
-
|
|
1528
|
+
/** Whose authority an actor's work runs under: a child has no user, so a subplanner's is a supervisor's (ADR-0056 M6). */
|
|
1529
|
+
declare function actorAuthority(actor: ExecutionActor['kind']): TurnAuthority;
|
|
1530
|
+
type ExecutionCommandName = 'run_plan' | 'run_task' | 'stop_task' | 'stop_run' | 'retry_task' | 'message_task' | 'answer_approval' | 'merge_all' | 'skip_task' | 'force_start' | 'mark_complete' | 'mark_not_done' | 'revert_task' | 'interrupt_task' | 'force_send_queued' | 'remove_queued' | 'cancel_resume' | 'answer_checkpoint' | 'approve_review' | 'run_script';
|
|
1171
1531
|
/**
|
|
1172
1532
|
* How the user consented to the script a `run_script` call ran (ADR-0035):
|
|
1173
1533
|
* on the approval card, by an effect allowlist rule (by name), by autorun in
|
|
1174
|
-
* Full,
|
|
1534
|
+
* Full, by choosing Act for the supervisor, or by a subplanner's mandate.
|
|
1175
1535
|
*/
|
|
1176
1536
|
type ScriptConsent = {
|
|
1177
1537
|
by: 'card';
|
|
@@ -1182,6 +1542,8 @@ type ScriptConsent = {
|
|
|
1182
1542
|
by: 'autorun';
|
|
1183
1543
|
} | {
|
|
1184
1544
|
by: 'act';
|
|
1545
|
+
} | {
|
|
1546
|
+
by: 'mandate';
|
|
1185
1547
|
};
|
|
1186
1548
|
/**
|
|
1187
1549
|
* Where a `run_script` call's task stood as the call answered, or as it ended
|
|
@@ -1320,6 +1682,349 @@ declare class SkillsService {
|
|
|
1320
1682
|
*/
|
|
1321
1683
|
declare function createSkillsService(workspaceRoot?: string, workspaceRepos?: readonly string[]): SkillsService;
|
|
1322
1684
|
|
|
1685
|
+
/** A script task's time limit when it sets none. */
|
|
1686
|
+
declare const DEFAULT_SCRIPT_TIMEOUT_MS: number;
|
|
1687
|
+
/** What a script task runs, its time limit filled in. */
|
|
1688
|
+
type ScriptBody =
|
|
1689
|
+
/** Argument vectors run in order with no shell, stopping at the first that fails. */
|
|
1690
|
+
{
|
|
1691
|
+
commands: string[][];
|
|
1692
|
+
timeoutMs: number;
|
|
1693
|
+
}
|
|
1694
|
+
/** One script, run by the research shell's interpreter. */
|
|
1695
|
+
| {
|
|
1696
|
+
script: string;
|
|
1697
|
+
timeoutMs: number;
|
|
1698
|
+
};
|
|
1699
|
+
type BodyFields = Pick<Task, 'type' | 'commands' | 'script' | 'timeoutMs'>;
|
|
1700
|
+
/** The body a script task runs; null for any other task, or one whose body the plan's rules refuse. */
|
|
1701
|
+
declare function scriptBodyOf(task: BodyFields): ScriptBody | null;
|
|
1702
|
+
/**
|
|
1703
|
+
* An argument vector as a reader would type it in a shell: a word is quoted
|
|
1704
|
+
* only where it needs to be, and one holding a character a reader cannot see
|
|
1705
|
+
* is written with escapes (`$'…'`), so a command is always one line and reads
|
|
1706
|
+
* as what runs. For reading only; nothing runs it.
|
|
1707
|
+
*/
|
|
1708
|
+
declare function commandLine(argv: readonly string[]): string;
|
|
1709
|
+
/**
|
|
1710
|
+
* A script task's body as the approval card shows it (ADR-0035), so the
|
|
1711
|
+
* consent is to what will run: each command on a line of its own, or the
|
|
1712
|
+
* script as written, then the time limit. A character a reader cannot see in
|
|
1713
|
+
* a script, but for its line breaks and tabs, is shown as its code.
|
|
1714
|
+
*/
|
|
1715
|
+
declare function scriptBodyText(body: ScriptBody): string;
|
|
1716
|
+
/**
|
|
1717
|
+
* A script task as a row shows it: the body {@link scriptBodyText} gives the
|
|
1718
|
+
* approval card, so what the user read when consenting is what the plan lists.
|
|
1719
|
+
* A task whose body the plan's rules refuse says so rather than showing nothing.
|
|
1720
|
+
*/
|
|
1721
|
+
declare function scriptTaskText(task: BodyFields): string;
|
|
1722
|
+
/** A time limit in the largest units it is a whole number of: "10 minutes", "90 seconds". */
|
|
1723
|
+
declare function timeLimitText(ms: number): string;
|
|
1724
|
+
|
|
1725
|
+
/**
|
|
1726
|
+
* The planner's standing approvals (ADR-0026): what runs without asking
|
|
1727
|
+
* anyone, under every approval mode.
|
|
1728
|
+
*
|
|
1729
|
+
* One entry is one of:
|
|
1730
|
+
*
|
|
1731
|
+
* - a **command rule**, `gh issue list` or `gcloud * * list`: the binary,
|
|
1732
|
+
* then words matched against the command's leading arguments, the ones
|
|
1733
|
+
* before its first flag. A command whose leading words match the rule's
|
|
1734
|
+
* runs, whatever arguments follow — but the rule must spell out at least
|
|
1735
|
+
* the words the command's approval scope holds (ADR-0008, T1), so
|
|
1736
|
+
* `az group` never covers `az group delete`, and a one-word read takes a
|
|
1737
|
+
* `*` for its argument (`kubectl get *`). `*` stands for one word, and
|
|
1738
|
+
* inside a word for any run of characters (`describe-*`). An entry equal
|
|
1739
|
+
* to a scope also matches that scope, as pre-approved scopes always did.
|
|
1740
|
+
* - an **MCP tool rule**, `mcp:find-*`: a glob over the tool's own name,
|
|
1741
|
+
* without the server, case-insensitive.
|
|
1742
|
+
* - a **scope pattern**, anything starting with `/`, `~`, `http://`,
|
|
1743
|
+
* `https://`, `web_search:`, `mcp__`, `mcp-server:` or a drive letter: matched against an approval's
|
|
1744
|
+
* scope as ADR-0008 always matched pre-approved entries, `*` matching any
|
|
1745
|
+
* run of characters.
|
|
1746
|
+
*
|
|
1747
|
+
* A leading `!` excludes instead, and an exclusion wins over every rule. A
|
|
1748
|
+
* command exclusion's words are looked for anywhere among the arguments, in
|
|
1749
|
+
* order, flags included and case ignored, so `!kubectl *secret*` and
|
|
1750
|
+
* `!* --endpoint*` hold wherever the word appears; a lone short flag (`-s`)
|
|
1751
|
+
* also holds inside a bundle (`-As`, `-shost`). `*` as its binary covers
|
|
1752
|
+
* every command.
|
|
1753
|
+
*/
|
|
1754
|
+
/** The words a command rule is matched against: a lexed segment's binary and arguments. */
|
|
1755
|
+
interface CommandWords {
|
|
1756
|
+
binary: string;
|
|
1757
|
+
args: readonly string[];
|
|
1758
|
+
/** How many leading arguments the command's approval scope holds; a rule must cover at least that many. */
|
|
1759
|
+
scopeWords?: number;
|
|
1760
|
+
}
|
|
1761
|
+
interface RuleWord {
|
|
1762
|
+
matches: (word: string) => boolean;
|
|
1763
|
+
wildcard: boolean;
|
|
1764
|
+
}
|
|
1765
|
+
interface CommandRule {
|
|
1766
|
+
text: string;
|
|
1767
|
+
binary: string;
|
|
1768
|
+
words: RuleWord[];
|
|
1769
|
+
}
|
|
1770
|
+
interface PlannerAllowlist {
|
|
1771
|
+
commands: CommandRule[];
|
|
1772
|
+
commandExclusions: CommandRule[];
|
|
1773
|
+
tools: RegExp[];
|
|
1774
|
+
toolExclusions: RegExp[];
|
|
1775
|
+
scopes: RegExp[];
|
|
1776
|
+
scopeExclusions: RegExp[];
|
|
1777
|
+
}
|
|
1778
|
+
declare function parseAllowlist(entries: readonly string[]): PlannerAllowlist;
|
|
1779
|
+
/** The rule that lets this command run unasked, or undefined when none does or an exclusion holds. */
|
|
1780
|
+
declare function commandAllowedBy(list: PlannerAllowlist, command: CommandWords): string | undefined;
|
|
1781
|
+
/** Whether an MCP tool, by its own name without the server, runs unasked. */
|
|
1782
|
+
declare function toolAllowed(list: PlannerAllowlist, tool: string): boolean;
|
|
1783
|
+
/** Whether an approval scope — a directory, an origin, a tool's full name — is pre-approved. */
|
|
1784
|
+
declare function scopeAllowed(list: PlannerAllowlist, scope: string): boolean;
|
|
1785
|
+
/**
|
|
1786
|
+
* Read-only command families that are safe to run unasked: they read, never
|
|
1787
|
+
* write a file or change a resource, and need no argument that runs code.
|
|
1788
|
+
* Absent on purpose: commands that run the repository's own code (test
|
|
1789
|
+
* runners, builds, package scripts, a package manager the repository pins or
|
|
1790
|
+
* extends — on an untrusted repository someone else wrote that code), commands
|
|
1791
|
+
* a repository's own config can point at another endpoint with the user's
|
|
1792
|
+
* credentials (`.npmrc`, `.sentryclirc`, a Terraform or Pulumi backend), and
|
|
1793
|
+
* commands whose usual output is a secret.
|
|
1794
|
+
*/
|
|
1795
|
+
declare const DEFAULT_PLANNER_ALLOWLIST: readonly string[];
|
|
1796
|
+
|
|
1797
|
+
/** A delegated task's budget: tokens, and optionally wall-clock time (ADR-0056 M5). */
|
|
1798
|
+
interface DelegatedBudget {
|
|
1799
|
+
tokens: number;
|
|
1800
|
+
wallClockMs?: number;
|
|
1801
|
+
}
|
|
1802
|
+
/** Where a child plan's tasks stand now: the counts a delegated task's row shows while its child runs (ADR-0055 D20). */
|
|
1803
|
+
interface ChildTaskCounts {
|
|
1804
|
+
completed: number;
|
|
1805
|
+
running: number;
|
|
1806
|
+
/** Waiting on a person, a checkpoint among them. */
|
|
1807
|
+
waiting: number;
|
|
1808
|
+
pending: number;
|
|
1809
|
+
failed: number;
|
|
1810
|
+
skipped: number;
|
|
1811
|
+
}
|
|
1812
|
+
/**
|
|
1813
|
+
* What a delegated task's row says beyond any task's (ADR-0055 D16, D20): all of
|
|
1814
|
+
* it derived where it is read, from the child's plan, the tree's ledger and the
|
|
1815
|
+
* Stop, never kept. Every part is absent when there is nothing to say.
|
|
1816
|
+
*/
|
|
1817
|
+
interface DelegatedRow {
|
|
1818
|
+
/** The child's tasks by where they stand; absent with no child session open. */
|
|
1819
|
+
tasks?: ChildTaskCounts;
|
|
1820
|
+
/** The task's token budget, and what the tree has not yet spent of it, across every child it has had (ADR-0056 M10). */
|
|
1821
|
+
tokens?: {
|
|
1822
|
+
budget: number;
|
|
1823
|
+
left: number;
|
|
1824
|
+
};
|
|
1825
|
+
/** A Stop is still winding the subtree down, though the task already reads as not started (D16). */
|
|
1826
|
+
stopping?: true;
|
|
1827
|
+
}
|
|
1828
|
+
/** What a task declares it works on (ADR-0057 R6). Advisory: nothing gates on it. */
|
|
1829
|
+
interface TaskScope {
|
|
1830
|
+
paths?: string[];
|
|
1831
|
+
provides?: string[];
|
|
1832
|
+
consumes?: string[];
|
|
1833
|
+
}
|
|
1834
|
+
/** Something a check is made of. A `command` is the check itself at any length, where prose says little until it has some. */
|
|
1835
|
+
interface CheckWord {
|
|
1836
|
+
text: string;
|
|
1837
|
+
command: boolean;
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
/**
|
|
1841
|
+
* The effect allowlist (ADR-0035): the user's standing approval for named
|
|
1842
|
+
* effects, beside the planner allowlist, which names reads. It pre-approves a
|
|
1843
|
+
* script task whose `commands` are all covered; it never covers a `script`
|
|
1844
|
+
* body, whose shell text no rule can be matched against.
|
|
1845
|
+
*
|
|
1846
|
+
* A rule is matched against the whole command, every word in order and flags
|
|
1847
|
+
* included, because an effect's flags change what it does: `git push origin
|
|
1848
|
+
* feature/*` covers `git push origin feature/login`, never the same push with
|
|
1849
|
+
* `--force`. `*` stands for one word, or inside a word for any run of
|
|
1850
|
+
* characters, as in the planner allowlist, except that it never stands for
|
|
1851
|
+
* what changes the effect: a flag (`--force`, and `/force` on Windows), a
|
|
1852
|
+
* refspec's force or delete (`+main`, `:main`), or a `:` outside a URL
|
|
1853
|
+
* (`feature/x:main`, which pushes to `main`). The rule writes any of those
|
|
1854
|
+
* itself. A rule spells out its operation before any `*`, so
|
|
1855
|
+
* `az webapp config * set` is no rule at all.
|
|
1856
|
+
*
|
|
1857
|
+
* Exclusions are the planner allowlist's `!` entries, with any `!` entry
|
|
1858
|
+
* written here; an exclusion wins. A command exclusion is matched as the
|
|
1859
|
+
* planner allowlist matches it; a path or URL exclusion holds for an argument
|
|
1860
|
+
* that names an absolute path or URL it covers, whole or after a `=`, `@`,
|
|
1861
|
+
* `:` or `,` or a short flag (`--url=…`, `-d @…`). A relative path is not
|
|
1862
|
+
* resolved, since the body does not say where it runs. A program named by its
|
|
1863
|
+
* path is a file the repository ships (ADR-0026), so it is never covered.
|
|
1864
|
+
* There are no built-in rules: a default would pre-approve an effect the user
|
|
1865
|
+
* never chose.
|
|
1866
|
+
*/
|
|
1867
|
+
interface EffectRule {
|
|
1868
|
+
text: string;
|
|
1869
|
+
binary: string;
|
|
1870
|
+
words: RuleWord[];
|
|
1871
|
+
}
|
|
1872
|
+
interface EffectRules {
|
|
1873
|
+
rules: EffectRule[];
|
|
1874
|
+
exclusions: PlannerAllowlist;
|
|
1875
|
+
platform: NodeJS.Platform;
|
|
1876
|
+
/** The entries that are no rule, each with the warning that says why it is ignored. */
|
|
1877
|
+
ignored: {
|
|
1878
|
+
rule: string;
|
|
1879
|
+
warning: string;
|
|
1880
|
+
}[];
|
|
1881
|
+
}
|
|
1882
|
+
/**
|
|
1883
|
+
* `entries` are the effect allowlist's; `plannerEntries` the planner allowlist
|
|
1884
|
+
* in force, whose `!` entries hold here too; `platform` the one the commands
|
|
1885
|
+
* run on, which decides how a flag is spelled and how a path resolves.
|
|
1886
|
+
*/
|
|
1887
|
+
declare function parseEffectAllowlist(entries: readonly string[], plannerEntries?: readonly string[], platform?: NodeJS.Platform): EffectRules;
|
|
1888
|
+
/**
|
|
1889
|
+
* The rules, by name, that cover every command of a `commands` body, or null
|
|
1890
|
+
* when one command is not covered, an exclusion holds for one, or the body is
|
|
1891
|
+
* a `script`.
|
|
1892
|
+
*/
|
|
1893
|
+
declare function effectRuleFor(list: EffectRules, body: ScriptBody): string | null;
|
|
1894
|
+
|
|
1895
|
+
/**
|
|
1896
|
+
* The mandate (ADR-0056): what a node may do without a person, and within what
|
|
1897
|
+
* limits. The root's is derived on each read from today's settings and never
|
|
1898
|
+
* saved; a child's is one pure function of its parent's and its request, which
|
|
1899
|
+
* can only narrow what the parent may hand on. Authority only: capability stays
|
|
1900
|
+
* at the boundary a session runs in, and a prompt enforces nothing.
|
|
1901
|
+
*/
|
|
1902
|
+
declare const GRANTS: readonly ["observe", "steer", "control", "replan", "approve", "delegate", "effect", "research", "merge"];
|
|
1903
|
+
/** Each is a set of things a node may do unasked (M2). */
|
|
1904
|
+
type Grant = (typeof GRANTS)[number];
|
|
1905
|
+
/** What a mandate could not finish without: a child holds these unasked, and `narrow` refuses one that would lack any (M2). */
|
|
1906
|
+
declare const FLOOR_GRANTS: readonly Grant[];
|
|
1907
|
+
/** The shape of a tree, by ADR-0055 D19: refused past the hard cap, never dropped. */
|
|
1908
|
+
declare const SHAPE_LIMITS: {
|
|
1909
|
+
readonly depth: {
|
|
1910
|
+
readonly default: 2;
|
|
1911
|
+
readonly hard: 4;
|
|
1912
|
+
};
|
|
1913
|
+
readonly delegatedTasks: {
|
|
1914
|
+
readonly default: 8;
|
|
1915
|
+
readonly hard: 30;
|
|
1916
|
+
};
|
|
1917
|
+
readonly tasksPerPlan: {
|
|
1918
|
+
readonly default: 30;
|
|
1919
|
+
readonly hard: 100;
|
|
1920
|
+
};
|
|
1921
|
+
};
|
|
1922
|
+
interface MandateLimits {
|
|
1923
|
+
/** The node's token budget; the root's is the tree's, from the delegation setting (M3, M5). */
|
|
1924
|
+
tokens: number;
|
|
1925
|
+
/** Null: no limit, which only the root has. */
|
|
1926
|
+
wallClockMs: number | null;
|
|
1927
|
+
/** How many levels may still open below this node. */
|
|
1928
|
+
depth: number;
|
|
1929
|
+
delegatedTasks: number;
|
|
1930
|
+
tasksPerPlan: number;
|
|
1931
|
+
runners: readonly RunnerId[];
|
|
1932
|
+
/** The models a runner is held to; a runner not named may use any it offers, as the user's allowlist reads. */
|
|
1933
|
+
models: Readonly<Record<RunnerId, readonly string[]>>;
|
|
1934
|
+
}
|
|
1935
|
+
interface MandateExclusions {
|
|
1936
|
+
protectedPaths: readonly string[];
|
|
1937
|
+
}
|
|
1938
|
+
interface Mandate {
|
|
1939
|
+
/** What this node may do. */
|
|
1940
|
+
grants: ReadonlySet<Grant>;
|
|
1941
|
+
/** What it may hand a child. */
|
|
1942
|
+
grantable: ReadonlySet<Grant>;
|
|
1943
|
+
/** Read in place of the global level. */
|
|
1944
|
+
autonomy: 'full' | 'guarded';
|
|
1945
|
+
limits: MandateLimits;
|
|
1946
|
+
/** These only accumulate. */
|
|
1947
|
+
exclusions: MandateExclusions;
|
|
1948
|
+
/** One per level, each with its own `!` rules: a command must match at every level (M4). */
|
|
1949
|
+
effectRules: readonly EffectRules[];
|
|
1950
|
+
/** The level of `effectRules` this node's own request added: all of it a node keeps, the levels above being read as they stand (M1). */
|
|
1951
|
+
ownEffectRules: readonly EffectRules[];
|
|
1952
|
+
}
|
|
1953
|
+
/** What the root's mandate is read from, each where it lives today (M1). */
|
|
1954
|
+
interface RootSettings {
|
|
1955
|
+
/** The run's own copy: where a guard or a failure lowers it, and the user's change lands. */
|
|
1956
|
+
level: SupervisorLevel;
|
|
1957
|
+
autorun: boolean;
|
|
1958
|
+
autonomous: boolean;
|
|
1959
|
+
/** The tree's budget; 0 is delegation off (ADR-0055 D21). */
|
|
1960
|
+
delegationTokens: number;
|
|
1961
|
+
/** The effect allowlist, absent where nothing was read. */
|
|
1962
|
+
effects?: EffectRules;
|
|
1963
|
+
runners: readonly RunnerId[];
|
|
1964
|
+
models: Readonly<Record<RunnerId, readonly string[]>>;
|
|
1965
|
+
}
|
|
1966
|
+
/** What a delegated task asks of the mandate it is given. `grants` names what it asks for past the floor; absent asks for nothing. */
|
|
1967
|
+
interface MandateRequest {
|
|
1968
|
+
/** The level of the node narrowing, the root being 0: the one a refusal names. */
|
|
1969
|
+
level: number;
|
|
1970
|
+
grants?: readonly Grant[];
|
|
1971
|
+
autonomy?: Mandate['autonomy'];
|
|
1972
|
+
/** A delegated task must carry one (M5). */
|
|
1973
|
+
tokens?: number;
|
|
1974
|
+
wallClockMs?: number;
|
|
1975
|
+
depth?: number;
|
|
1976
|
+
delegatedTasks?: number;
|
|
1977
|
+
tasksPerPlan?: number;
|
|
1978
|
+
runners?: readonly RunnerId[];
|
|
1979
|
+
models?: Readonly<Record<RunnerId, readonly string[]>>;
|
|
1980
|
+
protectedPaths?: readonly string[];
|
|
1981
|
+
effectRules?: EffectRules;
|
|
1982
|
+
}
|
|
1983
|
+
interface MandateRefusal {
|
|
1984
|
+
level: number;
|
|
1985
|
+
field: string;
|
|
1986
|
+
asked: string;
|
|
1987
|
+
there: string;
|
|
1988
|
+
}
|
|
1989
|
+
type Narrowed = {
|
|
1990
|
+
ok: true;
|
|
1991
|
+
mandate: Mandate;
|
|
1992
|
+
} | {
|
|
1993
|
+
ok: false;
|
|
1994
|
+
refusal: MandateRefusal;
|
|
1995
|
+
};
|
|
1996
|
+
declare function mandateRefusalText({ level, field, asked, there }: MandateRefusal): string;
|
|
1997
|
+
/**
|
|
1998
|
+
* The root's mandate, as it stands now (M1): built afresh on each read, so an
|
|
1999
|
+
* Act that a guard lowered reads Watch at the next check, and nothing saved
|
|
2000
|
+
* could disagree with the settings.
|
|
2001
|
+
*/
|
|
2002
|
+
declare function rootMandate(settings: RootSettings): Mandate;
|
|
2003
|
+
/**
|
|
2004
|
+
* What holds at a node now (M1): its saved mandate within every ancestor's
|
|
2005
|
+
* `grantable` as it stands, under every ancestor's effect rules as they stand,
|
|
2006
|
+
* so a change at the root reaches the subtree at the next check. This reading
|
|
2007
|
+
* intersects and refuses nothing: the floor binds {@link narrow}, which writes
|
|
2008
|
+
* a new child, not this.
|
|
2009
|
+
*/
|
|
2010
|
+
declare function heldMandate(saved: Mandate, ancestors: readonly Mandate[]): Mandate;
|
|
2011
|
+
/**
|
|
2012
|
+
* A child's mandate (M4), or the refusal that names the level that refused,
|
|
2013
|
+
* the field, what was asked and what is there. Pure, and written to be proved:
|
|
2014
|
+
* no result is wider than its parent. `parent.limits.tokens` and `wallClockMs`
|
|
2015
|
+
* are what the parent has left, which is the caller's to read.
|
|
2016
|
+
*/
|
|
2017
|
+
declare function narrow(parent: Mandate, request: MandateRequest): Narrowed;
|
|
2018
|
+
/** What a node reads of its own authority, at each check (M1). */
|
|
2019
|
+
interface NodeAuthority {
|
|
2020
|
+
/** How far below the root, which is 0 and where a person remains. */
|
|
2021
|
+
readonly depth: number;
|
|
2022
|
+
/** The mandate that holds now. `level` is what the root's is read at; a child's does not depend on it. */
|
|
2023
|
+
mandate(level: SupervisorLevel): Mandate;
|
|
2024
|
+
}
|
|
2025
|
+
/** The root: its settings read as each check asks, the level included, which each caller names. */
|
|
2026
|
+
declare function rootAuthority(settings: () => Omit<RootSettings, 'level'>): NodeAuthority;
|
|
2027
|
+
|
|
1323
2028
|
/** How many times a loop's check runs when the loop sets no `maxRounds`. */
|
|
1324
2029
|
declare const DEFAULT_LOOP_ROUNDS = 3;
|
|
1325
2030
|
/** The most rounds a loop may set: past it, the fix is not converging, and a person should look. */
|
|
@@ -1423,6 +2128,8 @@ interface SupervisionMemorySnapshot {
|
|
|
1423
2128
|
edits: EditMemory;
|
|
1424
2129
|
/** The keys of the guard trips the user was already told of. */
|
|
1425
2130
|
told: string[];
|
|
2131
|
+
/** The tasks the user stopped and has not started again. Absent on saves before it. */
|
|
2132
|
+
stopped?: string[];
|
|
1426
2133
|
}
|
|
1427
2134
|
/** What the supervisor's own edits did this run: the tasks it removed, and each field it changed. */
|
|
1428
2135
|
interface EditMemory {
|
|
@@ -1438,16 +2145,20 @@ interface EditMemory {
|
|
|
1438
2145
|
}
|
|
1439
2146
|
|
|
1440
2147
|
/**
|
|
1441
|
-
* When the supervisor wakes during a run
|
|
1442
|
-
*
|
|
1443
|
-
* the host stamps each event and polls
|
|
2148
|
+
* When the supervisor wakes during a run (#27, ADR-0057 R4). The decision is
|
|
2149
|
+
* {@link wakeDue}, a pure function of the events held and what the plan says:
|
|
2150
|
+
* no model, and no clock of its own, since the host stamps each event and polls
|
|
2151
|
+
* on its own tick. A pass opens nothing and rides along as context. An event a
|
|
2152
|
+
* person or a planner is waiting on wakes at once, which is ADR-0029's merge
|
|
2153
|
+
* window. Anything else is held until the plan says it is time, or until the
|
|
2154
|
+
* planner's prompt cache would go cold.
|
|
1444
2155
|
*
|
|
1445
2156
|
* `task_report` is a task addressed to the planner ending: one whose result a
|
|
1446
2157
|
* planner turn asked for and did not get before it answered (ADR-0037, R2).
|
|
1447
|
-
* It
|
|
1448
|
-
*
|
|
2158
|
+
* It wakes the planner whatever the supervisor's level, since the planner
|
|
2159
|
+
* asked for it.
|
|
1449
2160
|
*/
|
|
1450
|
-
type RunEventKind = 'task_passed' | 'task_failed' | 'waiting_input' | 'waiting_approval' | 'task_idle' | 'landing_conflict' | 'usage_limit' | 'auto_merge_stopped' | 'run_finished' | 'task_report';
|
|
2161
|
+
type RunEventKind = 'task_passed' | 'task_failed' | 'waiting_input' | 'waiting_approval' | 'approval_denied' | 'task_idle' | 'landing_conflict' | 'usage_limit' | 'auto_merge_stopped' | 'start_refused' | 'run_finished' | 'task_report';
|
|
1451
2162
|
type RunEvent = {
|
|
1452
2163
|
kind: RunEventKind;
|
|
1453
2164
|
taskId?: string;
|
|
@@ -1473,7 +2184,7 @@ interface TaskReportEvent {
|
|
|
1473
2184
|
}
|
|
1474
2185
|
/** What the policy holds before its next wake-up, for the plan (ADR-0029). */
|
|
1475
2186
|
interface WakePolicySnapshot {
|
|
1476
|
-
/**
|
|
2187
|
+
/** The events waiting for a wake-up, in arrival order. */
|
|
1477
2188
|
attention: RunEvent[];
|
|
1478
2189
|
/** The passes since the previous wake-up. */
|
|
1479
2190
|
sinceLast: RunEvent[];
|
|
@@ -1490,6 +2201,8 @@ interface SupervisorSnapshot {
|
|
|
1490
2201
|
policy: WakePolicySnapshot;
|
|
1491
2202
|
/** When each wake-up since the last pass was delivered, for the wake-up rate guard. */
|
|
1492
2203
|
wakeUps: number[];
|
|
2204
|
+
/** The user's Stop stands: a reload is not them starting the run again (ADR-0029). */
|
|
2205
|
+
stopped?: true;
|
|
1493
2206
|
}
|
|
1494
2207
|
|
|
1495
2208
|
interface UserStep {
|
|
@@ -1502,7 +2215,7 @@ interface UserStep {
|
|
|
1502
2215
|
* `script_exit` is a script task's exit status, its one evidence (ADR-0035).
|
|
1503
2216
|
*/
|
|
1504
2217
|
interface VerificationCheck {
|
|
1505
|
-
name: 'exit_code' | 'completion_marker' | 'task_complete' | 'manual' | 'script_exit';
|
|
2218
|
+
name: 'exit_code' | 'completion_marker' | 'task_complete' | 'manual' | 'script_exit' | 'protected_paths';
|
|
1506
2219
|
passed: boolean;
|
|
1507
2220
|
/** A check that did not apply. Skipped checks don't affect the verdict. */
|
|
1508
2221
|
skipped: boolean;
|
|
@@ -1520,7 +2233,8 @@ interface Verdict {
|
|
|
1520
2233
|
* `done` on exit 0, `failed` on a non-zero exit, a signal or its time limit,
|
|
1521
2234
|
* `blocked` when it could not start. A loop starts a round only on `failed`
|
|
1522
2235
|
* (ADR-0045 L2). Absent when nothing reported: a runner that exited without
|
|
1523
|
-
* the call, Mark complete, a stopped script,
|
|
2236
|
+
* the call, Mark complete, a stopped script, an attempt the host died in, a
|
|
2237
|
+
* verdict saved before it was kept.
|
|
1524
2238
|
*/
|
|
1525
2239
|
reported?: 'done' | 'failed' | 'blocked';
|
|
1526
2240
|
}
|
|
@@ -1532,8 +2246,11 @@ interface TaskOutputSummary {
|
|
|
1532
2246
|
logTail: string;
|
|
1533
2247
|
capturedAt: string;
|
|
1534
2248
|
}
|
|
1535
|
-
/**
|
|
1536
|
-
|
|
2249
|
+
/**
|
|
2250
|
+
* `script` is an ops task whose body Ordewell runs with no model (ADR-0035);
|
|
2251
|
+
* `delegated` holds a goal, and its attempt is a child plan (ADR-0055).
|
|
2252
|
+
*/
|
|
2253
|
+
type TaskType = 'ai' | 'user' | 'script' | 'delegated';
|
|
1537
2254
|
/**
|
|
1538
2255
|
* `skipped` is terminal and verdict-less: the task will not be waited for, and
|
|
1539
2256
|
* nothing it did lands. Its dependents go ahead without it once the work it
|
|
@@ -1550,7 +2267,7 @@ type TaskMode = string;
|
|
|
1550
2267
|
* usage limit. Saved, so no surface has to guess it from whether an attempt
|
|
1551
2268
|
* is live.
|
|
1552
2269
|
*/
|
|
1553
|
-
type AwaitingReason = 'input' | 'checkpoint' | 'conflict' | 'files-changed' | 'usage-limit';
|
|
2270
|
+
type AwaitingReason = 'input' | 'checkpoint' | 'question-lost' | 'conflict' | 'files-changed' | 'usage-limit';
|
|
1554
2271
|
declare function isAwaitingReason(value: unknown): value is AwaitingReason;
|
|
1555
2272
|
interface TaskModelAssignment {
|
|
1556
2273
|
modelId: string;
|
|
@@ -1615,6 +2332,19 @@ interface Task {
|
|
|
1615
2332
|
runnerSessionOwner?: RunnerId;
|
|
1616
2333
|
/** Set only while `status` is `awaiting_user`, and not always then — a pause saved by an older build has none. */
|
|
1617
2334
|
awaitingReason?: AwaitingReason;
|
|
2335
|
+
/**
|
|
2336
|
+
* The question a delegated task's subplanner is parked on (ADR-0056 M8). The
|
|
2337
|
+
* live one is held in memory by what answers it, so this copy is only what a
|
|
2338
|
+
* restart can still say was lost (ADR-0055 D17). Goes with the wait.
|
|
2339
|
+
*/
|
|
2340
|
+
parkedQuestion?: string;
|
|
2341
|
+
/**
|
|
2342
|
+
* How many waits have ended since its latest attempt started, or since the
|
|
2343
|
+
* task was written if none has: an attempt can wait many times, and this
|
|
2344
|
+
* tells one wait from the next in an escalation's id (ADR-0053). Saved with
|
|
2345
|
+
* the plan, so the id holds across a reload. Absent counts as none.
|
|
2346
|
+
*/
|
|
2347
|
+
waitsEnded?: number;
|
|
1618
2348
|
/**
|
|
1619
2349
|
* When a task paused on its runner's usage limit is resumed on its own (ISO
|
|
1620
2350
|
* time): the reset the runner announced, plus a short margin. Absent when no
|
|
@@ -1630,6 +2360,12 @@ interface Task {
|
|
|
1630
2360
|
carriedFrom?: RunnerId;
|
|
1631
2361
|
/** Why the task was skipped, as whoever skipped it put it; set only while `status` is `skipped`, and not always then. */
|
|
1632
2362
|
skipReason?: string;
|
|
2363
|
+
/**
|
|
2364
|
+
* The user reverted its landed work (ADR-0054): saved with the plan, so the
|
|
2365
|
+
* hold that keeps it from running again outlives this process. Set only
|
|
2366
|
+
* while it waits as the revert left it: its next start clears it.
|
|
2367
|
+
*/
|
|
2368
|
+
reverted?: true;
|
|
1633
2369
|
/**
|
|
1634
2370
|
* An ops task (ADR-0020): it changes no repository files, runs at the
|
|
1635
2371
|
* workspace root rather than in a worktree, and waits for the change tasks
|
|
@@ -1678,6 +2414,22 @@ interface Task {
|
|
|
1678
2414
|
script?: string;
|
|
1679
2415
|
/** A script task's time limit; absent means ten minutes (`DEFAULT_SCRIPT_TIMEOUT_MS`). */
|
|
1680
2416
|
timeoutMs?: number;
|
|
2417
|
+
/** What a delegated task's child plan must achieve, in place of a prompt (ADR-0055 D1). */
|
|
2418
|
+
goal?: string;
|
|
2419
|
+
/** A delegated task's budget (ADR-0056 M5). */
|
|
2420
|
+
budget?: DelegatedBudget;
|
|
2421
|
+
/** What a delegated task asks for past the floor; absent asks for nothing (ADR-0056 M2). */
|
|
2422
|
+
grants?: Grant[];
|
|
2423
|
+
/** The paths a delegated task's child may not change, what its check runs among them (ADR-0055 D7). */
|
|
2424
|
+
protectedPaths?: string[];
|
|
2425
|
+
/** What a delegated task declares it works on (ADR-0057 R6). */
|
|
2426
|
+
scope?: TaskScope;
|
|
2427
|
+
/**
|
|
2428
|
+
* On a delegated task, it answers a question and lands nothing (ADR-0055 D1).
|
|
2429
|
+
* On a script task, it runs sealed in a throwaway worktree, past no gate (D8).
|
|
2430
|
+
* A read-only AI task says so by its mode (ADR-0031) and stores none.
|
|
2431
|
+
*/
|
|
2432
|
+
readOnly?: boolean;
|
|
1681
2433
|
/** Set on a loop's check (ADR-0045): the tasks that fix what it finds, and how many times it may run. */
|
|
1682
2434
|
loop?: TaskLoop;
|
|
1683
2435
|
/**
|
|
@@ -1709,6 +2461,9 @@ type TaskReportTo = ({
|
|
|
1709
2461
|
} | {
|
|
1710
2462
|
actor: 'supervisor';
|
|
1711
2463
|
level: SupervisorLevel;
|
|
2464
|
+
} | {
|
|
2465
|
+
actor: 'subplanner';
|
|
2466
|
+
depth: number;
|
|
1712
2467
|
});
|
|
1713
2468
|
/** Whose authority a turn opened without the user acts with (ADR-0037, R3): the user's turn, or the supervisor's. */
|
|
1714
2469
|
type TurnAuthority = 'user' | 'supervisor';
|
|
@@ -1995,6 +2750,13 @@ interface PendingPlanTurn {
|
|
|
1995
2750
|
* the user's turn, which the turn then acts as (R3).
|
|
1996
2751
|
*/
|
|
1997
2752
|
report?: TurnAuthority;
|
|
2753
|
+
/**
|
|
2754
|
+
* The tasks a supervisor input is wholly about, absent when any of it is about
|
|
2755
|
+
* the run. While the user has stopped all of them it opens no turn (ADR-0029).
|
|
2756
|
+
*/
|
|
2757
|
+
tasks?: string[];
|
|
2758
|
+
/** It goes with the next turn and opens none (ADR-0057 R6). */
|
|
2759
|
+
rides?: true;
|
|
1998
2760
|
}
|
|
1999
2761
|
/**
|
|
2000
2762
|
* The run's own copy of the user's run settings (ADR-0030): taken when the
|
|
@@ -2192,4 +2954,4 @@ type ApprovalRecord = Pick<LegacyPlanState, 'approved' | 'approvedTasks'>;
|
|
|
2192
2954
|
*/
|
|
2193
2955
|
declare function waitsForApproval(task: Pick<Task, 'id' | 'type' | 'status'>, record: ApprovalRecord): boolean;
|
|
2194
2956
|
|
|
2195
|
-
export { type
|
|
2957
|
+
export { type IsolationLanding as $, type ApprovalRecord as A, BUILTIN_SKILL_NAMES as B, type CheckWord as C, DEFAULT_LOOP_ROUNDS as D, type EffectRules as E, FLOOR_GRANTS as F, GRANTS as G, HANDOFF_LIMITS as H, type HandoffCheck as I, type HandoffCommit as J, type HandoffDigest as K, type HandoffEvidence as L, type HandoffFinding as M, type HandoffLogs as N, type HandoffPatch as O, type HandoffPins as P, type HandoffPreviewOptions as Q, type HandoffTaskName as R, type IIsolationPreview as S, type IWorktreeIsolation as T, type IntegrationDisposal as U, type InvalidSkill as V, type IsolationAvailability as W, type IsolationHandoff as X, type IsolationHandoffRepo as Y, type IsolationInactiveReason as Z, type IsolationLandedTask as _, type AttemptUsage as a, type RevertCommand as a$, type IsolationMergeBlock as a0, type IsolationMergeBlockReason as a1, type IsolationMergeResult as a2, type IsolationOutcome as a3, type IsolationPreview as a4, type IsolationPruneResult as a5, type IsolationRemoval as a6, type IsolationRepo as a7, type IsolationRepoRevert as a8, type IsolationRevertResult as a9, type PlanUsage as aA, type PlannerAllowlist as aB, type PlannerCompaction as aC, type PlannerCompactionOutcome as aD, type PlannerContextPause as aE, type PlannerResendState as aF, type PlannerUsage as aG, type PrepareIntent as aH, type PreparedTask as aI, type PreservedWork as aJ, type PreviewRepo as aK, type PreviousWork as aL, REPORT_MAX_CHARS as aM, ROOT_NODE as aN, type RefusedRemoval as aO, type RepairEvidence as aP, type RepairWait as aQ, type ReplyRun as aR, type RepoGroupLayout as aS, type RepoHead as aT, type ReportItem as aU, type ReportedWindow as aV, type ResearchLogEntry as aW, type ResearchProgress as aX, type ResearchStep as aY, type ResearchStepOutcome as aZ, type ResearchToolType as a_, type IsolationRevertTask as aa, type IsolationRun as ab, type IsolationTaskRecord as ac, type IsolationTaskRef as ad, type IsolationTaskRepo as ae, type IsolationTaskStatus as af, type IsolationView as ag, type LandedTask as ah, type LandedWork as ai, type LegacyPlanState as aj, type LoopSubject as ak, MAX_LOOP_ROUNDS as al, type Mandate as am, type MandateExclusions as an, type MandateLimits as ao, type MandateRefusal as ap, type MandateRequest as aq, type ModelUsage as ar, type Narrowed as as, type NodeAuthority as at, type PatchFlag as au, type PatchView as av, type PendingPlanTurn as aw, type PlanIsolation as ax, type PlanState as ay, type PlanStatus as az, type AwaitingReason as b, costText as b$, type RevertWatch as b0, type RootSettings as b1, type RunSettings as b2, type RunnerId as b3, type RunnerSessionCost as b4, SEVERITY_LABEL as b5, SHAPE_LIMITS as b6, type ScriptBody as b7, type ScriptConsent as b8, type ScriptResult as b9, type TaskSnapshot as bA, type TaskStatus as bB, type TaskType as bC, type TaskUsageSummary as bD, type TreeSnapshot as bE, type UsageLine as bF, type UsageRecord as bG, type UsageTotals as bH, type Verdict as bI, type VerificationCheck as bJ, type WrittenTaskRef as bK, actorAuthority as bL, addAttemptUsage as bM, addModelUsage as bN, addPlannerUsage as bO, addUsage as bP, addUsageTotals as bQ, artifactLines as bR, betweenRounds as bS, boundedHandoffLines as bT, byteSize as bU, checkHandoff as bV, checkOf as bW, commandAllowedBy as bX, commandLine as bY, contextMeterText as bZ, contextMeterTitle as b_, type SessionBilling as ba, type SetupFailure as bb, type ShadowedSkill as bc, type SkillAppliesTo as bd, type SkillCatalog as be, type SkillInfo as bf, type SkillLoad as bg, type SkillLoadNotice as bh, type SkillMetadata as bi, type SkillSource as bj, SkillsService as bk, type StoredHandoff as bl, type SubagentOutcome as bm, type SubtreeReport as bn, type SupervisorLevel as bo, type Task as bp, type TaskDiffRead as bq, type TaskDiffResult as br, type TaskEvidence as bs, type TaskIsolation as bt, type TaskIsolationState as bu, type TaskLoop as bv, type TaskModelAssignment as bw, type TaskReportTo as bx, type TaskSkillNotice as by, type TaskSkillSnapshot as bz, type BelowPlan as c, scriptTaskText as c$, countedSessionCost as c0, createEmptyPlan as c1, createSkillsService as c2, createTask as c3, effectRuleFor as c4, endAttemptUsage as c5, findingLines as c6, findingRefText as c7, flattenTasks as c8, flattenTasksWithParents as c9, parseEffectAllowlist as cA, parseFindingRef as cB, parsePlanPath as cC, partedPromptUsage as cD, patchChangesText as cE, patchFlagText as cF, patchLines as cG, patchLinesText as cH, patchText as cI, patchView as cJ, pausedOnLimit as cK, pinReference as cL, planUsage as cM, plannerContextFill as cN, readableTaskIds as cO, rejoinPlanTree as cP, removedAttempt as cQ, resolveWrittenRef as cR, resumedSessionWindow as cS, rootAuthority as cT, rootMandate as cU, savedPatchOf as cV, savedPatchView as cW, savedPatchViews as cX, scopeAllowed as cY, scriptBodyOf as cZ, scriptBodyText as c_, formatCost as ca, formatTokenCount as cb, handoffDigest as cc, handoffLines as cd, handoffPreviewLines as ce, handoffReferenceText as cf, handoffWakeLines as cg, heldHandoff as ch, heldMandate as ci, heldWords as cj, inLoop as ck, isAwaitingReason as cl, isMeasured as cm, isSupervisorLevel as cn, isUserMessage as co, loopRemovalRefusal as cp, loopRoundOf as cq, mandateRefusalText as cr, migratePlanState as cs, modelCostTitle as ct, namedHandoff as cu, narrow as cv, nodeText as cw, openingLines as cx, outOfRounds as cy, parseAllowlist as cz, type ChildTaskCounts as d, severityLabel as d0, spentTokens as d1, startAttemptUsage as d2, storedHandoff as d3, subagentCostTitle as d4, taskUsageSummary as d5, tasksTotalText as d6, timeLimitText as d7, toolAllowed as d8, usageLine as d9, usageText as da, waitsForApproval as db, withPatch as dc, wordsFrom as dd, worstSeverity as de, type CommandWords as e, type ContextCheckpoint as f, type ContextFill as g, type ConversationMessage as h, type CostProvenance as i, DEFAULT_PLANNER_ALLOWLIST as j, DEFAULT_RUNNERS as k, DEFAULT_SCRIPT_TIMEOUT_MS as l, DEFAULT_SUPERVISOR_RETRY_LIMIT as m, DIGEST_FINDINGS as n, type DelegatedRow as o, type DiscoveredModel as p, type ExecutionActor as q, type ExecutionCommandName as r, type ExecutionRecord as s, type FindingSeverity as t, type Grant as u, type GuardTarget as v, type GuardTrip as w, HANDOFF_PUSH_CHARS as x, type Handoff as y, type HandoffArtifact as z };
|