Skip to content

Conversation

@gamesguru
Copy link

@gamesguru gamesguru commented Jan 11, 2026

Drawing inspiration from this issue: #7410

This is a large PR which requires careful and detailed review! I am excited for these improvements, but we need to minimize risks while still making great strides in overall framework improvement. Cheers. I look forward to any feedback and recommendations on improvements or delineating features in separate PRs.

  • fix lag with long chats (recycle DOM elements)
  • marry sexy context menu with "open dev tools" one
  • sync package-lock.json to resolve CI sync errors
  • downgrade @types/node to ^20.0.0 (build was failing)
  • chore: add packages directory to dev_lockfile-sync.sh
  • fix(gui): improve comment whitespace handling in commandExtractor
  • fix(vscode): implement missing deleteFile method in VsCodeIde
  • fix?(vscode): add explicit yaml dependency (build error)
PR Review Guide (Notes from earlier session)

PR Review Guide for Deep Think Session

Executive Summary

This PR introduces significant changes across the stack, most notably a new MultiEdit capability in core, a complete refactor of Chat Scrolling in the GUI, and fundamental updates to the IDE Protocol (supporting file deletion). The UX for the main input (TipTap) and Context Menus (OSR) has also been heavily touched.

1. Ranked Critical Files for Deep Review

  1. core/tools/implementations/multiEdit.ts

    • Why: Introduces a powerful new primitive for applying multiple edits simultaneously.
    • Focus: Error handling, partial failure states, and interaction with executeMultiFindAndReplace.
  2. gui/src/hooks/useChatScroll.ts

    • Why: Chat scrolling is notoriously difficult to get right.
    • Focus: Edge cases: fast streaming, large history, resizing window.
  3. core/util/conversationCompaction.ts

    • Why: Core logic for managing context window.
    • Focus: New sanitization logic and safety.
  4. extensions/vscode/src/apply/ApplyManager.ts

    • Why: Changes file opening/focusing behavior.
    • Focus: The preserveFocus: true change.
  5. gui/src/components/OSRContextMenu.tsx

    • Why: Re-implements native-like behaviors (Undo/Redo/Paste).
    • Focus: Cross-platform compatibility and use of deprecated document.execCommand.
  6. core/protocol/ide.ts & core.ts

    • Why: Adds deleteFile.
    • Focus: Security implications and path validation.

2. Library & Lifecycle Changes

  • New Tool Lifecycle (MultiEdit): Batched edits move complexity to Core.
  • Scrolling Lifecycle (react-virtuoso): Delegating complexity to library; risk to Cmd+F.
  • Clipboard Lifecycle (OSRContextMenu): Potential flakiness due to browser permissions.

3. Testing Strategy

  • Platform: Windows path normalization, Linux environment checks.
  • Accessibility: Ensure OSRContextMenu and Chat Scrolling respect screen readers and keyboard navigation.

4. Recommendations for Evolution

  1. Security Audit on File Deletion
  2. Deprecate execCommand
  3. Sanitization Validation

Continue Tasks

Status Task Actions
▶️ Queued changelog View
▶️ Queued test coverage View
▶️ Queued Review Agent View
▶️ Queued test View

Powered by Continue


Summary by cubic

Switches chat rendering to react-virtuoso to eliminate lag in long conversations and keep Ctrl/Cmd+F reliable. Unifies the custom context menu with the dev-tools menu, introduces MultiEdit, and adds IDE-level file deletion.

  • New Features

    • Virtualized chat via react-virtuoso (DOM recycling, initial scroll to bottom, stable follow-output).
    • Find-in-chat works with virtualization; highlights and navigates matches per message.
    • Context menu merged (OSR + native-like actions).
    • New MultiEdit tool for batched edits.
    • IDE protocol adds deleteFile; implemented in core and VS Code; APIs for deleting workspace blocks and global rules.
    • VS Code ApplyManager opens files with preserveFocus to avoid stealing focus.
    • Developer scripts: local CI simulation, lockfile sync, and local build scripts for VS Code and JetBrains.
  • Bug Fixes

    • Ctrl/Cmd+F works on Linux/Windows and with virtualized chat.
    • Cross-platform cut/copy/paste and undo/redo without execCommand; stable TipTap placeholder and non-destructive clearContent.
    • Improved shell command extraction (comment/whitespace and continuations).
    • Conversation compaction: bounds checks and message sanitization to avoid validation errors.
    • History saving ensures workspaceDirectory is set.
    • Terminal kill timeout unref to prevent hanging tests; opened-files LRU increased to 50.
    • VS Code: implemented deleteFile; switched to stringifyConfigYaml from config-yaml to remove direct yaml dependency.
    • Test stability: mocked sqlite/posthog; Mistral API key detection bypass in tests; updated Jest setup.

Written for commit 6ad80f5. Summary will update on new commits.

    fix Ctrl+F (find) on Linux/Windows and, separately, w/ recycled DOM

    always show chat scrollbar
    make Ctrl+F work with Virtuoso
    Ctrl+Z (undo context menu). partially simualte CI script

    resume chats at bottom, not top
    useEffect to scroll to bottom of chat on initial load
    optimize: `useMemo` and `computeItemKey`

    add build-jetbrains and build-vscode scripts for local testing

    Cache filtered history so array only re-renders if history changes.
    Tell Virtuoso what is message.id, to avoid race condition/re-render.

    fix open handle issue in Jest after quitting

    rules & context menu additions & fixes
@continue
Copy link
Contributor

continue bot commented Jan 11, 2026

All Green - Keep your PRs mergeable

Learn more

All Green is an AI agent that automatically:

✅ Addresses code review comments

✅ Fixes failing CI checks

✅ Resolves merge conflicts


Unsubscribe from All Green comments

1 similar comment
@continue-staging
Copy link

All Green - Keep your PRs mergeable

Learn more

All Green is an AI agent that automatically:

✅ Addresses code review comments

✅ Fixes failing CI checks

✅ Resolves merge conflicts


Unsubscribe from All Green comments

@continue-development-app
Copy link

All Green - Keep your PRs mergeable

Learn more

All Green is an AI agent that automatically:

✅ Addresses code review comments

✅ Fixes failing CI checks

✅ Resolves merge conflicts


Unsubscribe from All Green comments

@github-actions
Copy link

github-actions bot commented Jan 11, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@gamesguru gamesguru marked this pull request as ready for review January 11, 2026 21:35
@gamesguru gamesguru requested a review from a team as a code owner January 11, 2026 21:35
@gamesguru gamesguru requested review from Patrick-Erichsen and removed request for a team January 11, 2026 21:35
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jan 11, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

14 issues found across 64 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="gui/src/components/mainInput/util/handleMetaKeyIssues.ts">

<violation number="1" location="gui/src/components/mainInput/util/handleMetaKeyIssues.ts:58">
P1: VSCode .ipynb meta key workaround was removed: handlers map is empty so cut/copy/paste/undo/redo logic no longer runs, causing regression.</violation>
</file>

<file name="gui/src/hooks/ParallelListeners.tsx">

<violation number="1" location="gui/src/hooks/ParallelListeners.tsx:99">
P2: HasReasoningEnabled not updated when reasoning capability changes without model title change, leaving stale state</violation>
</file>

<file name="scripts/dev_build-jetbrains-local.sh">

<violation number="1" location="scripts/dev_build-jetbrains-local.sh:70">
P2: Unsanitized git describe output can include slashes, producing nested paths for the build artifact and causing mv to fail or place the file in an unintended subdirectory.</violation>
</file>

<file name="core/util/conversationCompaction.ts">

<violation number="1" location="core/util/conversationCompaction.ts:27">
P1: Bounds check ignores negative index; accessing historyUpToIndex[index] can crash with TypeError</violation>
</file>

<file name="gui/src/context/IdeMessenger.tsx">

<violation number="1" location="gui/src/context/IdeMessenger.tsx:91">
P1: Silent return when postIntellijMessage is undefined makes JetBrains requests hang (no retry, unresolved Promises/listeners).</violation>
</file>

<file name="core/util/filesystem.ts">

<violation number="1" location="core/util/filesystem.ts:214">
P2: Promise resolver calls resolve even after rejecting on error, creating a double-settlement pattern and masking failures</violation>
</file>

<file name="gui/src/redux/store.ts">

<violation number="1" location="gui/src/redux/store.ts:129">
P2: redux-logger is unconditionally enabled (with diff:true), adding heavy logging and state diffs to all builds instead of being limited to development.</violation>
</file>

<file name="scripts/dev_simulate-ci.sh">

<violation number="1" location="scripts/dev_simulate-ci.sh:2">
P2: Merge-conflict check can produce false negatives because pipeline ignores git merge-tree failures without pipefail.</violation>
</file>

<file name="gui/src/components/StyledMarkdownPreview/index.tsx">

<violation number="1" location="gui/src/components/StyledMarkdownPreview/index.tsx:279">
P2: Counters for codeblocks/search matches persist across parses, causing drifting indices and incorrect active-match highlighting on re-renders.</violation>

<violation number="2" location="gui/src/components/StyledMarkdownPreview/index.tsx:293">
P2: Search highlighting wraps inline code text in <mark>, turning code children into elements and breaking symbol/file autolinking that expects a plain string.</violation>
</file>

<file name="gui/src/pages/gui/Chat.tsx">

<violation number="1" location="gui/src/pages/gui/Chat.tsx:173">
P2: Search navigation uses indices from the unfiltered history while the virtualized list renders `filteredHistory`, so matches after tool entries scroll to the wrong item.</violation>
</file>

<file name="gui/src/components/OSRContextMenu.tsx">

<violation number="1" location="gui/src/components/OSRContextMenu.tsx:183">
P1: Rule context menu is triggered on any mousedown and ruleContext isn’t cleared when closing via outside click/leave, so stale ruleContext can make Edit/Delete operate on the wrong rule and left-clicks open the menu unintentionally.</violation>

<violation number="2" location="gui/src/components/OSRContextMenu.tsx:228">
P2: Context menu is globally suppressed even when OSR is disabled or on macOS, causing native menu loss (ctrl+click yields no menu)</violation>

<violation number="3" location="gui/src/components/OSRContextMenu.tsx:278">
P2: Paste uses document.activeElement instead of the right-clicked editable element, so paste can go to a different control when focus doesn’t change on right-click.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

… promise settlement, logger, pipefail, markdown preview, chat nav, OSR suppression)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 11 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="gui/src/context/IdeMessenger.tsx">

<violation number="1" location="gui/src/context/IdeMessenger.tsx:86">
P2: Loss of message context in JetBrains send failures: thrown error and retry logs omit messageType/data, removing prior diagnostics.</violation>
</file>

<file name="gui/src/components/StyledMarkdownPreview/index.tsx">

<violation number="1" location="gui/src/components/StyledMarkdownPreview/index.tsx:296">
P2: Skipping <code> text nodes causes search highlight/localMatchIndex to desync from FindWidget’s raw-text indexing; inline code matches are unhighlighted and active match selection can be wrong.</violation>
</file>

<file name="gui/src/redux/store.ts">

<violation number="1" location="gui/src/redux/store.ts:129">
P2: `redux-logger` is still imported/instantiated unconditionally, so prod builds still include and run it even though the middleware is gated to DEV.</violation>
</file>

<file name="gui/src/components/OSRContextMenu.tsx">

<violation number="1" location="gui/src/components/OSRContextMenu.tsx:173">
P2: Rule context menu is opened on any mousedown (including left-click) and reuses stale clipboard state/target because the rule menu block is not gated by event.button, leading to unexpected menu opens and paste acting on the previous target.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.


visit(tree, "text", (node: any, index: any, parent: any) => {
if (!node.value || !parent) return;
if (parent.tagName === "code") return;
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Skipping text nodes causes search highlight/localMatchIndex to desync from FindWidget’s raw-text indexing; inline code matches are unhighlighted and active match selection can be wrong.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At gui/src/components/StyledMarkdownPreview/index.tsx, line 296:

<comment>Skipping <code> text nodes causes search highlight/localMatchIndex to desync from FindWidget’s raw-text indexing; inline code matches are unhighlighted and active match selection can be wrong.</comment>

<file context>
@@ -292,6 +293,7 @@ const StyledMarkdownPreview = memo(function StyledMarkdownPreview(
 
           visit(tree, "text", (node: any, index: any, parent: any) => {
             if (!node.value || !parent) return;
+            if (parent.tagName === "code") return;
 
             // Skip if already inside a mark (to avoid recursion if we had multiple passes, though here it's one pass)
</file context>

✅ Addressed in c946268

@gamesguru
Copy link
Author


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

I have read the CLA Document and I hereby acknowledge full agreement with its terms and sign it accordingly,
gamesguru.

@gamesguru
Copy link
Author

I have read the CLA Document and I hereby sign the CLA

rollback sus yaml dependency added on this PR

bump timeout to 20 seconds for flaky test

Signed-off-by: Shane Jaroch <[email protected]>
@gamesguru gamesguru changed the title Virtuoso for long laggy chats, ContextMenu & key bindings, execCommand fixes refactor,feat(gui,core) Virtuoso for long laggy chats, ContextMenu & key bindings, execCommand fix Jan 12, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 12 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="gui/src/components/StyledMarkdownPreview/index.test.tsx">

<violation number="1" location="gui/src/components/StyledMarkdownPreview/index.test.tsx:32">
P2: FilenameLink mock forces a <mark>, so highlighting tests always pass and cannot catch regressions.</violation>
</file>

<file name="gui/src/components/StyledMarkdownPreview/index.tsx">

<violation number="1" location="gui/src/components/StyledMarkdownPreview/index.tsx:296">
P2: Search highlighting now wraps mermaid code contents in <mark>, causing String(codeProps.children) to become "[object Object]" and break mermaid rendering when the search term matches inside a mermaid block.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

add test for focus stealing, modify node fetch accordingly.

add FocusTest for JetBrains impl to match VSCode
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10 issues found across 30 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="gui/src/pages/gui/Chat.test.tsx">

<violation number="1" location="gui/src/pages/gui/Chat.test.tsx:25">
P2: Test incorrectly expects Virtuoso to be called with two args; React function components receive only props, causing the assertion to fail.</violation>
</file>

<file name="packages/fetch/src/node-fetch-patch.js">

<violation number="1" location="packages/fetch/src/node-fetch-patch.js:108">
P1: Abort now destroys response body without emitting AbortError, so aborted reads can hang or never reject once the Response is resolved.</violation>
</file>

<file name="extensions/intellij/src/testIntegration/kotlin/com/github/continuedev/continueintellijextension/FocusTest.kt">

<violation number="1" location="extensions/intellij/src/testIntegration/kotlin/com/github/continuedev/continueintellijextension/FocusTest.kt:73">
P2: UI integration test is a no-op: only `assertTrue(true)` so it always passes despite running expensive UI steps, providing false signal and potential flakiness</violation>
</file>

<file name="core/protocol/ide.ts">

<violation number="1" location="core/protocol/ide.ts:30">
P2: `openFile` protocol added `preserveFocus`, but dispatcher ignores the option, dropping the new parameter</violation>
</file>

<file name="gui/src/components/StyledMarkdownPreview/index.test.tsx">

<violation number="1" location="gui/src/components/StyledMarkdownPreview/index.test.tsx:178">
P2: Test mutates HTMLElement.prototype.scrollIntoView without restoring it, leaking the mock into later tests.</violation>
</file>

<file name="extensions/vscode/e2e/tests/KeyboardShortcuts.test.ts">

<violation number="1" location="extensions/vscode/e2e/tests/KeyboardShortcuts.test.ts:182">
P2: Test closes all editors, invalidating `editor` used in afterEach and causing teardown flakiness</violation>
</file>

<file name="gui/src/components/find/FindWidget.test.tsx">

<violation number="1" location="gui/src/components/find/FindWidget.test.tsx:40">
P2: ResizeObserver mock overwrites global without being restored, leaking into other tests</violation>
</file>

<file name="gui/src/components/OSRContextMenu.test.tsx">

<violation number="1" location="gui/src/components/OSRContextMenu.test.tsx:169">
P2: document.createRange is overwritten in the test and never restored, so later tests run with a mocked global and can become order-dependent/flaky.</violation>
</file>

<file name="gui/src/components/find/FindWidget.tsx">

<violation number="1" location="gui/src/components/find/FindWidget.tsx:161">
P2: Yield timing never resets, causing a 0ms delay on nearly every iteration after 10ms and drastically slowing large searches.</violation>

<violation number="2" location="gui/src/components/find/FindWidget.tsx:203">
P2: Async search not cancelled on close/disable/unmount can update state/scroll after widget is closed</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.


response.body.emit("error", error);
// response.body.emit("error", error);
response.body.destroy();
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Abort now destroys response body without emitting AbortError, so aborted reads can hang or never reject once the Response is resolved.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/fetch/src/node-fetch-patch.js, line 108:

<comment>Abort now destroys response body without emitting AbortError, so aborted reads can hang or never reject once the Response is resolved.</comment>

<file context>
@@ -97,14 +97,15 @@ export default async function fetch(url, options_) {
 
-      response.body.emit("error", error);
+      // response.body.emit("error", error);
+      response.body.destroy();
     };
 
</file context>
Suggested change
response.body.destroy();
response.body.destroy(error);
Fix with Cubic

overscan: 200,
atBottomThreshold: 50,
}),
expect.anything(),
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Test incorrectly expects Virtuoso to be called with two args; React function components receive only props, causing the assertion to fail.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At gui/src/pages/gui/Chat.test.tsx, line 25:

<comment>Test incorrectly expects Virtuoso to be called with two args; React function components receive only props, causing the assertion to fail.</comment>

<file context>
@@ -0,0 +1,28 @@
+        overscan: 200,
+        atBottomThreshold: 50,
+      }),
+      expect.anything(),
+    );
+  });
</file context>
Fix with Cubic

}

// Placeholder assertion to ensure test structure is valid
assertTrue(true, "Focus test structure created")
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: UI integration test is a no-op: only assertTrue(true) so it always passes despite running expensive UI steps, providing false signal and potential flakiness

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At extensions/intellij/src/testIntegration/kotlin/com/github/continuedev/continueintellijextension/FocusTest.kt, line 73:

<comment>UI integration test is a no-op: only `assertTrue(true)` so it always passes despite running expensive UI steps, providing false signal and potential flakiness</comment>

<file context>
@@ -0,0 +1,77 @@
+                }
+                
+                // Placeholder assertion to ensure test structure is valid
+                assertTrue(true, "Focus test structure created")
+            }
+        }
</file context>
Fix with Cubic

showVirtualFile: [{ name: string; content: string }, void];
openFile: [{ path: string }, void];
deleteFile: [{ path: string }, void];
openFile: [{ path: string; preserveFocus?: boolean }, void];
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: openFile protocol added preserveFocus, but dispatcher ignores the option, dropping the new parameter

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At core/protocol/ide.ts, line 30:

<comment>`openFile` protocol added `preserveFocus`, but dispatcher ignores the option, dropping the new parameter</comment>

<file context>
@@ -27,7 +27,7 @@ export type ToIdeFromWebviewOrCoreProtocol = {
   showVirtualFile: [{ name: string; content: string }, void];
   deleteFile: [{ path: string }, void];
-  openFile: [{ path: string }, void];
+  openFile: [{ path: string; preserveFocus?: boolean }, void];
   openUrl: [string, void];
   runCommand: [{ command: string; options?: TerminalOptions }, void];
</file context>
Fix with Cubic

Comment on lines +178 to +188
window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;

renderComponent("text match", {}, "match", {
messageIndex: 0,
matchIndexInMessage: 0,
});

await waitFor(() => {
const mark = document.querySelector("mark");
expect(mark).toBeInTheDocument();
expect(mark).toHaveClass("active");
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Test mutates HTMLElement.prototype.scrollIntoView without restoring it, leaking the mock into later tests.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At gui/src/components/StyledMarkdownPreview/index.test.tsx, line 178:

<comment>Test mutates HTMLElement.prototype.scrollIntoView without restoring it, leaking the mock into later tests.</comment>

<file context>
@@ -168,3 +172,20 @@ file.ts
+
+it("should scroll to active search match", async () => {
+  const scrollIntoViewMock = vi.fn();
+  window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
+
+  renderComponent("text match", {}, "match", {
</file context>
Suggested change
window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
renderComponent("text match", {}, "match", {
messageIndex: 0,
matchIndexInMessage: 0,
});
await waitFor(() => {
const mark = document.querySelector("mark");
expect(mark).toBeInTheDocument();
expect(mark).toHaveClass("active");
const originalScrollIntoView = window.HTMLElement.prototype.scrollIntoView;
window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
try {
renderComponent("text match", {}, "match", {
messageIndex: 0,
matchIndexInMessage: 0,
});
await waitFor(() => {
const mark = document.querySelector("mark");
expect(mark).toBeInTheDocument();
expect(mark).toHaveClass("active");
expect(scrollIntoViewMock).toHaveBeenCalled();
});
} finally {
window.HTMLElement.prototype.scrollIntoView = originalScrollIntoView;
}
});
Fix with Cubic

expect(textInputHtml).to.equal(activeElementHtml);

// Cleanup: close the new file
await new EditorView().closeAllEditors();
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Test closes all editors, invalidating editor used in afterEach and causing teardown flakiness

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At extensions/vscode/e2e/tests/KeyboardShortcuts.test.ts, line 182:

<comment>Test closes all editors, invalidating `editor` used in afterEach and causing teardown flakiness</comment>

<file context>
@@ -156,6 +156,32 @@ describe("Keyboard Shortcuts", () => {
+    expect(textInputHtml).to.equal(activeElementHtml);
+
+    // Cleanup: close the new file
+    await new EditorView().closeAllEditors();
+  }).timeout(DEFAULT_TIMEOUT.XL);
+
</file context>
Suggested change
await new EditorView().closeAllEditors();
// Cleanup handled by afterEach; avoid closing the editor here
// await new EditorView().closeAllEditors();
Fix with Cubic

beforeEach(() => {
vi.useFakeTimers();
// Mock ResizeObserver
global.ResizeObserver = class {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: ResizeObserver mock overwrites global without being restored, leaking into other tests

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At gui/src/components/find/FindWidget.test.tsx, line 40:

<comment>ResizeObserver mock overwrites global without being restored, leaking into other tests</comment>

<file context>
@@ -0,0 +1,126 @@
+  beforeEach(() => {
+    vi.useFakeTimers();
+    // Mock ResizeObserver
+    global.ResizeObserver = class {
+      observe() {}
+      unobserve() {}
</file context>
Fix with Cubic

document.body.appendChild(container);

// Mock document.createRange to return our mock
document.createRange = vi.fn().mockReturnValue(mockRange);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: document.createRange is overwritten in the test and never restored, so later tests run with a mocked global and can become order-dependent/flaky.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At gui/src/components/OSRContextMenu.test.tsx, line 169:

<comment>document.createRange is overwritten in the test and never restored, so later tests run with a mocked global and can become order-dependent/flaky.</comment>

<file context>
@@ -0,0 +1,211 @@
+    document.body.appendChild(container);
+
+    // Mock document.createRange to return our mock
+    document.createRange = vi.fn().mockReturnValue(mockRange);
+
+    window.getSelection = vi.fn().mockReturnValue({
</file context>
Fix with Cubic

}

if (abortController.signal.aborted) return;
setMatches(results);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Async search not cancelled on close/disable/unmount can update state/scroll after widget is closed

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At gui/src/components/find/FindWidget.tsx, line 203:

<comment>Async search not cancelled on close/disable/unmount can update state/scroll after widget is closed</comment>

<file context>
@@ -136,74 +137,100 @@ export const useFindWidget = (
 
-    setMatches(results);
+      if (abortController.signal.aborted) return;
+      setMatches(results);
 
-    // Determine scrolling behavior
</file context>
Fix with Cubic

Comment on lines +161 to +168
const start = Date.now();
while (i < history.length) {
if (abortController.signal.aborted) return;

// Yield to main thread every 10ms
if (Date.now() - start > 10) {
await new Promise((resolve) => setTimeout(resolve, 0));
}
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Yield timing never resets, causing a 0ms delay on nearly every iteration after 10ms and drastically slowing large searches.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At gui/src/components/find/FindWidget.tsx, line 161:

<comment>Yield timing never resets, causing a 0ms delay on nearly every iteration after 10ms and drastically slowing large searches.</comment>

<file context>
@@ -136,74 +137,100 @@ export const useFindWidget = (
+    let i = 0;
+
+    const processChunk = async () => {
+      const start = Date.now();
+      while (i < history.length) {
+        if (abortController.signal.aborted) return;
</file context>
Suggested change
const start = Date.now();
while (i < history.length) {
if (abortController.signal.aborted) return;
// Yield to main thread every 10ms
if (Date.now() - start > 10) {
await new Promise((resolve) => setTimeout(resolve, 0));
}
let start = Date.now();
while (i < history.length) {
if (abortController.signal.aborted) return;
// Yield to main thread every 10ms
if (Date.now() - start > 10) {
await new Promise((resolve) => setTimeout(resolve, 0));
start = Date.now();
}
Fix with Cubic

Copy link
Collaborator

@RomneyDa RomneyDa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gamesguru I think all these changes seem

In order to review this we'll need it to be broken up into digestible chunks. A few meta-level things to keep in mind as you're going

  • Revert any file changes that are the result of formatting only, e.g. the first file in Files changed, .github/workflows/continue-agents.yml
  • Revert any package lock changes which are not accompanied by package changes e.g. the second file in Files changed, binary/package-lock.json
  • Do any const change in separate PRs with explanations where possible, e.g. changing MAX_NUM_OPEN_CONTEXT_FILES from 20 to 50
  • Revert various opinionated test, log, etc tweaks which are not directly related to main changes and which make review more difficult
  • The shell scripts seem like they do not change behavior and could be removed
  • Break up the remaining major changes into separate PRs. A few I see include
    • Virtuoso integration - this seems like a really neat change
    • LRU cache changes
    • changes related to deleting workspace blocks
    • compaction and summary changes
    • various memory improvements, disposals and derefs
    • OSR context menu updates
    • And others

Breaking these up would allow us to review and make it easier for you to get tests passing!

@github-project-automation github-project-automation bot moved this from Todo to In Progress in Issues and PRs Jan 13, 2026
@RomneyDa
Copy link
Collaborator

@gamesguru since this will need to be split up into several PRs I'll go ahead and close this one to keep things clean. Please feel free to open new PRs with targeted changes and I'll keep an eye out for them!

@RomneyDa RomneyDa closed this Jan 13, 2026
@github-project-automation github-project-automation bot moved this from In Progress to Done in Issues and PRs Jan 13, 2026
@github-actions github-actions bot locked and limited conversation to collaborators Jan 13, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants