feat(server): improve task CLI with steering, execution order, and planner guidance

- Fix steering notes to check scope task instead of leaf task
- Fix NOT_DONE replan to use scope for bird's eye view
- Pass reason to planner prompt ("Why you were called" section)
- Add execution-order.ts with reusable computeExecutionOrder and buildSortedChildrenMap
- Make 'tree' an alias for 'plan' command
- Add comprehensive help text for run command and acceptance criteria
- Add planner guidance for propagating requirements to subtasks
This commit is contained in:
Mohamed Boudra
2026-01-17 11:46:38 +07:00
parent 420f25f1e9
commit d964415eba
33 changed files with 5205 additions and 3922 deletions
+17 -5
View File
@@ -1228,9 +1228,11 @@ export class DaemonClientV2 {
pendingPermissionIds.add(request.id);
}
}
let sawRunning =
current?.status === "running" ||
pendingPermissionIds.size > 0;
// Track whether we've seen a running state. Important: we only set this
// when we see running IN THE QUEUE, not based on current state. This prevents
// finding old idle states that occurred before the current run started.
let sawRunningInQueue = false;
let queuedIdle: AgentSnapshotPayload | null = null;
const updatePendingPermissions = (msg: SessionOutboundMessage): void => {
@@ -1267,10 +1269,11 @@ export class DaemonClientV2 {
(msg.payload.pendingPermissions?.length ?? 0) > 0 ||
pendingPermissionIds.size > 0;
if (status === "running" || hasPendingPermissions) {
sawRunning = true;
sawRunningInQueue = true;
queuedIdle = null; // Reset: any previous idle was before this run
}
if (
sawRunning &&
sawRunningInQueue &&
(status === "idle" || status === "error") &&
!hasPendingPermissions
) {
@@ -1281,6 +1284,15 @@ export class DaemonClientV2 {
return queuedIdle;
}
// If current state is running (or has pending permissions), we need to wait
// for the next idle. If current is already idle and we didn't see running
// in the queue, this is an edge case - the agent might not have started yet
// or was already idle. Use the current state's running status to seed the waiter.
let sawRunning =
sawRunningInQueue ||
current?.status === "running" ||
pendingPermissionIds.size > 0;
return this.waitFor(
(msg) => {
updatePendingPermissions(msg);