Skip to content

Fix delegation link loss across interrupt/resume; type NewTaskTool provider call (#18) - #1270

Closed
easonLiangWorldedtech wants to merge 9 commits into
Zoo-Code-Org:mainfrom
easonLiangWorldedtech:up-8
Closed

Fix delegation link loss across interrupt/resume; type NewTaskTool provider call (#18)#1270
easonLiangWorldedtech wants to merge 9 commits into
Zoo-Code-Org:mainfrom
easonLiangWorldedtech:up-8

Conversation

@easonLiangWorldedtech

Copy link
Copy Markdown
Contributor

Part 8/8 of the task-tree series (builds on parts 1-7). Resuming an interrupted delegated child no longer loses its parent delegation link: reestablishDelegationLinkOnResume restores the legal active->delegated transition after markDelegatedChildInterrupted, skipping cancelled children and never clobbering a live other-child delegation. Also types the NewTaskTool provider call (removes the as-any cast).

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d61b0042-3137-4544-b737-b8db7eb5c1b3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

easonliang28 and others added 9 commits August 17, 2026 09:29
Part 1/8 of the task-tree series (upstream-ready recomposition).

Adds `depth` to HistoryItem and a cycle-safe `backfillTaskDepth()` that
propagates parent depth through the delegation tree, so every task knows its
nesting level. Depth is surfaced for later use by settings validation,
environment details, and history-tree display.

Includes the single-open-invariant spec mock for backfillTaskDepth (folded in
from the series' CI fix) so this PR passes unit tests standalone.
…ound-trip

Part 2/8 of the task-tree series (upstream-ready recomposition).

Adds two global settings that control subtask delegation:

- `maxNestingDepth` (default 2, range 0-5): how many levels a subtask may
  nest. A value of 0 disables delegation entirely — every new_task runs inline.
- `autoFlattenOnLimit` (default true): when the limit is reached, flatten the
  subtask into the current conversation instead of opening a new tab; when
  disabled such requests are rejected so you can continue directly.

Full round trip: global-settings schema + defaults, ExtensionState,
SettingsView control bound to cachedState with save payload, webviewMessageHandler
persistence through ContextProxy, ClineProvider getState/getStateToPostToWebview,
runtime consumers using the shared defaults. Includes focused tests for UI
binding/save, persistence, and the saved value returned to the webview.

Also completes the taskTree translation keys in all 17 non-English locales so
check-translations passes standalone (folded in from the series' CI fix).
…ached (#12)

Co-authored-by: Eason Liang <easonliang28@gmail.com>
Adds a three-level new_task chain e2e (root -> child -> depth-2 task) where the
depth-2 task's own new_task call exceeds maxNestingDepth and is flattened inline.
Asserts exactly 3 tasks exist, the flattened work completes in the depth-2 task's
own conversation, parent/child resume correctly, and the task stack never holds a
fourth task. Hand-written aimock fixtures (no API key needed) use unique
FLATTEN_E2E_ markers with predicate matching to avoid cross-suite collisions.
…n history tree (#13)

Co-authored-by: Eason Liang <easonliang28@gmail.com>
…hods (#14)

Co-authored-by: Eason Liang <easonliang28@gmail.com>
Co-authored-by: Eason Liang <easonliang28@gmail.com>
…nners (#17)

* feat(webview): surface inline-subtask transitions as distinct chat banners

* fix(webview): localize inline-subtask banner details and task-tree settings keys

---------

Co-authored-by: Eason Liang <easonliang28@gmail.com>
…ovider call (#18)

## Problem A/C — delegation link lost across interrupt/resume

When a delegated child is interrupted (cancelTask / evictCurrentTask), the parent's
`awaitingChildId` link is preserved only while the parent is still `delegated`. After a
crash or resume cycle the parent can be left `active` with no `awaitingChildId`, so when
the user resumes the child, AttemptCompletionTool refuses to route its completion back
(it requires `parent.awaitingChildId === this child`). The result: a resumed subtask's
result is silently stranded and never reported to the parent.

Fix: re-establish the link in `createTaskWithHistoryItem` (the common funnel for every
resume path) when resuming an *interrupted* child. New private helper
`reestablishDelegationLinkOnResume` transitions a demoted `active` parent back to
`delegated`, gated so it:
  - skips children whose delegation was intentionally severed (`cancelledDelegationChildIds`),
  - never clobbers a live delegation to a different child,
  - only performs the legal `active -> delegated` transition.
Non-fatal: any failure is logged and the resume proceeds without the link. Because
AttemptCompletionTool already accepts an `active` parent whose `awaitingChildId` matches,
routing (Problem C) works automatically once the link is restored.

## Problem D — remove `as any` in NewTaskTool

`task.providerRef` is a `WeakRef<ClineProvider>`, so after the null-check `provider` is
already typed `ClineProvider`. The `(provider as any).delegateParentAndOpenChild(...)`
cast was unnecessary; it is now a typed method call. This removes the last `as any` in
NewTaskTool.ts, so its stale `no-explicit-any` suppression entry is dropped from
eslint-suppressions.json (count never increases).

## Tests

Added 4 focused regression tests for `reestablishDelegationLinkOnResume` covering: link
restored on resume of an interrupted child with a demoted parent; no-op when already
delegated to the same child; never clobbers a live delegation to another child; and no
reattach for intentionally-severed children.

Co-authored-by: Eason Liang <easonliang28@gmail.com>
@easonLiangWorldedtech

Copy link
Copy Markdown
Contributor Author

Closing per the author: this stacked series is being re-verified in a fork sandbox before upstream submission. Will be re-opened as individually reviewed PRs once each branch's CI is confirmed green.

@codecov

codecov Bot commented Aug 17, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants