Skip to content

perf: speed up large session forks - #11075

Merged
marius-kilocode merged 4 commits into
mainfrom
canyon-stage
Jun 11, 2026
Merged

perf: speed up large session forks#11075
marius-kilocode merged 4 commits into
mainfrom
canyon-stage

Conversation

@marius-kilocode

@marius-kilocode marius-kilocode commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Problem

Forking a session previously copied every referenced subagent session recursively. A large parent could therefore expand into hundreds of child sessions and tens of thousands of message and part writes before Agent Manager could open the new tab. In the profiled case, the visible parent referenced 194 child sessions and took 12.66 seconds to fork.

The fork does not need those child sessions as live execution state. Their completed outcomes are already embedded in the parent task results, and copied children cannot continue running work from the source session.

Behavior

The fork now copies only the parent transcript. Task calls become detached historical results:

  • Completed tasks retain their final result for model context and display.
  • Child session IDs and resumable task IDs are removed, including IDs in background-task output.
  • Pending and running tasks become interrupted snapshots in the fork.
  • New task calls from the fork create fresh child sessions.
  • The source session and its child histories remain unchanged.

Completed task cards also start collapsed and hydrate child details only when expanded. Existing source sessions still allow opening their historical child transcripts.

Why This Is Faster

The change removes four sources of work from the fork path:

  1. It no longer recursively clones the complete child-session tree.
  2. It writes the copied parent messages and parts in one immediate transaction instead of one transaction per row.
  3. It avoids publishing thousands of copied-row SSE notifications because the destination transcript is hydrated after the fork response.
  4. It defers completed task-card content so opening the fork does not immediately hydrate every historical child.

For the profiled large session, click-to-tab time dropped from 12.66 seconds to approximately 1.5 seconds.

Product Constraint

A fork no longer contains navigable or resumable copies of historical child sessions. It retains their final outcomes, while detailed child history remains available from the source session. This intentionally treats a fork as a continuation of the parent conversation rather than a duplicate of prior subagent execution state.

Comment thread packages/opencode/src/kilocode/session/fork.ts Outdated
Comment thread packages/opencode/src/kilocode/session/fork.ts
@kilo-code-bot

kilo-code-bot Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 1 Resolved, 1 Suggestion Remaining | Recommendation: Merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

RESOLVED

File Line Issue
packages/opencode/src/kilocode/session/fork.ts 8 WARNING: stale regex missing m flagFixed in commit fd566bbc. The regex now correctly has the m flag: `/^[ \t]*task_id:[^
]*(?:(?:\r?\n){1,2} $)/m`

SUGGESTION

File Line Issue
packages/opencode/src/kilocode/session/fork.ts 29 Effect.runSync calls inside Database.transaction callback — worth a clarifying comment explaining why sync execution is safe here
Other Observations (not blocking)

stale regex is now correct: The new commit (fd566bbc) added the m flag. The regex also correctly handles tab-prefixed lines (the test fixture uses \ttask_id: ...) and both \n and \r\n line endings.

initialOpen dual-call pattern: TaskToolExpanded calls initialOpen({tool, partID, defaultOpen: running()}) to seed its own open signal, and separately passes defaultOpen={running()} to BasicTool, which calls initialOpen again with the same arguments. Both reads return the same persisted value so there is no functional issue, but the redundant read is harmless noise.

taskVisible(open: boolean | undefined, ...) type: The open parameter is typed as boolean | undefined but is always boolean in practice. No issue.

Detached completed tasks get metadata: {}: When state.metadata is undefined on a completed task, the detached copy gets metadata: {} instead of undefined. This is intentional — it strips child-session references — but differs from the original value in the edge case of no metadata.

Test coverage is thorough: The updated session-fork-remap.test.ts covers completed, running, pending, errored, non-task, and workspace-sync sequencing cases. The workspace-sync test verifies the atomic commit behavior with correct event sequence assertions.

Files Reviewed (11 files)
  • .changeset/fast-session-forks.md
  • packages/kilo-ui/src/components/basic-tool.tsx
  • packages/kilo-vscode/tests/unit/task-tool-hydration.test.ts
  • packages/kilo-vscode/webview-ui/src/components/chat/TaskToolExpanded.tsx
  • packages/kilo-vscode/webview-ui/src/components/chat/task-tool-state.ts
  • packages/opencode/src/kilocode/server/httpapi/session-fork.ts
  • packages/opencode/src/kilocode/session/fork.ts — WARNING resolved, 1 suggestion remains
  • packages/opencode/src/kilocode/session/index.ts
  • packages/opencode/src/session/session.ts
  • packages/opencode/test/kilocode/session-fork-remap.test.ts

Fix these issues in Kilo Cloud


Reviewed by claude-4.6-sonnet-20260217 · 758,940 tokens

Review guidance: REVIEW.md from base branch main

@marius-kilocode
marius-kilocode merged commit cdef15c into main Jun 11, 2026
22 checks passed
@marius-kilocode
marius-kilocode deleted the canyon-stage branch June 11, 2026 13:55
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
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