Skip to content

Fix shared WebView task manager attribution - #4047

Merged
lawrencecchen merged 3 commits into
mainfrom
feat-webview-task-manager-percentages
May 13, 2026
Merged

lawrencecchen merged 3 commits into
mainfrom
feat-webview-task-manager-percentages

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented May 13, 2026 •

Copy link
Copy Markdown
Contributor

Fixes task manager resource attribution for WebView rows that share the same WebContent PID. Each shared WebView row now shows its attributed share of CPU, resident memory, and virtual memory while keeping the PID list intact for process actions.

Verification:


Note

Medium Risk
Adjusts task manager resource attribution for WebView rows sharing a PID; risk is moderate because it changes how CPU/memory numbers are computed and displayed but is scoped and covered by new unit tests.

Overview
Fixes task manager resource attribution when multiple WebView rows share the same WebContent PID by prorating CPU, resident memory, and virtual memory per occurrence while keeping the underlying PID lists intact for actions.

Adds CmuxTopResourceSummary.attributedPayload(sharedAcross:) and updates v2AnnotateTopWebView to use it (and to clamp shared_process_count to at least 1). Adds targeted unit tests validating both the prorating logic and end-to-end window/WebView annotation behavior for shared PIDs.

Reviewed by Cursor Bugbot for commit 1e58b18. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Fix resource attribution in the task manager for shared WebView rows. Each WebView now shows its proportional CPU, resident, and virtual memory when multiple rows share the same WebContent PID, while keeping PID lists usable for process actions; edge cases (<=1 occurrence) return unmodified totals.

  • Bug Fixes
    • Prorate CPU, resident, and virtual memory across shared WebView rows via attributedPayload(sharedAcross:) (no-op for counts <= 1).
    • Use prorated resources when annotating WebView rows in TerminalController.
    • Add tests for prorating math, end-to-end shared-WebView annotation, edge cases (0/negative), and a regression verifying per-WebView attribution against window totals.

Written for commit 1e58b18. Summary will update on new commits.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced shared resource reporting: CPU percentage, resident memory, and virtual memory are now accurately distributed across multiple process occurrences, providing precise resource metrics for shared processes and webviews.
  • Tests

    • Added comprehensive test coverage for shared resource attribution calculations and multi-occurrence resource distribution scenarios.

Review Change Stack

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@vercel

vercel Bot commented May 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment May 13, 2026 4:43am
cmux-staging Building Building Preview, Comment May 13, 2026 4:43am

@coderabbitai

coderabbitai Bot commented May 13, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR adds resource attribution for shared webview surfaces by introducing a method to divide CPU and memory metrics across multiple occurrences, integrating it into webview annotation, and validating the behavior with unit and integration tests.

Changes

Attributed Payload for Shared Webview Resources

Layer / File(s) Summary
Attributed payload method with unit tests
Sources/CmuxTopSnapshot.swift, cmuxTests/TaskManagerResourcesTests.swift
New attributedPayload(sharedAcross:) method prorates cpuPercent, residentBytes, and virtualBytes by occurrence count; unit test verifies prorated values, numeric type conversions, and PID array formatting.
Webview resource attribution
Sources/TerminalControllerTopSupport.swift
v2AnnotateTopWebView clamps sharedProcessCount to minimum 1, retrieves summary via summary(for:rootPIDs:), and applies attributedPayload(sharedAcross:) to normalize resource values per webview.
Webview resource integration test
cmuxTests/CmuxTopSnapshotScopeTests.swift
Test creates dual shared webviews, annotates windows with browser PID occurrences, extracts per-webview resource dictionaries using helpers, and verifies both instances are present with sum-consistent resident bytes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

  • manaflow-ai/cmux#3290: Both PRs address the cmux top task manager pipeline and the CmuxTopResourceSummary class, with this PR adding attributedPayload(sharedAcross:) to integrate into annotated webview resources.
  • manaflow-ai/cmux#3588: This PR directly builds on CPU-sampling infrastructure added in the related PR, integrating CmuxTopResourceSummary.attributedPayload(sharedAcross:) into resource aggregation.

Poem

🐰 With shared resources fairly divided, once twice or thrice—a summary splits its treasure true, and webviews rest assured their bytes are fairly due. Tests affirm the math, each occurrence gets its due!

🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (14 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: fixing resource attribution for shared WebView rows in the task manager.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed Nonisolated Sendable struct properly maintained; nonisolated method inheritance correct; MainActor boundary properly enforced in TerminalControllerTopSupport. No actor isolation violations.
Cmux Swift Blocking Runtime ✅ Passed No blocking synchronization primitives detected in production code. Changes are deterministic arithmetic operations (dividing resource values) with no semaphores, sleeps, locks, or dispatch blocking.
Cmux No Hacky Sleeps ✅ Passed All production code changes (Sources/CmuxTopSnapshot.swift, TerminalControllerTopSupport.swift) contain no sleep/timing patterns. Test code uses only pre-existing test scaffolding allowed by the rule.
Cmux Swift Concurrency ✅ Passed No legacy async patterns detected. Changes are synchronous value transformations in core logic and tests, with no DispatchQueue, Combine, completion handlers, or fire-and-forget Tasks.
Cmux Swift @Concurrent ✅ Passed All Swift changes are synchronous methods. No async functions, @concurrent annotations, or actor isolation violations were introduced.
Cmux Swift File And Package Boundaries ✅ Passed Focused 9-line addition to untracked file with single responsibility. No mixed concerns or oversized files. Meets custom check criteria.
Cmux Swift Logging ✅ Passed No logging violations detected. The PR adds the attributedPayload() method and updates resource calculations without introducing print, NSLog, debug-only logs, or secrets exposure.
Cmux Swiftui State Layout ✅ Passed No SwiftUI changes found. PR only modifies data model structures (CmuxTopResourceSummary) and helper functions with no SwiftUI state management, GeometryReader, or render-time mutations.
Cmux Architecture Rethink ✅ Passed Pure, stateless correctness fix for shared WebView resource attribution. No timing dependencies, mutable state, caches, observers, or lifecycle splits. Clear ownership and invariants.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR contains no user-visible window, panel, or window-controller creation/modification. Changes are limited to data transformation methods and resource attribution logic. Check does not apply.
Description check ✅ Passed The pull request description is comprehensive and follows the template structure with Summary, Testing (verification steps), and a detailed Checklist section.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-webview-task-manager-percentages

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 and usage tips.

coderabbitai[bot]
coderabbitai Bot previously requested changes May 13, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmuxTests/TaskManagerResourcesTests.swift`:
- Around line 10-25: Add unit tests for CmuxTopResourceSummary.attributedPayload
to cover edge cases of the occurrenceCount (sharedAcross) parameter: create
tests that call attributedPayload(sharedAcross: 1) to assert the payload is
unchanged (cpuPercent, residentBytes, virtualBytes, processCount, pids),
attributedPayload(sharedAcross: 0) to assert no divide-by-zero/crash and values
remain unchanged (or documented behavior), and attributedPayload(sharedAcross:
-1) to ensure negative inputs are handled consistently; place these new test
methods in TaskManagerResourcesTests.swift (e.g.,
testAttributedPayloadReturnsUnmodifiedPayloadWhenOccurrenceCountIsOne,
testAttributedPayloadHandlesZeroOccurrenceCount,
testAttributedPayloadHandlesNegativeOccurrenceCount) and assert the same numeric
expectations used in the existing test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1b60175a-0141-4a10-b9cb-c32f6e4d894e

📥 Commits

Reviewing files that changed from the base of the PR and between be769af and e5ef5dd.

📒 Files selected for processing (4)
  • Sources/CmuxTopSnapshot.swift
  • Sources/TerminalControllerTopSupport.swift
  • cmuxTests/CmuxTopSnapshotScopeTests.swift
  • cmuxTests/TaskManagerResourcesTests.swift

Comment thread cmuxTests/TaskManagerResourcesTests.swift
@greptile-apps

greptile-apps Bot commented May 13, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes task manager resource over-reporting when multiple WebView rows share the same WebContent PID. Previously each row showed the full process totals; now each row shows its proportional (1/N) share of CPU, resident memory, and virtual memory via the new attributedPayload(sharedAcross:) method, while pids and the PID list are intentionally kept intact for process actions. Parent-level aggregation (surface, pane, workspace, window) remains correct because it uses Set<Int>-deduplicated summaryPayload(), so shared PIDs are still counted only once at higher levels.

  • CmuxTopResourceSummary.attributedPayload(sharedAcross:) performs the integer/float division for CPU, resident, and virtual bytes; a guard occurrenceCount > 1 short-circuit preserves unmodified behavior for the single-occurrence case.
  • v2AnnotateTopWebView now fetches summary(for:rootPIDs:) then calls attributedPayload(sharedAcross:) with a max(1,…)-guarded occurrence count, replacing the previous single summaryPayload() call.
  • New unit tests cover the prorating math (including off-by-one for odd byte values), the identity cases (count ≤ 1), and an end-to-end fixture with two surfaces sharing the same PID.

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped to WebView resource attribution math with no effect on auth, persistence, or process control.

The prorating logic is straightforward integer/float division applied only to display metrics; the unit tests explicitly cover the prorating calculation, edge cases for counts ≤ 1, and an end-to-end shared-PID fixture. Parent-level resource totals are unaffected because they use Set-deduplicated summation. The only open question is whether process_count should also be prorated, which is a display-semantics concern rather than a functional defect.

No files require special attention. Sources/CmuxTopSnapshot.swift contains the only design question worth revisiting (process_count proration) but this does not affect correctness of the resource totals.

Important Files Changed

Filename Overview
Sources/CmuxTopSnapshot.swift Adds attributedPayload(sharedAcross:) that prorates CPU/resident/virtual by occurrence count; processCount, pids, and missingPIDs are intentionally passed through unchanged.
Sources/TerminalControllerTopSupport.swift Switches v2AnnotateTopWebView to call summary() + attributedPayload(sharedAcross:) instead of summaryPayload(); adds max(1,…) guard for defensive safety against zero division.
cmuxTests/TaskManagerResourcesTests.swift New unit tests for attributedPayload(sharedAcross:) covering normal prorating, count = 1, count = 0, and count = -1 edge cases.
cmuxTests/CmuxTopSnapshotScopeTests.swift End-to-end test for shared WebView attribution; spawns a real process, constructs a fixture with two surfaces sharing the same PID, and verifies each row carries ~half the resident bytes.

Sequence Diagram

sequenceDiagram
    participant TC as TerminalController
    participant AWV as v2AnnotateTopWebView
    participant SNAP as CmuxTopProcessSnapshot
    participant SUM as CmuxTopResourceSummary

    TC->>AWV: "v2AnnotateTopWebView(&webview, …, browserPIDOccurrences)"
    AWV->>SNAP: expandedPIDs(rootPIDs: [pid])
    SNAP-->>AWV: "pids (Set<Int>)"
    AWV->>SNAP: summary(for: pids, rootPIDs: rootPIDs)
    SNAP-->>AWV: CmuxTopResourceSummary (full totals)
    AWV->>SUM: attributedPayload(sharedAcross: sharedProcessCount)
    Note over SUM: cpuPercent /= N<br/>residentBytes /= N<br/>virtualBytes /= N<br/>pids, processCount unchanged
    SUM-->>AWV: attributed [String: Any] payload
    AWV-->>TC: "pids (Set<Int>, for parent rollup)"
    Note over TC: Parent surface/pane/workspace/window<br/>use Set-deduplicated summaryPayload()<br/>so shared PIDs count only once
Loading

Reviews (2): Last reviewed commit: "Test shared WebView attribution edge cas..." | Re-trigger Greptile

Comment on lines +25 to +32
func attributedPayload(sharedAcross occurrenceCount: Int) -> [String: Any] {
guard occurrenceCount > 1 else { return payload() }
var attributed = self
attributed.cpuPercent /= Double(occurrenceCount)
attributed.residentBytes = attributed.residentBytes / Int64(occurrenceCount)
attributed.virtualBytes = attributed.virtualBytes / Int64(occurrenceCount)
return attributed.payload()
}

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.

P2 missingPIDs is not attributed and its behaviour is untested

attributedPayload divides CPU/resident/virtual but passes missingPIDs through unchanged. If a shared WebContent PID is absent from the process snapshot, every WebView row referencing it will contain that PID in missing_pids. A consumer that reacts to missing_pids (e.g. "process gone – show reconnect banner") will fire N times for the same dead process. The unit test seeds an empty missingPIDs, so this path has no coverage today. Is duplicating missingPIDs across all shared WebView rows intentional, or should only one row carry the list while the others see []?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Leaving missing_pids unchanged is intentional because it is row-scoped diagnostic metadata, not an attributable resource measurement. A consumer that aggregates missing PIDs should de-dupe by PID across rows.

— Claude Code

@lawrencecchen
lawrencecchen dismissed coderabbitai[bot]’s stale review May 13, 2026 04:33

Addressed in commit 1e58b18; CodeRabbit resolved the inline thread after re-review.

@lawrencecchen
lawrencecchen merged commit 1657a83 into main May 13, 2026
30 checks passed
@lawrencecchen
lawrencecchen deleted the feat-webview-task-manager-percentages branch May 13, 2026 04:45

This branch was successfully deployed

1 active deployment
Preview – cmux — 1e58b18b Deployed May 13, 2026 by vercel[bot]
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.

1 participant