taskplane 0.24.21 → 0.24.23
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/README.md +1 -1
- package/bin/taskplane.mjs +239 -103
- package/extensions/task-runner.ts +2 -110
- package/extensions/taskplane/agent-bridge-extension.ts +196 -3
- package/extensions/taskplane/config-loader.ts +306 -269
- package/extensions/taskplane/config-schema.ts +49 -32
- package/extensions/taskplane/engine-worker.ts +4 -0
- package/extensions/taskplane/engine.ts +884 -12
- package/extensions/taskplane/execution.ts +12 -1
- package/extensions/taskplane/extension.ts +4 -0
- package/extensions/taskplane/lane-runner.ts +5 -0
- package/extensions/taskplane/merge.ts +7 -1
- package/extensions/taskplane/persistence.ts +12 -0
- package/extensions/taskplane/resume.ts +132 -22
- package/extensions/taskplane/settings-tui.ts +149 -172
- package/extensions/taskplane/supervisor.ts +2 -2
- package/extensions/taskplane/types.ts +82 -17
- package/package.json +1 -1
|
@@ -62,8 +62,13 @@ export interface OrchestratorConfig {
|
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
/**
|
|
66
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Stable segment identifier.
|
|
67
|
+
*
|
|
68
|
+
* SegmentId is opaque — never parse by string-splitting.
|
|
69
|
+
* Use structured node/record fields (`repoId`, `taskId`) instead.
|
|
70
|
+
*/
|
|
71
|
+
export type SegmentId = `${string}::${string}` | `${string}::${string}::${number}`;
|
|
67
72
|
|
|
68
73
|
/** How an intra-task segment edge was produced (for observability/debugging). */
|
|
69
74
|
export type SegmentEdgeProvenance = "explicit" | "inferred";
|
|
@@ -122,11 +127,31 @@ export interface ParsedTask {
|
|
|
122
127
|
activeSegmentId?: string | null;
|
|
123
128
|
}
|
|
124
129
|
|
|
125
|
-
/** Build a stable segment ID from task + repo identity (`<taskId>::<repoId
|
|
126
|
-
export function buildSegmentId(taskId: string, repoId: string): SegmentId {
|
|
130
|
+
/** Build a stable segment ID from task + repo identity (`<taskId>::<repoId>[::N]`). */
|
|
131
|
+
export function buildSegmentId(taskId: string, repoId: string, sequence?: number): SegmentId {
|
|
132
|
+
if (typeof sequence === "number" && Number.isFinite(sequence) && sequence >= 2) {
|
|
133
|
+
return `${taskId}::${repoId}::${Math.floor(sequence)}` as SegmentId;
|
|
134
|
+
}
|
|
127
135
|
return `${taskId}::${repoId}` as SegmentId;
|
|
128
136
|
}
|
|
129
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Read repoId from structured segment metadata.
|
|
140
|
+
*
|
|
141
|
+
* SegmentId is opaque — never parse it by string-splitting.
|
|
142
|
+
*/
|
|
143
|
+
export function parseSegmentIdRepo(segment: { repoId: string }): string {
|
|
144
|
+
return segment.repoId;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Build a dynamic segment expansion request ID (`exp-{timestamp}-{random5}`). */
|
|
148
|
+
export function buildExpansionRequestId(timestamp = Date.now()): string {
|
|
149
|
+
const ts = Number.isFinite(timestamp) ? Math.floor(timestamp) : Date.now();
|
|
150
|
+
const base = Math.random().toString(36).slice(2).toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
151
|
+
const random5 = (base + "00000").slice(0, 5);
|
|
152
|
+
return `exp-${ts}-${random5}`;
|
|
153
|
+
}
|
|
154
|
+
|
|
130
155
|
/** One repo-scoped segment node for a task. */
|
|
131
156
|
export interface TaskSegmentNode {
|
|
132
157
|
segmentId: SegmentId;
|
|
@@ -167,6 +192,36 @@ export interface TaskSegmentPlan {
|
|
|
167
192
|
mode: "explicit-dag" | "inferred-sequential" | "repo-singleton";
|
|
168
193
|
}
|
|
169
194
|
|
|
195
|
+
/** Directed edge between repos requested in a dynamic segment expansion. */
|
|
196
|
+
export interface SegmentExpansionEdge {
|
|
197
|
+
from: string;
|
|
198
|
+
to: string;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* File IPC payload for worker-initiated dynamic segment expansion requests.
|
|
203
|
+
*
|
|
204
|
+
* Written to: `.pi/mailbox/{batchId}/{agentId}/outbox/segment-expansion-{requestId}.json`
|
|
205
|
+
*/
|
|
206
|
+
export interface SegmentExpansionRequest {
|
|
207
|
+
/** Unique request ID: `exp-{timestamp}-{random5}` */
|
|
208
|
+
requestId: string;
|
|
209
|
+
/** Task ID making the expansion request. */
|
|
210
|
+
taskId: string;
|
|
211
|
+
/** Segment active when the request was emitted. */
|
|
212
|
+
fromSegmentId: SegmentId;
|
|
213
|
+
/** Repo IDs the worker is requesting the engine to add. */
|
|
214
|
+
requestedRepoIds: string[];
|
|
215
|
+
/** Human rationale from the worker. */
|
|
216
|
+
rationale: string;
|
|
217
|
+
/** Placement directive for inserting new segments. */
|
|
218
|
+
placement: "after-current" | "end";
|
|
219
|
+
/** Optional inter-request ordering edges. */
|
|
220
|
+
edges: SegmentExpansionEdge[];
|
|
221
|
+
/** Epoch milliseconds when the request was emitted. */
|
|
222
|
+
timestamp: number;
|
|
223
|
+
}
|
|
224
|
+
|
|
170
225
|
/**
|
|
171
226
|
* TaskId-keyed segment plans.
|
|
172
227
|
* Iteration order must be deterministic: sort task IDs lexicographically.
|
|
@@ -282,7 +337,7 @@ export const DEFAULT_ORCHESTRATOR_CONFIG: OrchestratorConfig = {
|
|
|
282
337
|
merge: {
|
|
283
338
|
model: "",
|
|
284
339
|
tools: "read,write,edit,bash,grep,find,ls",
|
|
285
|
-
thinking: "",
|
|
340
|
+
thinking: "off",
|
|
286
341
|
verify: [],
|
|
287
342
|
order: "fewest-files-first",
|
|
288
343
|
timeout_minutes: 90,
|
|
@@ -1934,17 +1989,27 @@ export type EngineEventCallback = (event: EngineEvent) => void;
|
|
|
1934
1989
|
* Alert category for supervisor notifications.
|
|
1935
1990
|
*
|
|
1936
1991
|
* Matches the alert categories in the autonomous supervisor spec:
|
|
1937
|
-
* - `task-failure`:
|
|
1938
|
-
* - `merge-failure`:
|
|
1939
|
-
* - `batch-complete`:
|
|
1940
|
-
* - `agent-message`:
|
|
1992
|
+
* - `task-failure`: A task failed after deterministic recovery was exhausted
|
|
1993
|
+
* - `merge-failure`: Wave merge failed and batch paused
|
|
1994
|
+
* - `batch-complete`: Batch finished (all waves done)
|
|
1995
|
+
* - `agent-message`: Runtime mailbox reply/escalation from a running agent
|
|
1996
|
+
* - `segment-expansion-requested`: Worker requested dynamic segment expansion
|
|
1997
|
+
* - `segment-expansion-approved`: Engine approved an expansion request
|
|
1998
|
+
* - `segment-expansion-rejected`: Engine rejected/discarded an expansion request
|
|
1941
1999
|
*
|
|
1942
2000
|
* Note: `stall` detection is deferred to a future phase (requires
|
|
1943
2001
|
* last-activity tracking not yet built).
|
|
1944
2002
|
*
|
|
1945
2003
|
* @since TP-076
|
|
1946
2004
|
*/
|
|
1947
|
-
export type SupervisorAlertCategory =
|
|
2005
|
+
export type SupervisorAlertCategory =
|
|
2006
|
+
| "task-failure"
|
|
2007
|
+
| "merge-failure"
|
|
2008
|
+
| "batch-complete"
|
|
2009
|
+
| "agent-message"
|
|
2010
|
+
| "segment-expansion-requested"
|
|
2011
|
+
| "segment-expansion-approved"
|
|
2012
|
+
| "segment-expansion-rejected";
|
|
1948
2013
|
|
|
1949
2014
|
/**
|
|
1950
2015
|
* Structured context payload for supervisor alerts.
|
|
@@ -1993,6 +2058,8 @@ export interface SupervisorAlertContext {
|
|
|
1993
2058
|
agentId?: string;
|
|
1994
2059
|
/** Mailbox message ID (for agent-message alerts) */
|
|
1995
2060
|
messageId?: string;
|
|
2061
|
+
/** Segment expansion request ID (for segment-expansion alerts) */
|
|
2062
|
+
expansionRequestId?: string;
|
|
1996
2063
|
/** Whether partial progress was preserved (for task-failure alerts) */
|
|
1997
2064
|
partialProgress?: boolean;
|
|
1998
2065
|
/** Batch progress summary */
|
|
@@ -2070,12 +2137,6 @@ export function buildBatchProgressSnapshot(
|
|
|
2070
2137
|
};
|
|
2071
2138
|
}
|
|
2072
2139
|
|
|
2073
|
-
function repoIdFromSegmentId(segmentId: string): string {
|
|
2074
|
-
const idx = segmentId.indexOf("::");
|
|
2075
|
-
if (idx <= 0 || idx >= segmentId.length - 2) return "unknown";
|
|
2076
|
-
return segmentId.slice(idx + 2);
|
|
2077
|
-
}
|
|
2078
|
-
|
|
2079
2140
|
/**
|
|
2080
2141
|
* Build a task-level segment frontier snapshot for supervisor failure alerts.
|
|
2081
2142
|
*
|
|
@@ -2112,7 +2173,7 @@ export function buildSupervisorSegmentFrontierSnapshot(
|
|
|
2112
2173
|
?? (resolvedActiveSegmentId === segmentId ? "running" : "pending");
|
|
2113
2174
|
return {
|
|
2114
2175
|
segmentId,
|
|
2115
|
-
repoId: persisted
|
|
2176
|
+
repoId: persisted ? parseSegmentIdRepo(persisted) : "unknown",
|
|
2116
2177
|
status,
|
|
2117
2178
|
dependsOnSegmentIds: persisted?.dependsOnSegmentIds ?? [],
|
|
2118
2179
|
};
|
|
@@ -2692,6 +2753,10 @@ export interface PersistedSegmentRecord {
|
|
|
2692
2753
|
exitDiagnostic?: TaskExitDiagnostic;
|
|
2693
2754
|
/** Human-readable exit reason (legacy compat, same as task-level) */
|
|
2694
2755
|
exitReason: string;
|
|
2756
|
+
/** Anchor segment ID this segment was dynamically expanded from (if any). */
|
|
2757
|
+
expandedFrom?: string;
|
|
2758
|
+
/** Segment expansion request ID that created this segment (if any). */
|
|
2759
|
+
expansionRequestId?: string;
|
|
2695
2760
|
}
|
|
2696
2761
|
|
|
2697
2762
|
/**
|