Skip to content

Release: v2.0.2 - #170

Merged
Minitour merged 8 commits into
mainfrom
develop
Aug 4, 2026
Merged

Release: v2.0.2#170
Minitour merged 8 commits into
mainfrom
develop

Conversation

@Minitour

@Minitour Minitour commented Aug 4, 2026

Copy link
Copy Markdown
Member

This pull request introduces several significant improvements and fixes across activity tracking, plugin handling, and workspace path utilities. The main focus is on enhancing activity correlation for the Cursor provider, improving serialization logic for activity attributes, and adding robust test coverage for new and existing features.

Activity correlation and tracking improvements:

  • Added reconcileCursorActivityConversationIds and chatConversationIdFromTranscriptPath in activity-correlation-reconcile.ts to unify conversation_id for Cursor provider activities within the same generation, ensuring accurate grouping of prompts, tools, and stops. Includes comprehensive tests. [1] [2]
  • Updated agent-activity-normalize.ts to properly trace Cursor tool usage at the beforeTool event for dynamic tools (like WebSearch and Glob) that lack a postToolUse event, while avoiding duplicates for tools already covered. Added logic to display inner tool names for wrapped tools. [1] [2] [3]
  • Adjusted buildSystemActivityHooks and related constants in agent-activity.ts to include supplemental events for Cursor, ensuring all relevant hooks are registered. [1] [2]
  • Updated and expanded tests in agent-activity.test.ts to reflect new tracing logic and event handling. [1] [2]

Activity attribute serialization:

  • Improved serializeActivityAttributes to drop fields one by one until the JSON fits within the size cap, returning null if not possible, instead of truncating raw JSON. Added tests to verify valid output or null on overflow. [1] [2] [3]
  • Fixed readAttribute to correctly handle arrays and objects, improving robustness.

Plugin and skill handling:

  • Fixed resolvePluginSkillContent to only resolve skills with type "plugin" and a valid sourcePlugin, preventing incorrect resolution for inline skills with plugin metadata. Added targeted test. [1] [2] [3]
  • Enhanced resolveNestedPluginById to detect and record the actual manifest file path used, improving plugin manifest detection.

Workspace path utilities:

  • Added tests for remapWrapShadowPath to ensure correct mapping of shadow workspace paths to real project paths and proper handling of edge cases.

These changes collectively improve reliability, maintainability, and test coverage for activity tracking, plugin management, and workspace handling.

Minitour and others added 7 commits August 4, 2026 15:30
Cursor Agent CLI sends different conversation_id values on prompts vs tool hooks; reconcile by generation before grouping so live SSE updates keep one run per turn.
Keep attributes_json valid JSON under the size cap, tighten plugin skill fallback guards, namespace activity run ids by conversation, populate nested plugin manifest paths, and skip Cursor id reconcile when generation chat ids conflict.
Cursor CLI does not emit postToolUse for CallDynamicTool (WebSearch/WebFetch) or Glob; ingest those at preToolUse without duplicating Read/Shell spans.
Show touched files beside activity spans with search, resizable split,
wrap shadow path remapping, and two-way highlight between expanded spans
and file rows.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use Array.isArray for file-tree selection typing. Only read
transcript_path from stop rows after a cheap string pre-check.

Co-authored-by: Cursor <cursoragent@cursor.com>
Treat strict path prefixes and extensionless search roots as directories
so nested activity paths no longer render with file icons.

Co-authored-by: Cursor <cursoragent@cursor.com>
…on-reconcile

Fix Cursor CLI activity trace grouping
Copilot AI lite review requested due to automatic review settings August 4, 2026 14:11
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Release v2.0.2: Cursor activity correlation, serialization fixes, run file tree

🐞 Bug fix ✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Reconciles conflicting conversation_id values across Cursor prompt/tool/stop rows so a
 generation groups under one chat id, with new activity-correlation-reconcile.ts module and tests.
• Traces Cursor's beforeTool events for tools lacking postToolUse (WebSearch, Glob) while
 avoiding duplicate spans, and unwraps CallDynamicTool to show inner tool names.
• Fixes attribute serialization to drop oversized fields incrementally (returning valid JSON or
 null) instead of truncating raw JSON, and corrects array/object handling in readAttribute.
• Fixes resolvePluginSkillContent to require both type === "plugin" and sourcePlugin,
 preventing incorrect resolution of inline skills with plugin metadata; records actual manifest file
 path for nested plugins.
• Adds remapWrapShadowPath utility and tests to map shadow workspace paths back to real project
 paths.
• Adds a run dialog file tree (web-ui) showing files touched during an activity run, with search,
 resizable split pane, and two-way highlighting between spans and file rows.
Diagram

graph TD
  A["Cursor CLI Hooks"] --> B["agent-activity-normalize.ts"] --> C["activity-correlation-reconcile.ts"] --> D["groupActivityRuns.ts"] --> E["ActivityRunDialog"]
  E --> F["buildRunFileTree.ts"] --> G["remap-shadow-path.ts"]
  F --> H["ActivityRunFileTree"]
  E --> I["ActivitySpanRow"]
  H -.highlight sync.-> I
Loading
Files changed (25) +1847 / -71

Enhancement (12) +1251 / -60
activity-correlation-reconcile.tsAdd Cursor activity conversation id reconciliation module +110/-0

Add Cursor activity conversation id reconciliation module

• New module with reconcileCursorActivityConversationIds and chatConversationIdFromTranscriptPath, unifying conversation_id across prompt/tool/stop rows within the same generation for the Cursor provider, and skipping reconciliation when generation ids map to conflicting chat ids.

src/shared/activity-correlation-reconcile.ts

agent-activity-normalize.tsTrace Cursor beforeTool events for tools without postToolUse +53/-11

Trace Cursor beforeTool events for tools without postToolUse

• Adds cursorPreToolShouldTrace to selectively trace beforeTool events for Cursor tools (WebSearch, Glob) that never emit postToolUse, while skipping tools already covered. Adds displayToolNameFrom to unwrap CallDynamicTool wrapper and show the inner tool name.

src/shared/agent-activity-normalize.ts

agent-activity.tsRegister supplemental beforeTool hook for Cursor provider +20/-2

Register supplemental beforeTool hook for Cursor provider

• Adds CURSOR_SUPPLEMENTAL_ACTIVITY_EVENTS constant and updates buildSystemActivityHooks to include beforeTool for the cursor provider without duplicating existing events.

src/shared/agent-activity.ts

remap-shadow-path.tsAdd remapWrapShadowPath utility for shadow workspace paths +52/-0

Add remapWrapShadowPath utility for shadow workspace paths

• New module providing normalizePosixPath and remapWrapShadowPath, mapping capa wrap shadow workspace paths back to the corresponding real project paths, handling nested and legacy flat cache layouts.

src/shared/workspaces/remap-shadow-path.ts

FileTree.tsxEnhance FileTree with selection, search, badges, and directory heuristics +263/-18

Enhance FileTree with selection, search, badges, and directory heuristics

• Significantly expands FileTree to support file metadata badges (read/modified/deleted), selection highlighting, search-driven auto-expand, scroll-into-view, tree expansion control, and improved folder-vs-file detection for extensionless and prefix paths.

web-ui/src/components/common/FileTree.tsx

ActivityFeed.tsxThread projectPath prop through ActivityFeed to run dialog +3/-0

Thread projectPath prop through ActivityFeed to run dialog

• Adds a projectPath prop to ActivityFeedProps and passes it down to ActivityRunDialog.

web-ui/src/features/projects/components/activity/ActivityFeed.tsx

ActivityRunDialog.tsxAdd file tree pane and span linking to run dialog +127/-27

Add file tree pane and span linking to run dialog

• Integrates ActivityRunFileTree and ActivityRunSplitPane to show touched files alongside spans, tracks expanded span/file selection state, and links span expansion to file tree scrolling and highlighting.

web-ui/src/features/projects/components/activity/ActivityRunDialog.tsx

ActivityRunFileTree.tsxAdd ActivityRunFileTree component for run dialog +141/-0

Add ActivityRunFileTree component for run dialog

• New component rendering a searchable, expandable file tree of files touched in an activity run, with read/modified/deleted legend and selection callbacks.

web-ui/src/features/projects/components/activity/ActivityRunFileTree.tsx

ActivityRunSplitPane.tsxAdd resizable split pane component +82/-0

Add resizable split pane component

• New component providing a draggable, resizable two-pane layout used to place the file tree beside the activity span list in the run dialog.

web-ui/src/features/projects/components/activity/ActivityRunSplitPane.tsx

ActivitySection.tsxPass project path to ActivityFeed +3/-1

Pass project path to ActivityFeed

• Fetches the project via useProject and forwards its path as projectPath to ActivityFeed.

web-ui/src/features/projects/components/activity/ActivitySection.tsx

ActivitySpanRow.tsxAdd file-linked highlighting and expansion callback to span rows +11/-1

Add file-linked highlighting and expansion callback to span rows

• Adds onExpandedChange and fileLinked props to ActivitySpanRow, adding an id attribute for scroll targeting and a highlight style when linked to a selected file.

web-ui/src/features/projects/components/activity/ActivitySpanRow.tsx

buildRunFileTree.tsAdd buildRunFileTree module deriving touched files from activity spans +386/-0

Add buildRunFileTree module deriving touched files from activity spans

• New module that parses tool args to detect Read/Write/Delete/Grep operations, merges flags per path, remaps shadow workspace paths, builds a directory tree, and provides helpers to map spans to display path keys and vice versa for the run dialog file tree.

web-ui/src/features/projects/components/activity/buildRunFileTree.ts

Bug fix (4) +39 / -8
skill-content.tsFix resolvePluginSkillContent guard condition +1/-1

Fix resolvePluginSkillContent guard condition

• Changes the guard from 'type !== 'plugin' && !sourcePlugin' to 'type !== 'plugin' || !sourcePlugin', requiring both conditions to be true before resolving a plugin skill, preventing false-positive resolution.

src/server/skill-content.ts

activity-attributes.tsFix attribute serialization to drop fields instead of truncating JSON +13/-4

Fix attribute serialization to drop fields instead of truncating JSON

• Reworks serializeActivityAttributes to iteratively remove keys until the serialized JSON fits the size cap, returning null if it never fits, avoiding invalid truncated JSON. Also fixes readAttribute to properly return arrays separately from objects.

src/shared/activity-attributes.ts

detect.tsPopulate manifestFile path when resolving nested plugin by id +9/-1

Populate manifestFile path when resolving nested plugin by id

• Adds logic to search for and record the actual manifest file path used when resolving a nested plugin, instead of always returning an empty string.

src/shared/plugin-manifest/detect.ts

groupActivityRuns.tsReconcile Cursor conversation ids and namespace run ids by conversation +16/-2

Reconcile Cursor conversation ids and namespace run ids by conversation

• Calls reconcileCursorActivityConversationIds before grouping calls, and introduces activityRunSelectionId to namespace run ids by conversation+generation to avoid collisions across conversations.

web-ui/src/features/projects/components/activity/groupActivityRuns.ts

Tests (8) +541 / -2
skill-content-plugin.test.tsAdd test for inline skill with plugin metadata not resolving via plugin path +26/-1

Add test for inline skill with plugin metadata not resolving via plugin path

• Adds a test asserting that an inline skill with sourcePlugin metadata is not incorrectly resolved through the plugin unpack path; also fixes a formatting issue in an adjacent test.

src/server/tests/skill-content-plugin.test.ts

activity-attributes.test.tsAdd test for size-capped serialization returning valid JSON or null +15/-0

Add test for size-capped serialization returning valid JSON or null

• Adds a test verifying serializeActivityAttributes returns parseable JSON within the size cap or null when it cannot fit, importing the new ACTIVITY_ATTRIBUTES_MAX_JSON_CHARS constant.

src/shared/tests/activity-attributes.test.ts

activity-correlation-reconcile.test.tsAdd tests for Cursor conversation id reconciliation +122/-0

Add tests for Cursor conversation id reconciliation

• New test suite covering chatConversationIdFromTranscriptPath parsing and reconcileCursorActivityConversationIds behavior including rewriting, transcript-based learning, ambiguity handling, and non-cursor sources.

src/shared/tests/activity-correlation-reconcile.test.ts

agent-activity.test.tsUpdate and expand tests for Cursor beforeTool tracing +45/-1

Update and expand tests for Cursor beforeTool tracing

• Updates expectations for buildSystemActivityHooks to include beforeTool for cursor provider, and adds tests for normalizeActivityHookPayload tracing WebSearch, Glob, and skipping Read at preToolUse.

src/shared/tests/agent-activity.test.ts

remap-shadow-path.test.tsAdd tests for remapWrapShadowPath utility +29/-0

Add tests for remapWrapShadowPath utility

• New test file covering nested shadow workspace path mapping, project root mapping, non-shadow path passthrough, and missing real project path handling.

src/shared/workspaces/tests/remap-shadow-path.test.ts

FileTree.test.tsAdd tests for FileTree path tree building +29/-0

Add tests for FileTree path tree building

• New test file covering buildFilePathTree treating strict path prefixes and extensionless Grep roots as folders, and normal files as leaves.

web-ui/src/components/common/FileTree.test.ts

buildRunFileTree.test.tsAdd tests for run file tree building utilities +201/-0

Add tests for run file tree building utilities

• New test suite covering collectRunFileChanges merging read/write flags, ignoring prompts/shell, shadow path remapping, tree building, file list generation, and span-to-path lookup.

web-ui/src/features/projects/components/activity/buildRunFileTree.test.ts

groupActivityRuns.test.tsAdd tests for Cursor conversation id namespacing in run grouping +74/-0

Add tests for Cursor conversation id namespacing in run grouping

• Adds tests verifying tool spans merge into the prompt's conversation for one generation, and that run ids are namespaced by conversation id when generation_id collides across conversations.

web-ui/src/features/projects/components/activity/groupActivityRuns.test.ts

Documentation (1) +16 / -1
projects.jsonAdd i18n strings for run file tree UI +16/-1

Add i18n strings for run file tree UI

• Adds new localization keys for the run file tree pane: heading, empty states, counts, legend labels, search placeholder, and expand/collapse controls.

web-ui/src/locales/en/projects.json

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This release PR (v2.0.2) improves activity ingestion/correlation (especially for Cursor), makes activity attribute serialization safer under size caps, tightens plugin/skill resolution behavior, and adds a new “Files touched” UI in the project activity run dialog (including shared FileTree enhancements and workspace shadow-path remapping).

Changes:

  • Correlate Cursor activity rows within a generation so prompts/tools/stops share the same conversation_id, and improve Cursor pre-tool tracing for tools that don’t emit postToolUse.
  • Replace activity-attributes truncation with “drop fields until JSON fits” serialization, and harden attribute extraction for arrays/objects.
  • Add run “Files touched” sidebar + split-pane UI, backed by file-change derivation and a richer FileTree component; add wrap shadow workspace path remapping + tests.

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
web-ui/src/locales/en/projects.json Adds localized strings for the new run “Files” sidebar UI (labels, empty states, search, expand/collapse).
web-ui/src/features/projects/components/activity/groupActivityRuns.ts Normalizes Cursor conversation IDs before grouping; introduces stable run selection IDs namespaced by conversation.
web-ui/src/features/projects/components/activity/groupActivityRuns.test.ts Adds coverage for Cursor CLI conversation merging and generation-id collision namespacing.
web-ui/src/features/projects/components/activity/buildRunFileTree.ts New utilities to derive touched files from activity spans, build display keys, and support file tree selection/scrolling.
web-ui/src/features/projects/components/activity/buildRunFileTree.test.ts Tests for file change collection, shadow-path remapping behavior, tree building, and span→file mapping.
web-ui/src/features/projects/components/activity/ActivitySpanRow.tsx Adds span anchoring + callbacks for expansion tracking and file-linked highlighting.
web-ui/src/features/projects/components/activity/ActivitySection.tsx Passes project.path to the activity feed so file paths can be rendered relative to the project root.
web-ui/src/features/projects/components/activity/ActivityRunSplitPane.tsx New resizable split-pane for run dialog (files sidebar + span list).
web-ui/src/features/projects/components/activity/ActivityRunFileTree.tsx New run sidebar showing touched files with filtering, selection, and legend badges.
web-ui/src/features/projects/components/activity/ActivityRunDialog.tsx Integrates split-pane + file sidebar; links file selections to span scrolling and span expansion to file selection.
web-ui/src/features/projects/components/activity/ActivityFeed.tsx Threads projectPath through to the run dialog.
web-ui/src/components/common/FileTree.tsx Upgrades FileTree to support annotations/badges, selection, search-driven expansion, and scroll-to-selection.
web-ui/src/components/common/FileTree.test.ts Adds unit tests for file-vs-folder inference (strict prefixes, extensionless roots).
src/shared/workspaces/remap-shadow-path.ts New helper to remap capa wrap shadow workspace paths back to the real project path.
src/shared/workspaces/tests/remap-shadow-path.test.ts Tests for nested/flat shadow workspace remapping and missing-real-path behavior.
src/shared/plugin-manifest/detect.ts Records the actual manifest file path used when resolving nested plugins.
src/shared/agent-activity.ts Registers supplemental Cursor beforeTool hooks to capture tools without postToolUse.
src/shared/agent-activity-normalize.ts Traces certain Cursor tools at beforeTool (avoids duplicates), and improves wrapped/dynamic tool naming.
src/shared/activity-correlation-reconcile.ts New module to reconcile Cursor conversation_id mismatches within a generation (prompt vs agent-session IDs).
src/shared/activity-attributes.ts Updates serialization to fit size caps by dropping fields; improves array/object robustness in attribute reading.
src/shared/tests/agent-activity.test.ts Updates/expands tests to validate Cursor supplemental hook registration and tracing behavior.
src/shared/tests/activity-correlation-reconcile.test.ts New tests for transcript-path parsing and Cursor conversation ID reconciliation rules.
src/shared/tests/activity-attributes.test.ts Adds test ensuring serialized attributes are valid JSON within cap or null.
src/server/skill-content.ts Fixes plugin-skill resolution to only apply to type: "plugin" skills with a valid sourcePlugin.
src/server/tests/skill-content-plugin.test.ts Adds targeted test to ensure inline skills aren’t incorrectly resolved via plugin unpack logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread web-ui/src/components/common/FileTree.tsx Outdated
Comment thread web-ui/src/features/projects/components/activity/buildRunFileTree.ts Outdated
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Aug 4, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Extensionless files unselectable ✓ Resolved 🐞 Bug ≡ Correctness
Description
FileTree only treats a leaf node as a file when the basename contains a dot or matches a small
allowlist, so legitimate extensionless files render as directories and never trigger onFileSelect.
This breaks selection/highlighting behavior for such files in the new run file tree and other
FileTree consumers.
Code

web-ui/src/components/common/FileTree.tsx[R22-25]

+  const base = displayPath.split('/').filter(Boolean).pop() ?? '';
+  if (!base) return false;
+  if (base.includes('.')) return true;
+  return EXTENSIONLESS_FILE_NAMES.test(base);
Evidence
The file/dir heuristic returns false for extensionless basenames not in the allowlist, and selection
is explicitly gated on showAsFile = node.isFile && !hasChildren, so those leaves cannot be
selected.

web-ui/src/components/common/FileTree.tsx[18-26]
web-ui/src/components/common/FileTree.tsx[70-74]
web-ui/src/components/common/FileTree.tsx[220-240]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`FileTree` currently infers “file vs directory” from filename spelling (has `.` or matches a small allowlist). This makes many valid extensionless files (e.g. `Gemfile`, `gradlew`, `Procfile`, project-specific scripts) render as directories. Because file selection is gated on `showAsFile`, these entries cannot be selected/clicked.
## Issue Context
You also need a way to represent “directory-like entries” that are present in the input list (e.g. Grep roots) without relying on the extensionless heuristic.
## Fix Focus Areas
- web-ui/src/components/common/FileTree.tsx[18-26]
- web-ui/src/components/common/FileTree.tsx[70-74]
- web-ui/src/components/common/FileTree.tsx[220-240]
## Suggested fix approach
- Change the classification so **terminal entries default to files** unless they have children (children already force directory via `normalizeDirectoryNodes`).
- Add an explicit mechanism to mark directory entries coming from data sources (e.g. allow callers to pass `directories` set, or treat paths ending in `/` as directories and keep that information through normalization), instead of assuming “extensionless == directory”.
- Ensure `onFileSelect` fires for leaf nodes that are intended to be files, regardless of extension.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Quadratic FileTree build ✓ Resolved 🐞 Bug ➹ Performance
Description
buildTree calls isStrictPathPrefix for each input path leaf, and isStrictPathPrefix linearly
scans the entire pathSet, making tree construction worst-case O(n²). This can cause noticeable UI
stalls when rendering large file lists.
Code

web-ui/src/components/common/FileTree.tsx[R28-31]

+function isStrictPathPrefix(full: string, pathSet: Set<string>): boolean {
+  for (const other of pathSet) {
+    if (other !== full && other.startsWith(`${full}/`)) return true;
+  }
Evidence
isStrictPathPrefix iterates the full Set of paths, and it is called when setting node.isFile
for each input path’s terminal segment, producing O(n²) work overall.

web-ui/src/components/common/FileTree.tsx[28-33]
web-ui/src/components/common/FileTree.tsx[44-74]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`isStrictPathPrefix(full, pathSet)` loops over *all* paths to detect whether `full` is a strict prefix of another path. `buildTree` invokes this per terminal path, yielding O(n²) behavior in the number of paths.
## Issue Context
You already run `normalizeDirectoryNodes(root)` which forces any node with children to be a directory. That means you can usually avoid a global prefix scan entirely, or replace it with a precomputed prefix set.
## Fix Focus Areas
- web-ui/src/components/common/FileTree.tsx[28-33]
- web-ui/src/components/common/FileTree.tsx[44-79]
## Suggested fix approach
- Preferred: **remove `isStrictPathPrefix` entirely** and set `node.isFile` based on leaf-ness + caller intent; rely on `normalizeDirectoryNodes` to flip nodes with children to directories.
- Alternative: precompute a `prefixSet` in O(totalSegments) by adding all parent prefixes while inserting paths, then replace the full scan with `prefixSet.has(pathSoFar)`.
- Add/adjust unit tests to ensure strict-prefix entries still render as directories (this should remain true via children detection).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread web-ui/src/components/common/FileTree.tsx Outdated
Comment thread web-ui/src/components/common/FileTree.tsx Outdated
Mark Grep/Glob roots as explicit directories, default leaf paths to
files, avoid O(n²) prefix scans, cache span path keys, and improve
splitter keyboard focus and non-interactive tree rows.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copilot AI review requested due to automatic review settings August 4, 2026 14:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.

Suppressed comments (2)

web-ui/src/components/common/FileTree.tsx:52

  • pathKey construction drops the leading / for absolute paths (/a/b becomes a/b). When files/annotations/selectedPathKeys use absolute display paths (e.g. when there’s no common prefix, or paths are mixed absolute+relative), this causes selection + annotations lookup to fail because the keys no longer match.
  for (const raw of paths) {
    const normalized = raw.replace(/\\/g, '/').replace(/\/+$/, '');
    const segments = normalized.split('/').filter(Boolean);
    if (segments.length === 0) continue;

web-ui/src/features/projects/components/activity/ActivityRunSplitPane.tsx:57

  • Drag handling only listens for pointerup. If the pointer is canceled (e.g. OS gesture, browser losing capture, alt-tab), draggingRef can remain true and the global cursor/userSelect styles may stay stuck, and listeners won’t be removed.
  const endDrag = useCallback(() => {
    draggingRef.current = false;
    document.body.style.cursor = '';
    document.body.style.userSelect = '';
    window.removeEventListener('pointermove', onPointerMove);

@Minitour
Minitour merged commit f4d141d into main Aug 4, 2026
18 of 19 checks passed
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