@ordewell/core 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ITerminalRunner-DXlJop_f.d.mts → ITerminalRunner-DCjsa2-I.d.mts} +6 -1
- package/dist/{ITerminalRunner-nupxhtPb.d.ts → ITerminalRunner-H1yT8LTy.d.ts} +6 -1
- package/dist/{ModeResolver-D1-2xJsE.d.mts → ModeResolver-DVJ7HV3k.d.mts} +1 -1
- package/dist/{ModeResolver-BBVktyiP.d.ts → ModeResolver-Dkig8ghQ.d.ts} +1 -1
- package/dist/{Task-CfTjRQeS.d.mts → Task-BxQkPlXO.d.mts} +88 -10
- package/dist/{Task-CfTjRQeS.d.ts → Task-BxQkPlXO.d.ts} +88 -10
- package/dist/{chunk-HQICT7HQ.mjs → chunk-T2S5O36I.mjs} +17 -4
- package/dist/chunk-T2S5O36I.mjs.map +1 -0
- package/dist/index.d.mts +82 -57
- package/dist/index.d.ts +82 -57
- package/dist/index.js +658 -252
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +657 -264
- package/dist/index.mjs.map +1 -1
- package/dist/order-labels.d.mts +1 -1
- package/dist/order-labels.d.ts +1 -1
- package/dist/{parsing-Bv3g2Tu_.d.ts → parsing-CF_grC29.d.ts} +2 -2
- package/dist/{parsing-BJECTMOD.d.mts → parsing-DRp4dPC0.d.mts} +2 -2
- package/dist/parsing.d.mts +3 -3
- package/dist/parsing.d.ts +3 -3
- package/dist/{plan-utils-Cy-RsBSV.d.ts → plan-utils-CkNbqAmS.d.ts} +36 -3
- package/dist/{plan-utils-B5oIZkuI.d.mts → plan-utils-CtB3_Ovf.d.mts} +36 -3
- package/dist/plan-utils.d.mts +3 -3
- package/dist/plan-utils.d.ts +3 -3
- package/dist/plan-utils.js +7 -0
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +4 -0
- package/dist/testing.d.mts +20 -8
- package/dist/testing.d.ts +20 -8
- package/dist/testing.js +52 -4
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +47 -4
- package/dist/testing.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-HQICT7HQ.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { I as IApproval, a as ApprovalMode } from './ApprovalPolicy-BVhGdECT.mjs';
|
|
2
|
-
import {
|
|
2
|
+
import { F as RunnerId } from './Task-BxQkPlXO.mjs';
|
|
3
3
|
|
|
4
4
|
interface ToolOutcome {
|
|
5
5
|
success: boolean;
|
|
@@ -230,6 +230,11 @@ interface IConfig {
|
|
|
230
230
|
* `*.tfstate` that a task must use, not a copy of.
|
|
231
231
|
*/
|
|
232
232
|
worktreeLinks: string[];
|
|
233
|
+
/**
|
|
234
|
+
* How many conflict repairs one task may go through before its conflict is
|
|
235
|
+
* left for a person (ADR-0015); 0 turns repair off.
|
|
236
|
+
*/
|
|
237
|
+
conflictRepairAttempts: number;
|
|
233
238
|
/**
|
|
234
239
|
* What to do when planner research reaches outside its default envelope — an
|
|
235
240
|
* out-of-workspace path, or a shell command beyond the auto-allowed read-only
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { I as IApproval, a as ApprovalMode } from './ApprovalPolicy-BVhGdECT.js';
|
|
2
|
-
import {
|
|
2
|
+
import { F as RunnerId } from './Task-BxQkPlXO.js';
|
|
3
3
|
|
|
4
4
|
interface ToolOutcome {
|
|
5
5
|
success: boolean;
|
|
@@ -230,6 +230,11 @@ interface IConfig {
|
|
|
230
230
|
* `*.tfstate` that a task must use, not a copy of.
|
|
231
231
|
*/
|
|
232
232
|
worktreeLinks: string[];
|
|
233
|
+
/**
|
|
234
|
+
* How many conflict repairs one task may go through before its conflict is
|
|
235
|
+
* left for a person (ADR-0015); 0 turns repair off.
|
|
236
|
+
*/
|
|
237
|
+
conflictRepairAttempts: number;
|
|
233
238
|
/**
|
|
234
239
|
* What to do when planner research reaches outside its default envelope — an
|
|
235
240
|
* out-of-workspace path, or a shell command beyond the auto-allowed read-only
|
|
@@ -35,10 +35,12 @@ type IsolationOutcome = 'merged' | 'conflict' | 'failed';
|
|
|
35
35
|
* `active` — worktree exists, a runner may be writing to it.
|
|
36
36
|
* `kept` — released with its worktree and branch preserved for inspection.
|
|
37
37
|
* `conflict` — integration stopped on a merge conflict; worktree and refs kept.
|
|
38
|
+
* `repairing` — a conflict repair (ADR-0015) is working in the kept worktree;
|
|
39
|
+
* one that ends without landing leaves the task `conflict` again.
|
|
38
40
|
* `failed` — integration hit a git error other than a conflict; refs kept.
|
|
39
41
|
* `merged` — landed on the integration branch; worktree and task branch removed.
|
|
40
42
|
*/
|
|
41
|
-
type IsolationTaskStatus = 'active' | 'kept' | 'conflict' | 'failed' | 'merged';
|
|
43
|
+
type IsolationTaskStatus = 'active' | 'kept' | 'conflict' | 'repairing' | 'failed' | 'merged';
|
|
42
44
|
/** One repo's share of a task: its worktree inside the task workspace. */
|
|
43
45
|
interface IsolationTaskRepo {
|
|
44
46
|
/** Absolute path of this repo's worktree: the task workspace joined with the repo's path. */
|
|
@@ -70,6 +72,24 @@ interface IsolationTaskRecord {
|
|
|
70
72
|
repos: Record<string, IsolationTaskRepo>;
|
|
71
73
|
/** The repo whose merge stopped the task from landing, while `status` is `conflict` or `failed`. */
|
|
72
74
|
conflictRepo?: string;
|
|
75
|
+
/** Repo-relative paths, in `conflictRepo`, that conflicted; set only while `status` is `conflict` or `repairing`. */
|
|
76
|
+
conflictFiles?: string[];
|
|
77
|
+
/**
|
|
78
|
+
* Conflict repairs started for this task (ADR-0015). Counted when one starts,
|
|
79
|
+
* so a crash cannot hand the spent attempt back; absent reads as none.
|
|
80
|
+
*/
|
|
81
|
+
repairs?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Keyed by repo path: each changed repo's integration tip when the repair in
|
|
84
|
+
* flight started — what the task branch must contain before it may land.
|
|
85
|
+
* Set only while `status` is `repairing`.
|
|
86
|
+
*/
|
|
87
|
+
repairBase?: Record<string, string>;
|
|
88
|
+
/**
|
|
89
|
+
* Every file a repair was started for, across all of them: as `conflictFiles`
|
|
90
|
+
* names it in a group of one, prefixed with its repo's path in a group.
|
|
91
|
+
*/
|
|
92
|
+
repairedFiles?: string[];
|
|
73
93
|
}
|
|
74
94
|
/**
|
|
75
95
|
* A task's landing in flight: each changed repo's integration tip from before
|
|
@@ -144,7 +164,7 @@ interface PlanIsolation {
|
|
|
144
164
|
* did not land and can be looked at. `none` is a task with no worktree in a plan
|
|
145
165
|
* that has an isolation run.
|
|
146
166
|
*/
|
|
147
|
-
type TaskIsolationState = 'none' | 'active' | 'integrated' | 'conflict' | 'kept';
|
|
167
|
+
type TaskIsolationState = 'none' | 'active' | 'integrated' | 'conflict' | 'repairing' | 'kept';
|
|
148
168
|
type TaskIsolation = {
|
|
149
169
|
state: 'none';
|
|
150
170
|
} | {
|
|
@@ -155,11 +175,22 @@ type TaskIsolation = {
|
|
|
155
175
|
/** Paths of the repos the task changed. */
|
|
156
176
|
repos: string[];
|
|
157
177
|
conflictRepo?: string;
|
|
178
|
+
/** Repo-relative paths, in `conflictRepo`, that conflicted. */
|
|
179
|
+
conflictFiles?: string[];
|
|
180
|
+
/** The conflict repair running or last run, of the most a task may have; absent before its first. */
|
|
181
|
+
repair?: {
|
|
182
|
+
attempt: number;
|
|
183
|
+
limit: number;
|
|
184
|
+
};
|
|
185
|
+
/** What {@link IsolationTaskRecord.repairedFiles} says. */
|
|
186
|
+
repairedFiles?: string[];
|
|
158
187
|
};
|
|
159
188
|
interface IsolationLandedTask {
|
|
160
189
|
taskId: string;
|
|
161
190
|
order: number;
|
|
162
191
|
title: string;
|
|
192
|
+
/** Set when the task landed only after a conflict repair (ADR-0015): the files it was started for. */
|
|
193
|
+
repairedFiles?: string[];
|
|
163
194
|
}
|
|
164
195
|
interface IsolationHandoffRepo {
|
|
165
196
|
path: string;
|
|
@@ -214,6 +245,26 @@ type IsolationMergeResult = {
|
|
|
214
245
|
files?: string[];
|
|
215
246
|
landed?: string[];
|
|
216
247
|
};
|
|
248
|
+
/**
|
|
249
|
+
* What `discard` does with each repo's integration branch: `keep` it for review
|
|
250
|
+
* or merge, `delete` it, or delete it only in the repos whose checked-out HEAD
|
|
251
|
+
* already contains it (`delete-merged`) — the one way that can never give up
|
|
252
|
+
* landed work the user has not merged.
|
|
253
|
+
*/
|
|
254
|
+
type IntegrationDisposal = 'keep' | 'delete' | 'delete-merged';
|
|
255
|
+
/**
|
|
256
|
+
* Whether a conflict repair's work may land. `not-merged`: the task branch in
|
|
257
|
+
* `repo` does not contain the tip the repair started from. `conflict-markers`:
|
|
258
|
+
* it adds leftover conflict markers to `files`. `failed`: git could not tell.
|
|
259
|
+
*/
|
|
260
|
+
type RepairEvidence = {
|
|
261
|
+
ok: true;
|
|
262
|
+
} | {
|
|
263
|
+
ok: false;
|
|
264
|
+
reason: 'not-merged' | 'conflict-markers' | 'failed';
|
|
265
|
+
repo: string;
|
|
266
|
+
files?: string[];
|
|
267
|
+
};
|
|
217
268
|
interface PreparedTask {
|
|
218
269
|
cwd: string;
|
|
219
270
|
branch: string;
|
|
@@ -250,6 +301,21 @@ interface IWorktreeIsolation {
|
|
|
250
301
|
* task sees everything its predecessors have integrated.
|
|
251
302
|
*/
|
|
252
303
|
prepare(task: Task, run: IsolationRun): Promise<PreparedTask>;
|
|
304
|
+
/**
|
|
305
|
+
* Hand a conflicted task's kept workspace to a conflict repair (ADR-0015)
|
|
306
|
+
* as it is — nothing is re-cut — and return the same cwd. Records each
|
|
307
|
+
* changed repo's integration tip as `repairBase`, counts the repair, and
|
|
308
|
+
* moves the task to `repairing`. Throws for a task that is not `conflict`.
|
|
309
|
+
*/
|
|
310
|
+
reopen(task: Task, run: IsolationRun): Promise<PreparedTask>;
|
|
311
|
+
/**
|
|
312
|
+
* The evidence a repair must show before it lands: its work committed, and
|
|
313
|
+
* in each repo of `repairBase` the task branch containing that tip
|
|
314
|
+
* (`git merge-base --is-ancestor`) and adding no leftover conflict markers
|
|
315
|
+
* (`git diff --check`; whitespace warnings do not count). Changes nothing
|
|
316
|
+
* else: a task that fails stays `repairing` until released.
|
|
317
|
+
*/
|
|
318
|
+
verifyRepair(task: Task, run: IsolationRun): Promise<RepairEvidence>;
|
|
253
319
|
/**
|
|
254
320
|
* Land the task atomically across the repos it changed: commit each
|
|
255
321
|
* worktree, then `git merge --no-ff` the task branch into each changed
|
|
@@ -257,7 +323,9 @@ interface IWorktreeIsolation {
|
|
|
257
323
|
* and the merges already made for the task are reset away, so `merged`
|
|
258
324
|
* always means the whole task landed. Serialized inside the module; among
|
|
259
325
|
* tasks waiting at once the lowest plan order goes first. On anything but
|
|
260
|
-
* `merged` the worktrees and refs stay, and nothing is
|
|
326
|
+
* `merged` the worktrees and refs stay, and nothing is resolved here: a
|
|
327
|
+
* conflict is repaired, if at all, by a new attempt of the task in its own
|
|
328
|
+
* worktree (ADR-0015), never inside this queue.
|
|
261
329
|
*
|
|
262
330
|
* `persist` is called once `run.landing` is set and before the first
|
|
263
331
|
* merge; the caller saves the run there, synchronously, which is what
|
|
@@ -268,7 +336,8 @@ interface IWorktreeIsolation {
|
|
|
268
336
|
* `keep: false` removes the task's worktree, branch and record (cancel, task
|
|
269
337
|
* removal). `keep: true` leaves the worktree and branch exactly as they are
|
|
270
338
|
* for inspection — a failed verdict — and only moves the task off `active`,
|
|
271
|
-
* so a crash-recovery prune does not sweep it away
|
|
339
|
+
* so a crash-recovery prune does not sweep it away; a repair it ends leaves
|
|
340
|
+
* the task `conflict`, as it was before the repair. Takes the run rather than
|
|
272
341
|
* a bare task id: ids are only unique within one plan, and one daemon serves
|
|
273
342
|
* many (ADR-0007).
|
|
274
343
|
*/
|
|
@@ -279,7 +348,8 @@ interface IWorktreeIsolation {
|
|
|
279
348
|
handoff(run: IsolationRun): Promise<IsolationHandoff>;
|
|
280
349
|
/**
|
|
281
350
|
* Drop what a crash left behind: a landing it interrupted is rolled back in
|
|
282
|
-
* every repo,
|
|
351
|
+
* every repo, a repair it interrupted leaves its task `conflict`, then stale
|
|
352
|
+
* active worktrees and directories no record owns go.
|
|
283
353
|
*/
|
|
284
354
|
pruneOrphans(run: IsolationRun): Promise<void>;
|
|
285
355
|
/** Unified diff of each repo's integration branch against its base ref. */
|
|
@@ -295,13 +365,21 @@ interface IWorktreeIsolation {
|
|
|
295
365
|
*/
|
|
296
366
|
mergeIntoCheckedOut(run: IsolationRun): Promise<IsolationMergeResult>;
|
|
297
367
|
/**
|
|
298
|
-
* Remove every worktree and task branch of the run, and
|
|
299
|
-
* branch
|
|
300
|
-
*
|
|
368
|
+
* Remove every worktree and task branch of the run, and settle each repo's
|
|
369
|
+
* integration branch as `integration` says. Anything but `keep` also clears
|
|
370
|
+
* the run's task records.
|
|
301
371
|
*/
|
|
302
372
|
discard(run: IsolationRun, opts: {
|
|
303
|
-
|
|
373
|
+
integration: IntegrationDisposal;
|
|
304
374
|
}): Promise<void>;
|
|
375
|
+
/**
|
|
376
|
+
* Clear what other runs left in each repo of `run`'s group: every
|
|
377
|
+
* `ordewell/<run-id>/…` branch the repo's checked-out HEAD already contains.
|
|
378
|
+
* Never a branch of `run` itself, one a worktree has checked out, or any
|
|
379
|
+
* branch of a run that still has a worktree — that run may be live in
|
|
380
|
+
* another plan. Tries every repo, then throws naming those where git failed.
|
|
381
|
+
*/
|
|
382
|
+
sweep(run: IsolationRun): Promise<void>;
|
|
305
383
|
}
|
|
306
384
|
|
|
307
385
|
interface UserStep {
|
|
@@ -583,4 +661,4 @@ interface ValidationContext {
|
|
|
583
661
|
type ValidationCheck = (ctx: ValidationContext) => ValidationResult;
|
|
584
662
|
declare function warningsText(w: PlanModificationWarnings): string | null;
|
|
585
663
|
|
|
586
|
-
export { type
|
|
664
|
+
export { type UserStep as $, type ActiveTaskSession as A, type ResearchStepOutcome as B, type ConversationMessage as C, type DiscoveredMode as D, type ResearchToolType as E, type RunnerId as F, type StreamStepEvent as G, type StreamThinkingEvent as H, type IWorktreeIsolation as I, type TaskIsolation as J, type TaskIsolationState as K, type LegacyPlanState as L, type Message as M, type TaskMode as N, type TaskModelAssignment as O, type PlanIsolation as P, type QueuedMessage as Q, type RepairEvidence as R, type StreamEvent as S, type Task as T, type TaskOutputSummary as U, type TaskSnapshot as V, type TaskStatus as W, type TaskType as X, type TaskWithParent as Y, type ThinkingBlock as Z, type UserPromptEntry as _, type DiscoveredModel as a, type ValidationCheck as a0, type ValidationContext as a1, type ValidationResult as a2, type Verdict as a3, type VerificationCheck as a4, addTaskToPlan as a5, createEmptyPlan as a6, createTask as a7, emptyWarnings as a8, flattenTasks as a9, flattenTasksWithParents as aa, migrateLegacyPlan as ab, migratePlanState as ac, migrateTask as ad, removeTaskFromPlan as ae, renumberTasks as af, updateTaskInPlan as ag, validateModifiedPlan as ah, warningsText as ai, type IntegrationDisposal as b, type IsolationAvailability as c, type IsolationHandoff as d, type IsolationHandoffRepo as e, type IsolationInactiveReason as f, type IsolationLandedTask as g, type IsolationLanding as h, type IsolationMergeBlock as i, type IsolationMergeBlockReason as j, type IsolationMergeResult as k, type IsolationOutcome as l, type IsolationRepo as m, type IsolationRun as n, type IsolationTaskRecord as o, type IsolationTaskRepo as p, type IsolationTaskStatus as q, type IsolationView as r, type PlanModificationWarnings as s, type PlanState as t, type PlanStatus as u, type PreparedTask as v, type RepoGroupLayout as w, type ResearchLogEntry as x, type ResearchProgress as y, type ResearchStep as z };
|
|
@@ -35,10 +35,12 @@ type IsolationOutcome = 'merged' | 'conflict' | 'failed';
|
|
|
35
35
|
* `active` — worktree exists, a runner may be writing to it.
|
|
36
36
|
* `kept` — released with its worktree and branch preserved for inspection.
|
|
37
37
|
* `conflict` — integration stopped on a merge conflict; worktree and refs kept.
|
|
38
|
+
* `repairing` — a conflict repair (ADR-0015) is working in the kept worktree;
|
|
39
|
+
* one that ends without landing leaves the task `conflict` again.
|
|
38
40
|
* `failed` — integration hit a git error other than a conflict; refs kept.
|
|
39
41
|
* `merged` — landed on the integration branch; worktree and task branch removed.
|
|
40
42
|
*/
|
|
41
|
-
type IsolationTaskStatus = 'active' | 'kept' | 'conflict' | 'failed' | 'merged';
|
|
43
|
+
type IsolationTaskStatus = 'active' | 'kept' | 'conflict' | 'repairing' | 'failed' | 'merged';
|
|
42
44
|
/** One repo's share of a task: its worktree inside the task workspace. */
|
|
43
45
|
interface IsolationTaskRepo {
|
|
44
46
|
/** Absolute path of this repo's worktree: the task workspace joined with the repo's path. */
|
|
@@ -70,6 +72,24 @@ interface IsolationTaskRecord {
|
|
|
70
72
|
repos: Record<string, IsolationTaskRepo>;
|
|
71
73
|
/** The repo whose merge stopped the task from landing, while `status` is `conflict` or `failed`. */
|
|
72
74
|
conflictRepo?: string;
|
|
75
|
+
/** Repo-relative paths, in `conflictRepo`, that conflicted; set only while `status` is `conflict` or `repairing`. */
|
|
76
|
+
conflictFiles?: string[];
|
|
77
|
+
/**
|
|
78
|
+
* Conflict repairs started for this task (ADR-0015). Counted when one starts,
|
|
79
|
+
* so a crash cannot hand the spent attempt back; absent reads as none.
|
|
80
|
+
*/
|
|
81
|
+
repairs?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Keyed by repo path: each changed repo's integration tip when the repair in
|
|
84
|
+
* flight started — what the task branch must contain before it may land.
|
|
85
|
+
* Set only while `status` is `repairing`.
|
|
86
|
+
*/
|
|
87
|
+
repairBase?: Record<string, string>;
|
|
88
|
+
/**
|
|
89
|
+
* Every file a repair was started for, across all of them: as `conflictFiles`
|
|
90
|
+
* names it in a group of one, prefixed with its repo's path in a group.
|
|
91
|
+
*/
|
|
92
|
+
repairedFiles?: string[];
|
|
73
93
|
}
|
|
74
94
|
/**
|
|
75
95
|
* A task's landing in flight: each changed repo's integration tip from before
|
|
@@ -144,7 +164,7 @@ interface PlanIsolation {
|
|
|
144
164
|
* did not land and can be looked at. `none` is a task with no worktree in a plan
|
|
145
165
|
* that has an isolation run.
|
|
146
166
|
*/
|
|
147
|
-
type TaskIsolationState = 'none' | 'active' | 'integrated' | 'conflict' | 'kept';
|
|
167
|
+
type TaskIsolationState = 'none' | 'active' | 'integrated' | 'conflict' | 'repairing' | 'kept';
|
|
148
168
|
type TaskIsolation = {
|
|
149
169
|
state: 'none';
|
|
150
170
|
} | {
|
|
@@ -155,11 +175,22 @@ type TaskIsolation = {
|
|
|
155
175
|
/** Paths of the repos the task changed. */
|
|
156
176
|
repos: string[];
|
|
157
177
|
conflictRepo?: string;
|
|
178
|
+
/** Repo-relative paths, in `conflictRepo`, that conflicted. */
|
|
179
|
+
conflictFiles?: string[];
|
|
180
|
+
/** The conflict repair running or last run, of the most a task may have; absent before its first. */
|
|
181
|
+
repair?: {
|
|
182
|
+
attempt: number;
|
|
183
|
+
limit: number;
|
|
184
|
+
};
|
|
185
|
+
/** What {@link IsolationTaskRecord.repairedFiles} says. */
|
|
186
|
+
repairedFiles?: string[];
|
|
158
187
|
};
|
|
159
188
|
interface IsolationLandedTask {
|
|
160
189
|
taskId: string;
|
|
161
190
|
order: number;
|
|
162
191
|
title: string;
|
|
192
|
+
/** Set when the task landed only after a conflict repair (ADR-0015): the files it was started for. */
|
|
193
|
+
repairedFiles?: string[];
|
|
163
194
|
}
|
|
164
195
|
interface IsolationHandoffRepo {
|
|
165
196
|
path: string;
|
|
@@ -214,6 +245,26 @@ type IsolationMergeResult = {
|
|
|
214
245
|
files?: string[];
|
|
215
246
|
landed?: string[];
|
|
216
247
|
};
|
|
248
|
+
/**
|
|
249
|
+
* What `discard` does with each repo's integration branch: `keep` it for review
|
|
250
|
+
* or merge, `delete` it, or delete it only in the repos whose checked-out HEAD
|
|
251
|
+
* already contains it (`delete-merged`) — the one way that can never give up
|
|
252
|
+
* landed work the user has not merged.
|
|
253
|
+
*/
|
|
254
|
+
type IntegrationDisposal = 'keep' | 'delete' | 'delete-merged';
|
|
255
|
+
/**
|
|
256
|
+
* Whether a conflict repair's work may land. `not-merged`: the task branch in
|
|
257
|
+
* `repo` does not contain the tip the repair started from. `conflict-markers`:
|
|
258
|
+
* it adds leftover conflict markers to `files`. `failed`: git could not tell.
|
|
259
|
+
*/
|
|
260
|
+
type RepairEvidence = {
|
|
261
|
+
ok: true;
|
|
262
|
+
} | {
|
|
263
|
+
ok: false;
|
|
264
|
+
reason: 'not-merged' | 'conflict-markers' | 'failed';
|
|
265
|
+
repo: string;
|
|
266
|
+
files?: string[];
|
|
267
|
+
};
|
|
217
268
|
interface PreparedTask {
|
|
218
269
|
cwd: string;
|
|
219
270
|
branch: string;
|
|
@@ -250,6 +301,21 @@ interface IWorktreeIsolation {
|
|
|
250
301
|
* task sees everything its predecessors have integrated.
|
|
251
302
|
*/
|
|
252
303
|
prepare(task: Task, run: IsolationRun): Promise<PreparedTask>;
|
|
304
|
+
/**
|
|
305
|
+
* Hand a conflicted task's kept workspace to a conflict repair (ADR-0015)
|
|
306
|
+
* as it is — nothing is re-cut — and return the same cwd. Records each
|
|
307
|
+
* changed repo's integration tip as `repairBase`, counts the repair, and
|
|
308
|
+
* moves the task to `repairing`. Throws for a task that is not `conflict`.
|
|
309
|
+
*/
|
|
310
|
+
reopen(task: Task, run: IsolationRun): Promise<PreparedTask>;
|
|
311
|
+
/**
|
|
312
|
+
* The evidence a repair must show before it lands: its work committed, and
|
|
313
|
+
* in each repo of `repairBase` the task branch containing that tip
|
|
314
|
+
* (`git merge-base --is-ancestor`) and adding no leftover conflict markers
|
|
315
|
+
* (`git diff --check`; whitespace warnings do not count). Changes nothing
|
|
316
|
+
* else: a task that fails stays `repairing` until released.
|
|
317
|
+
*/
|
|
318
|
+
verifyRepair(task: Task, run: IsolationRun): Promise<RepairEvidence>;
|
|
253
319
|
/**
|
|
254
320
|
* Land the task atomically across the repos it changed: commit each
|
|
255
321
|
* worktree, then `git merge --no-ff` the task branch into each changed
|
|
@@ -257,7 +323,9 @@ interface IWorktreeIsolation {
|
|
|
257
323
|
* and the merges already made for the task are reset away, so `merged`
|
|
258
324
|
* always means the whole task landed. Serialized inside the module; among
|
|
259
325
|
* tasks waiting at once the lowest plan order goes first. On anything but
|
|
260
|
-
* `merged` the worktrees and refs stay, and nothing is
|
|
326
|
+
* `merged` the worktrees and refs stay, and nothing is resolved here: a
|
|
327
|
+
* conflict is repaired, if at all, by a new attempt of the task in its own
|
|
328
|
+
* worktree (ADR-0015), never inside this queue.
|
|
261
329
|
*
|
|
262
330
|
* `persist` is called once `run.landing` is set and before the first
|
|
263
331
|
* merge; the caller saves the run there, synchronously, which is what
|
|
@@ -268,7 +336,8 @@ interface IWorktreeIsolation {
|
|
|
268
336
|
* `keep: false` removes the task's worktree, branch and record (cancel, task
|
|
269
337
|
* removal). `keep: true` leaves the worktree and branch exactly as they are
|
|
270
338
|
* for inspection — a failed verdict — and only moves the task off `active`,
|
|
271
|
-
* so a crash-recovery prune does not sweep it away
|
|
339
|
+
* so a crash-recovery prune does not sweep it away; a repair it ends leaves
|
|
340
|
+
* the task `conflict`, as it was before the repair. Takes the run rather than
|
|
272
341
|
* a bare task id: ids are only unique within one plan, and one daemon serves
|
|
273
342
|
* many (ADR-0007).
|
|
274
343
|
*/
|
|
@@ -279,7 +348,8 @@ interface IWorktreeIsolation {
|
|
|
279
348
|
handoff(run: IsolationRun): Promise<IsolationHandoff>;
|
|
280
349
|
/**
|
|
281
350
|
* Drop what a crash left behind: a landing it interrupted is rolled back in
|
|
282
|
-
* every repo,
|
|
351
|
+
* every repo, a repair it interrupted leaves its task `conflict`, then stale
|
|
352
|
+
* active worktrees and directories no record owns go.
|
|
283
353
|
*/
|
|
284
354
|
pruneOrphans(run: IsolationRun): Promise<void>;
|
|
285
355
|
/** Unified diff of each repo's integration branch against its base ref. */
|
|
@@ -295,13 +365,21 @@ interface IWorktreeIsolation {
|
|
|
295
365
|
*/
|
|
296
366
|
mergeIntoCheckedOut(run: IsolationRun): Promise<IsolationMergeResult>;
|
|
297
367
|
/**
|
|
298
|
-
* Remove every worktree and task branch of the run, and
|
|
299
|
-
* branch
|
|
300
|
-
*
|
|
368
|
+
* Remove every worktree and task branch of the run, and settle each repo's
|
|
369
|
+
* integration branch as `integration` says. Anything but `keep` also clears
|
|
370
|
+
* the run's task records.
|
|
301
371
|
*/
|
|
302
372
|
discard(run: IsolationRun, opts: {
|
|
303
|
-
|
|
373
|
+
integration: IntegrationDisposal;
|
|
304
374
|
}): Promise<void>;
|
|
375
|
+
/**
|
|
376
|
+
* Clear what other runs left in each repo of `run`'s group: every
|
|
377
|
+
* `ordewell/<run-id>/…` branch the repo's checked-out HEAD already contains.
|
|
378
|
+
* Never a branch of `run` itself, one a worktree has checked out, or any
|
|
379
|
+
* branch of a run that still has a worktree — that run may be live in
|
|
380
|
+
* another plan. Tries every repo, then throws naming those where git failed.
|
|
381
|
+
*/
|
|
382
|
+
sweep(run: IsolationRun): Promise<void>;
|
|
305
383
|
}
|
|
306
384
|
|
|
307
385
|
interface UserStep {
|
|
@@ -583,4 +661,4 @@ interface ValidationContext {
|
|
|
583
661
|
type ValidationCheck = (ctx: ValidationContext) => ValidationResult;
|
|
584
662
|
declare function warningsText(w: PlanModificationWarnings): string | null;
|
|
585
663
|
|
|
586
|
-
export { type
|
|
664
|
+
export { type UserStep as $, type ActiveTaskSession as A, type ResearchStepOutcome as B, type ConversationMessage as C, type DiscoveredMode as D, type ResearchToolType as E, type RunnerId as F, type StreamStepEvent as G, type StreamThinkingEvent as H, type IWorktreeIsolation as I, type TaskIsolation as J, type TaskIsolationState as K, type LegacyPlanState as L, type Message as M, type TaskMode as N, type TaskModelAssignment as O, type PlanIsolation as P, type QueuedMessage as Q, type RepairEvidence as R, type StreamEvent as S, type Task as T, type TaskOutputSummary as U, type TaskSnapshot as V, type TaskStatus as W, type TaskType as X, type TaskWithParent as Y, type ThinkingBlock as Z, type UserPromptEntry as _, type DiscoveredModel as a, type ValidationCheck as a0, type ValidationContext as a1, type ValidationResult as a2, type Verdict as a3, type VerificationCheck as a4, addTaskToPlan as a5, createEmptyPlan as a6, createTask as a7, emptyWarnings as a8, flattenTasks as a9, flattenTasksWithParents as aa, migrateLegacyPlan as ab, migratePlanState as ac, migrateTask as ad, removeTaskFromPlan as ae, renumberTasks as af, updateTaskInPlan as ag, validateModifiedPlan as ah, warningsText as ai, type IntegrationDisposal as b, type IsolationAvailability as c, type IsolationHandoff as d, type IsolationHandoffRepo as e, type IsolationInactiveReason as f, type IsolationLandedTask as g, type IsolationLanding as h, type IsolationMergeBlock as i, type IsolationMergeBlockReason as j, type IsolationMergeResult as k, type IsolationOutcome as l, type IsolationRepo as m, type IsolationRun as n, type IsolationTaskRecord as o, type IsolationTaskRepo as p, type IsolationTaskStatus as q, type IsolationView as r, type PlanModificationWarnings as s, type PlanState as t, type PlanStatus as u, type PreparedTask as v, type RepoGroupLayout as w, type ResearchLogEntry as x, type ResearchProgress as y, type ResearchStep as z };
|
|
@@ -17,21 +17,33 @@ var ISOLATION_STATE = {
|
|
|
17
17
|
active: "active",
|
|
18
18
|
merged: "integrated",
|
|
19
19
|
conflict: "conflict",
|
|
20
|
+
repairing: "repairing",
|
|
20
21
|
kept: "kept",
|
|
21
22
|
failed: "kept"
|
|
22
23
|
};
|
|
23
|
-
function taskIsolationOf(record) {
|
|
24
|
+
function taskIsolationOf(record, repairLimit) {
|
|
24
25
|
return {
|
|
25
26
|
state: ISOLATION_STATE[record.status],
|
|
26
27
|
branch: record.branch,
|
|
27
28
|
worktree: record.workspace,
|
|
28
29
|
repos: Object.entries(record.repos).filter(([, r]) => r.changed).map(([repoPath]) => repoPath),
|
|
29
|
-
...record.conflictRepo ? { conflictRepo: record.conflictRepo } : {}
|
|
30
|
+
...record.conflictRepo ? { conflictRepo: record.conflictRepo } : {},
|
|
31
|
+
...record.conflictFiles?.length ? { conflictFiles: record.conflictFiles } : {},
|
|
32
|
+
...record.repairs ? { repair: { attempt: record.repairs, limit: repairLimit } } : {},
|
|
33
|
+
...record.repairedFiles?.length ? { repairedFiles: record.repairedFiles } : {}
|
|
30
34
|
};
|
|
31
35
|
}
|
|
36
|
+
function capConflictFiles(files, max = 5) {
|
|
37
|
+
return files.length <= max ? files.join(", ") : `${files.slice(0, max).join(", ")}, +${files.length - max} more`;
|
|
38
|
+
}
|
|
32
39
|
function handoffOf(run) {
|
|
33
40
|
const merged = Object.values(run.tasks).filter((r) => r.status === "merged").sort((a, b) => a.order - b.order);
|
|
34
|
-
const entry = (r) => ({
|
|
41
|
+
const entry = (r) => ({
|
|
42
|
+
taskId: r.taskId,
|
|
43
|
+
order: r.order,
|
|
44
|
+
title: r.title,
|
|
45
|
+
...r.repairedFiles?.length ? { repairedFiles: r.repairedFiles } : {}
|
|
46
|
+
});
|
|
35
47
|
return {
|
|
36
48
|
repos: run.repos.map((repo) => ({
|
|
37
49
|
path: repo.path,
|
|
@@ -83,8 +95,9 @@ export {
|
|
|
83
95
|
layoutOf,
|
|
84
96
|
integrationBranchNameOf,
|
|
85
97
|
taskIsolationOf,
|
|
98
|
+
capConflictFiles,
|
|
86
99
|
handoffOf,
|
|
87
100
|
migratePlanIsolation,
|
|
88
101
|
migratePlanStateIsolation
|
|
89
102
|
};
|
|
90
|
-
//# sourceMappingURL=chunk-
|
|
103
|
+
//# sourceMappingURL=chunk-T2S5O36I.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/isolationRecord.ts"],"sourcesContent":["import * as path from 'path';\nimport type {\n IsolationHandoff,\n IsolationLandedTask,\n IsolationRepo,\n IsolationRun,\n IsolationTaskRecord,\n IsolationTaskStatus,\n PlanIsolation,\n RepoGroupLayout,\n TaskIsolation,\n} from '../interfaces/IWorktreeIsolation';\n\n/** The path of the repo in a workspace that is itself the repository. */\nexport const SELF_REPO = '.';\n\nexport function integrationBranchFor(runId: string): string {\n return `ordewell/${runId}/integration`;\n}\n\nexport function repoRootOf(workspaceRoot: string, repoPath: string): string {\n return path.join(workspaceRoot, repoPath);\n}\n\n/** The group a run isolates, as the planner is told it. */\nexport function layoutOf(run: IsolationRun): RepoGroupLayout {\n return { repos: run.repos.map((r) => r.path), shared: [...run.shared] };\n}\n\n/** The run's integration branch for a one-line notice: every repo's has the same name. */\nexport function integrationBranchNameOf(run: IsolationRun): string {\n return [...new Set(run.repos.map((r) => r.integrationBranch))].join(', ');\n}\n\nconst ISOLATION_STATE: Record<IsolationTaskStatus, Exclude<TaskIsolation['state'], 'none'>> = {\n active: 'active',\n merged: 'integrated',\n conflict: 'conflict',\n repairing: 'repairing',\n kept: 'kept',\n failed: 'kept',\n};\n\n/** `repairLimit` is `conflictRepairAttempts` as it stands now, which is what the next repair will be held to. */\nexport function taskIsolationOf(record: IsolationTaskRecord, repairLimit: number): TaskIsolation {\n return {\n state: ISOLATION_STATE[record.status],\n branch: record.branch,\n worktree: record.workspace,\n repos: Object.entries(record.repos).filter(([, r]) => r.changed).map(([repoPath]) => repoPath),\n ...(record.conflictRepo ? { conflictRepo: record.conflictRepo } : {}),\n ...(record.conflictFiles?.length ? { conflictFiles: record.conflictFiles } : {}),\n ...(record.repairs ? { repair: { attempt: record.repairs, limit: repairLimit } } : {}),\n ...(record.repairedFiles?.length ? { repairedFiles: record.repairedFiles } : {}),\n };\n}\n\n/** A conflict's files as one surface shows them: every one, up to `max`, then how many more. */\nexport function capConflictFiles(files: string[], max = 5): string {\n return files.length <= max ? files.join(', ') : `${files.slice(0, max).join(', ')}, +${files.length - max} more`;\n}\n\n/** What a run hands over: each repo's integration branch and base, and what landed, in plan order. */\nexport function handoffOf(run: IsolationRun): IsolationHandoff {\n const merged = Object.values(run.tasks)\n .filter((r) => r.status === 'merged')\n .sort((a, b) => a.order - b.order);\n const entry = (r: IsolationTaskRecord): IsolationLandedTask => ({\n taskId: r.taskId, order: r.order, title: r.title,\n ...(r.repairedFiles?.length ? { repairedFiles: r.repairedFiles } : {}),\n });\n return {\n repos: run.repos.map((repo) => ({\n path: repo.path,\n integrationBranch: repo.integrationBranch,\n baseRef: repo.baseRef,\n landed: merged.filter((r) => r.repos[repo.path]?.changed).map(entry),\n })),\n landed: merged.map(entry),\n };\n}\n\n/** A task record as ADR-0013 persisted it, for one repository. */\nexport interface Adr0013TaskRecord {\n taskId: string;\n order: number;\n title: string;\n branch: string;\n worktree: string;\n status: IsolationTaskStatus;\n linked: string[];\n}\n\n/** A run as ADR-0013 persisted it (0.4.23): one repository, its refs on the run itself. */\nexport interface Adr0013IsolationRun {\n id: string;\n workspaceRoot: string;\n baseRef: string;\n baseBranch?: string;\n integrationBranch: string;\n tasks: Record<string, Adr0013TaskRecord>;\n}\n\nexport interface Adr0013PlanIsolation {\n run: Adr0013IsolationRun;\n resolvers: Record<string, string>;\n}\n\nfunction isAdr0013(run: IsolationRun | Adr0013IsolationRun): run is Adr0013IsolationRun {\n return 'integrationBranch' in run && typeof run.integrationBranch === 'string';\n}\n\nfunction fromAdr0013Task(r: Adr0013TaskRecord): IsolationTaskRecord {\n return {\n taskId: r.taskId,\n order: r.order,\n title: r.title,\n branch: r.branch,\n workspace: r.worktree,\n status: r.status,\n // A merged task's branch was merged into the one repo there was; what it\n // changed was never recorded, and landing is what `changed` stands for.\n repos: { [SELF_REPO]: { worktree: r.worktree, linked: r.linked ?? [], ...(r.status === 'merged' ? { changed: true } : {}) } },\n ...(r.status === 'conflict' ? { conflictRepo: SELF_REPO } : {}),\n };\n}\n\n/**\n * A persisted plan isolation in today's shape. A run saved in the ADR-0013\n * format — recognised by its own `integrationBranch` — becomes a group of one\n * at `.`, keeping its branches, so a session saved by 0.4.23 resumes and hands\n * off exactly as it would have.\n */\nexport function migratePlanIsolation(state: PlanIsolation | Adr0013PlanIsolation): PlanIsolation {\n const { run, resolvers } = state;\n if (!isAdr0013(run)) return { run, resolvers: resolvers ?? {} };\n const repo: IsolationRepo = {\n path: SELF_REPO,\n root: repoRootOf(run.workspaceRoot, SELF_REPO),\n baseRef: run.baseRef,\n ...(run.baseBranch ? { baseBranch: run.baseBranch } : {}),\n integrationBranch: run.integrationBranch,\n };\n const tasks = Object.fromEntries(Object.entries(run.tasks ?? {}).map(([id, r]) => [id, fromAdr0013Task(r)]));\n return { run: { id: run.id, workspaceRoot: run.workspaceRoot, repos: [repo], shared: [], sharedRepos: [], tasks }, resolvers: resolvers ?? {} };\n}\n\n/** Bring a loaded plan's isolation record, if any, to today's shape in place. */\nexport function migratePlanStateIsolation(plan: { isolation?: PlanIsolation | Adr0013PlanIsolation }): void {\n if (plan.isolation?.run) plan.isolation = migratePlanIsolation(plan.isolation);\n}\n"],"mappings":"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","names":[]}
|