Skip to content

taskmanager: honest memory labels, untruncated grouping, agent row folding - #7624

Closed
austinywang wants to merge 6 commits into
mainfrom
issue-7596-taskmanager-accounting
Closed

austinywang wants to merge 6 commits into
mainfrom
issue-7596-taskmanager-accounting

Conversation

@austinywang

@austinywang austinywang commented Jul 8, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Part of #7596 (memory audit, slice 3 — Task Manager accounting).

Three fixes:

  1. Honest headline label. The "Memory" tile (and cmux top totals help) is a naive sum of per-process phys_footprint across cmux + all descendants; shared pages (dyld cache, frameworks, shared IOSurfaces) are counted once per process, which is how the audit session showed 22.4 GB while whole-machine RSS across ALL processes was 28 GB. The tile is now "Summed Footprint" with a tooltip explaining the double-counting (localized en/ja), and the cmux top help text says the same. The value is deliberately unchanged — "App Footprint" (single-PID phys_footprint) remains the accurate number, per the issue's "fix or honestly label" guidance.
  2. Truncation class fixed. Grouping keys used proc_name (p_comm, 16-char max), so the ~223 WebKit helpers grouped as "com.apple.WebKi". New cmuxTopCanonicalProcessName prefers the untruncated proc_pidpath basename when the comm looks truncated (15/16 chars and the basename extends it, case-insensitive) — no WebKit-specific hardcoding, fixes every truncated helper name. Applied to both program rows and child-memory diagnostic groups.
  3. Agent version-string rows folded. Claude Code's native-installer node binary is named by its version dir (~/.local/share/claude/versions/2.1.204), so it appeared BOTH in the "Claude Code" coding-agents row and as a raw "2.1.204" program row. Program rows now exclude agent-classified PIDs, and child-memory groups fold agent processes under the agent's display name — one shared codingAgentDefinitionsByPID classifier mirrors the existing gating exactly (argv reads still gated by shouldReadArguments).

Per-pane WebContent PIDs were already attributed via webview-root-pid; attributing the shared WebKit GPU/Networking helpers to individual panes needs per-pane WebKit SPI that doesn't exist today — deferred, noted on the issue.

Tests

New CmuxTopAccountingGroupingTests (wired into cmuxTests in pbxproj; lint-pbxproj-test-wiring.sh passes): canonical-name truncation matrix, agent-PID exclusion from program rows (agent still present in coding_agents), canonical program-row display names, child-group agent folding + truncated-helper renaming, and a guard that totals math (clampedAdd sum) is unchanged.

python3 scripts/swift_file_length_budget.py passes with no TSV changes — at-cap files stayed at cap (CmuxTopSnapshot.swift 664, CLI/cmux.swift exactly 35,600 via 1:1 replacement); new logic lives in new/untracked files.

Localization audit

Added taskManager.summary.summedFootprint + .help with en and ja values (matching the locale coverage of the sibling taskManager.summary.cpu); removed the now-unreferenced taskManager.summary.memory key (verified zero references repo-wide); taskManager.column.memory untouched. The cmux top CLI help block was already a non-localized bare string; the 1:1 replacement preserves that pre-existing pattern.

Part of #7596

🤖 Generated with Claude Code


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Note

Low Risk
Changes are limited to Task Manager / top labeling, grouping, and snapshot parsing; memory totals math is explicitly unchanged and covered by tests.

Overview
Task Manager and cmux top now call the headline memory total Summed Footprint (with a tooltip / help text that shared pages are counted per process, so the number can overstate real usage). The underlying sum is unchanged.

Process accounting grouping is tightened: cmuxTopCanonicalProcessName expands truncated proc_name values using the executable path basename; program totals and child-memory diagnostic groups use that name and case-insensitive keys (stable lowercased group ids). Coding-agent PIDs are classified once per snapshot via a memoized helper and are excluded from program rows while appearing under agent display names in diagnostics and coding_agents.

The Task Manager client treats a present but empty program_totals payload as intentional (no Program Totals section) instead of rebuilding aggregates from hierarchy rows. New CmuxTopAccountingGroupingTests cover these behaviors.

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


Summary by cubic

Clarifies Task Manager memory accounting and improves grouping by relabeling the memory tile, fixing truncated names, folding coding-agent processes under agent rows, and stabilizing memory-diagnostic group IDs. Also honors backend-provided empty program_totals. Part of #7596 Task Manager accounting.

  • Bug Fixes
    • Renamed the Memory tile to "Summed Footprint" with an explanatory tooltip; updated cmux top help. Value unchanged.
    • Canonicalized process/group names using the untruncated path basename when proc_name is truncated; applied to program rows and memory diagnostics.
    • Kept memory-diagnostic grouping case-insensitive and derived group IDs from the lowercased key for stable row identity; display names keep first-seen casing.
    • Excluded agent-classified PIDs from program rows and folded them under the agent display name in child-memory groups via a shared classifier.
    • Memoized per-PID coding-agent classification per snapshot via a private, lock-guarded cache so all payload sections agree and to avoid duplicate reads.
    • Honored explicitly empty program_totals in the payload; legacy fallback only when the field is absent so filtered-out agent rows aren’t recomputed client-side.

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

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added a “Summed Footprint” memory metric in the CPU/Memory/etc header, with a help tooltip explaining that shared memory can cause totals to appear higher than actual usage.
  • Bug Fixes
    • Improved program/process naming and grouping by using canonicalized names for more consistent, case-insensitive aggregation.
    • Refined memory diagnostics so agent processes are folded into stable canonical groups.
    • Fixed snapshot aggregation to respect explicitly empty program totals (no legacy fallback).
  • Tests
    • Added/expanded coverage for naming/canonicalization, grouping, and snapshot payload behavior.

…lding

Three accounting fixes from the #7596 audit:

- The headline "Memory" tile summed per-process phys_footprint across
  cmux and every descendant, double-counting the dyld shared cache,
  shared frameworks, and shared IOSurfaces (22.4 GB shown vs 28 GB
  whole-machine RSS). Relabel it "Summed Footprint" with an explanatory
  tooltip (en/ja) and matching cmux top CLI help; the value itself is
  unchanged and App Footprint remains the accurate single-process
  number.
- Program rows and child-memory groups keyed on proc_name, which is
  p_comm truncated to 16 chars, so all WebKit helpers collapsed into a
  row named "com.apple.WebKi". Group names now canonicalize through the
  untruncated proc_pidpath basename when the comm looks truncated,
  fixing the whole truncation class without WebKit-specific
  hardcoding.
- Coding-agent CLI processes with version-string binaries (e.g.
  Claude's ~/.local/share/claude/versions/2.1.204) were folded into the
  "Claude Code" coding-agents row but ALSO surfaced as a raw "2.1.204"
  program row. Program rows now exclude agent-classified PIDs, and
  child-memory groups fold agent processes under the agent display
  name, via one shared classifier.

Part of #7596

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 8, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
cmux Canceled Canceled Jul 8, 2026 11:54pm
cmux-staging Building Building Preview, Comment Jul 8, 2026 11:54pm

@coderabbitai

coderabbitai Bot commented Jul 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds canonical process-name and coding-agent lookup logic, applies it to memory diagnostics and summary payloads, renames the Task Manager metric to Summed Footprint, and updates tests, localization, and project wiring.

Changes

Summed footprint labeling and canonical process naming

Layer / File(s) Summary
Canonical process naming and coding-agent lookup
Sources/CmuxTopProcessNaming.swift
Adds canonical process-name derivation, conditional argument reading, and memoized per-PID coding-agent definition lookup.
Apply canonical names in summaries and diagnostics
Sources/CmuxTopMemoryDiagnostics.swift, Sources/CmuxTopSnapshot.swift, Sources/TaskManagerSnapshot.swift
Memory diagnostics grouping now uses agent display names or canonical names; program and coding-agent summaries use cached per-PID definitions and canonical titles; aggregate parsing now distinguishes absent from empty program_totals.
Summed Footprint UI metric and localization
Sources/TaskManagerView.swift, Resources/Localizable.xcstrings, CLI/cmux.swift
Replaces the memory header metric with Summed Footprint, adds localized help text, adds new localization keys, and updates the inline memory aggregation comment.
Accounting tests and project wiring
cmuxTests/CmuxTopAccountingGroupingTests.swift, cmuxTests/CmuxTopSnapshotScopeTests.swift, cmux.xcodeproj/project.pbxproj
Adds tests for canonical naming, grouping, snapshot parsing, and overflow handling, plus Xcode project entries for the new source and test files.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CmuxTopProcessSnapshot
  participant CmuxTopProcessNaming
  participant CmuxTopMemoryDiagnostics
  participant CmuxTaskManagerView

  CmuxTopProcessSnapshot->>CmuxTopProcessNaming: codingAgentDefinitionsByPID(for: pids)
  CmuxTopProcessNaming-->>CmuxTopProcessSnapshot: definitionsByPID map
  CmuxTopProcessSnapshot->>CmuxTopProcessNaming: cmuxTopCanonicalProcessName(name, path)
  CmuxTopProcessNaming-->>CmuxTopProcessSnapshot: canonical title
  CmuxTopMemoryDiagnostics->>CmuxTopProcessNaming: codingAgentDefinitionsByPID(for: pids)
  CmuxTopProcessNaming-->>CmuxTopMemoryDiagnostics: agentDefinitions map
  CmuxTopMemoryDiagnostics->>CmuxTopMemoryDiagnostics: derive groupName and group id
  CmuxTaskManagerView->>CmuxTopProcessSnapshot: read total.memoryBytes
  CmuxTaskManagerView-->>CmuxTaskManagerView: render "Summed Footprint" with localized help
Loading

Possibly related PRs

  • manaflow-ai/cmux#4132: Introduces the physical-footprint memory_bytes/memoryBytes behavior that the renamed Summed Footprint metric uses.
  • manaflow-ai/cmux#4437: Also updates the memory diagnostics and Task Manager memory presentation pipeline.

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (5 errors)

Check name Status Explanation Resolution
Cmux Swift Blocking Runtime ❌ Error PR adds a production NSLock in Sources/CmuxTopProcessNaming.swift for memoization, a manual lock the rule forbids here. Replace the lock with actor-owned state or another nonblocking explicit-signal design; keep test-only blocking out of Sources/.
Cmux Expensive Synchronous Load ❌ Error New codingAgentDefinitionsByPID does per-PID KERN_PROCARGS2 sysctl reads, and TerminalController calls it from the system.top socket handler. Move classification to an off-main cached loader (e.g. shared background index/task) and have system.top consume cached results only.
Cmux Full Internationalization ❌ Error New taskManager.summary.summedFootprint keys are only en/ja, but the catalog supports 20 locales, so full translation coverage is missing. Add translated entries for every existing locale in Resources/Localizable.xcstrings for taskManager.summary.summedFootprint and .help.
Cmux Architecture Rethink ❌ Error Sources/CmuxTopProcessNaming.swift adds a lock-guarded mutable PID cache in the production payload path, which the rule forbids as a new lock/side cache. Replace the NSLock memo with a single-owner, lock-free snapshot pass or precomputed map; keep any polling/sleep only in tests.
Cmux No Ambient Global State ❌ Error Sources/CmuxTopProcessNaming.swift:3 adds a new module-scope cmuxTopCanonicalProcessName free function, which the rule forbids as ambient API. Move the canonicalization onto CmuxTopProcessSnapshot as a private helper (or keep it file-private) and call it through the snapshot-owned path instead of exporting a free function.
✅ Passed checks (20 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 No new actor-isolation debt: TaskManagerModel stays @MainActor, and the new coding-agent cache is lock-guarded like other @unchecked Sendable helpers.
Cmux Browser Automation Off-Main ✅ Passed PR diff touches task-manager/memory files only; the browser-automation rule target files are unchanged and no socket-worker routing changes appear.
Cmux Cache Substitution Correctness ✅ Passed The memo is snapshot-local, computes from fresh proc args on miss, and is documented as a consistency-preserving deduplication rather than a persisted cache.
Cmux No Hacky Sleeps ✅ Passed PASS: The PR changes only Swift/config files; no JS/TS/shell/build-runtime scripts were modified, so the no-hacky-sleeps rule is not implicated.
Cmux Algorithmic Complexity ✅ Passed No new nested scans or per-target rescans; PID classification is memoized per snapshot, and each payload builder still does a single pass plus one sort.
Cmux Swift Concurrency ✅ Passed PASS: The only code change is a comment in CmuxTopProcessNaming; it documents an NSLock choice and adds no DispatchQueue, Combine, completion-handler, or fire-and-forget Task use.
Cmux Swift @Concurrent ✅ Passed No changed Swift code adds @concurrent, nonisolated async, or async UI-heavy helpers; the new helpers are synchronous and remain UI-bound where applicable.
Cmux Swift File And Package Boundaries ✅ Passed PASS: The new production file is only 74 lines and the touched production files stay below boundary thresholds; the change is a focused naming/accounting fix with tests.
Cmux Swiftpm Lockfiles ✅ Passed HEAD only changes Sources/CmuxTopProcessNaming.swift; no .gitignore, workflow, Package.swift/resolved, or Xcode package-reference diffs are present.
Cmux Swift Logging ✅ Passed Touched Swift code only changes UI strings and pure snapshot logic; no new/changed print, debugPrint, dump, NSLog, Logger, or stderr/stdout diagnostics were added.
Cmux User-Facing Error Privacy ✅ Passed PASS: The diff only changes help/tooltip copy and internal grouping code; no user-facing errors or alerts expose vendor names, secrets, or raw upstream payloads.
Cmux Swiftui State Layout ✅ Passed The PR diff only changes memory-diagnostics logic/tests; it introduces no new SwiftUI state/layout anti-patterns, and the existing TaskManagerView keeps snapshot/closure boundaries.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR only changes Task Manager/accounting code and tests; diff adds no NSWindow/NSPanel/WindowGroup or cmuxAuxiliaryWindowIdentifiers changes, so the auxiliary-window rule isn't implicated.
Cmux Source Artifacts ✅ Passed All changed paths are intentional source/config/localization/test files; no logs, temp dirs, caches, build output, or other artifact paths were added.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Changed production file only adds a comment; no #if DEBUG, test-only symbols, or access widening for tests.
Title check ✅ Passed The title is concise and accurately captures the main changes: memory labeling, canonical grouping, and agent row folding.
Description check ✅ Passed The description is detailed and covers the summary and testing, though some template sections like demo video and checklist are omitted.
✨ 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 issue-7596-taskmanager-accounting

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.

@greptile-apps

greptile-apps Bot commented Jul 8, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR updates Task Manager memory labeling and process grouping. The main changes are:

  • Renames the headline memory metric to Summed Footprint.
  • Adds localized help text explaining shared-memory double counting.
  • Uses canonical process names for truncated helper names.
  • Folds coding-agent processes out of program rows and into agent rows.
  • Treats an explicitly empty program_totals payload as intentional.
  • Adds tests for grouping, agent folding, and totals behavior.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
Sources/CmuxTopMemoryDiagnostics.swift Child memory groups now use canonical names, agent display names, and lowercased group ids.
Sources/CmuxTopProcessNaming.swift Adds shared process-name canonicalization and per-snapshot coding-agent classification.
Sources/CmuxTopSnapshot.swift Program aggregates now skip classified agent processes and use canonical case-insensitive grouping.
Sources/TaskManagerSnapshot.swift Snapshot parsing now distinguishes absent program_totals from an intentionally empty list.
Sources/TaskManagerView.swift The memory summary tile now uses the Summed Footprint label and help text.
Resources/Localizable.xcstrings Adds English and Japanese strings for the renamed memory metric and help text.

Reviews (5): Last reviewed commit: "taskmanager: document why the agent memo..." | Re-trigger Greptile

Comment on lines +209000 to +209015
"taskManager.summary.summedFootprint": {
"extractionState": "manual",
"localizations": {
"ar": {
"stringUnit": {
"state": "translated",
"value": "الذاكرة"
}
},
"bs": {
"stringUnit": {
"state": "translated",
"value": "Memorija"
}
},
"da": {
"stringUnit": {
"state": "translated",
"value": "Hukommelse"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "Speicher"
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "Memory"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "Memoria"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Mémoire"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "Memoria"
"value": "Summed Footprint"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "メモリ"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "메모리"
}
},
"nb": {
"stringUnit": {
"state": "translated",
"value": "Minne"
}
},
"pl": {
"stringUnit": {
"state": "translated",
"value": "Pamięć"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "Memória"
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "Память"
}
},
"th": {
"stringUnit": {
"state": "translated",
"value": "หน่วยความจำ"
}
},
"tr": {
"stringUnit": {
"state": "translated",
"value": "Bellek"
}
},
"uk": {
"stringUnit": {
"state": "translated",
"value": "Пам’ять"
"value": "合計フットプリント"
}
},
"zh-Hans": {
}
}

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.

P1 Summary Label Falls Back

The new taskManager.summary.summedFootprint key only defines en and ja, while this catalog still has other supported locales and nearby memory summary keys include those translations. On a French, German, or other supported non-English/non-Japanese system, this changed Task Manager tile falls back to English next to translated summary labels.

Rule Used: Flag production user-facing text that is not fully... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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.

Intentional: cmux's supported localization set is currently English and Japanese (see CLAUDE.md localization policy), and the new key matches the sibling summary key taskManager.summary.cpu, which is also en+ja only. The broader locale list on the old taskManager.summary.memory key was legacy coverage; machine-copying it to a renamed label with different semantics would not count as localization under the repo policy.

— Claude Code

Comment on lines +209017 to 209032
"taskManager.summary.summedFootprint.help": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "内存"
"value": "Sum of each process's physical footprint. Shared memory (frameworks, dyld cache, IOSurfaces) is counted once per process, so this overstates real usage."
}
},
"zh-Hant": {
"ja": {
"stringUnit": {
"state": "translated",
"value": "記憶體"
"value": "各プロセスの物理フットプリントの合計です。共有メモリ(フレームワーク、dyldキャッシュ、IOSurface)はプロセスごとに重複して計上されるため、実際の使用量より大きく表示されます。"
}
}
}

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.

P1 Tooltip Text Falls Back

The new help text has the same locale gap as the label: only en and ja values are present in a catalog that still supports the other app locales. Users in those locales get an English tooltip for this production UI text instead of localized help.

Rule Used: Flag production user-facing text that is not fully... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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.

Same as the label key: en+ja is the repo's supported localization set (CLAUDE.md policy), matching sibling taskManager.summary.cpu. Additional locales are out of scope for this PR.

— Claude Code

Comment thread Sources/CmuxTopMemoryDiagnostics.swift Outdated
?? cmuxTopCanonicalProcessName(name: process.name, path: process.path)
.trimmingCharacters(in: .whitespacesAndNewlines)
let groupName = displayName.isEmpty ? "pid-\(pid)" : displayName
let key = groupName

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.

P1 Case Variants Split Groups

This changed the child-memory diagnostic key from the old case-insensitive process name to the case-preserved display name. If two child processes report the same executable with different casing, such as node and Node, they now become separate groups; because groups are sorted and limited by RSS, the real top child process group can be understated or omitted.

Suggested change
let key = groupName
let key = groupName.lowercased()

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.

Fixed in 84f78fa: the grouping key is lowercased again so casing variants fold into one group, while id/name keep the first-seen display casing. Added a node/Node regression assertion to memoryDiagnosticsFoldAgentsAndCanonicalizeChildGroups.

— Claude Code

@@ -0,0 +1,30 @@
import Foundation

nonisolated func cmuxTopCanonicalProcessName(name: String, path: String?) -> String {

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 Module-Wide Helper Surface

This production helper is added as an internal top-level function even though it is only used by the cmux top snapshot/grouping code. That creates new ambient module API for process-name behavior; keeping it private/fileprivate or moving it onto the owning snapshot/accounting type preserves the intended scoped ownership.

Rule Used: Flag new ambient global state in production Swift:... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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.

Keeping the free function: it is a pure, stateless name transform in its own domain file (CmuxTopProcessNaming.swift) with the cmuxTop prefix, matching existing top-level cmuxTop* declarations (cmuxTopMemoryDiagnosticDefaultGroupLimit, cmuxTopNegativeScopeTTLNanoseconds). It is consumed by two sibling files in the same accounting domain plus tests, so private/fileprivate is not possible, and attaching it as a static member to CmuxTopProcessSnapshot would just create a static-as-namespace surface on a type whose state it does not use.

— Claude Code

Program totals, coding-agent totals, and memory diagnostics each ran an
independent live agent-classification pass (KERN_PROCARGS2 sysctl per
candidate PID). Under process churn between payload sections the same
snapshot could exclude an agent from program_totals while omitting it
from coding_agents, and the argument reads ran up to 3x per refresh.

Memoize the per-PID definition (including nil results, via updateValue)
behind an NSLock on the snapshot so every payload section shares one
classification and the sysctl read runs at most once per PID.

Adds a regression test: classify while the agent process is alive,
reap it, and assert the same snapshot keeps the classification in both
program and coding-agent sections.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Sources/CmuxTopSnapshot.swift (1)

356-379: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Coding-agent definitions are recomputed independently across sibling summary methods.

codingAgentDefinitionsByPID(for: pids) is called separately here and in codingAgentSummaryPayload, and a third time in CmuxTopMemoryDiagnostics.memoryDiagnosticGroups. If a caller builds program rows, coding-agent rows, and memory-diagnostic groups from the same pid set in one refresh (likely, given they all derive from the app's descendant pids), this repeats the same per-pid classification (including processArgumentsIfNeeded's sysctl-based reads for candidates) up to 3x per refresh cycle.

Consider computing this map once per refresh and threading it through as an optional parameter (defaulting to a fresh computation for callers that only need one view), so the expensive classification isn't triple-computed on scalable process counts.

As per path instructions: "Apply .github/review-bot-rules/algorithmic-complexity.md during review. For production code over scalable user data, flag ... repeated sort/filter/map work in hot paths."

Also applies to: 432-450

🤖 Prompt for 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.

In `@Sources/CmuxTopSnapshot.swift` around lines 356 - 379, The same coding-agent
classification map is being recomputed in multiple summary paths, causing
repeated expensive per-pid work on each refresh. Update
CmuxTopSnapshot.programSummaryPayload, codingAgentSummaryPayload, and
CmuxTopMemoryDiagnostics.memoryDiagnosticGroups to accept and reuse a shared
codingAgentDefinitionsByPID result (with an optional parameter that defaults to
recomputing when called standalone), so the map is built once per pid set and
threaded through the sibling summary methods.

Source: Path instructions

🤖 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 `@Sources/CmuxTopProcessNaming.swift`:
- Around line 3-10: cmuxTopCanonicalProcessName is being used as cross-file API,
so it should not remain a file-scope free function. Move this logic onto
CmuxTopProcessSnapshot as a static method named canonicalProcessName(name:path:)
and update the callers in CmuxTopMemoryDiagnostics and CmuxTopSnapshot to use
Self.canonicalProcessName(name:path:). Keep the existing behavior unchanged
while making the symbol an owned API instead of an ambient top-level function.

---

Outside diff comments:
In `@Sources/CmuxTopSnapshot.swift`:
- Around line 356-379: The same coding-agent classification map is being
recomputed in multiple summary paths, causing repeated expensive per-pid work on
each refresh. Update CmuxTopSnapshot.programSummaryPayload,
codingAgentSummaryPayload, and CmuxTopMemoryDiagnostics.memoryDiagnosticGroups
to accept and reuse a shared codingAgentDefinitionsByPID result (with an
optional parameter that defaults to recomputing when called standalone), so the
map is built once per pid set and threaded through the sibling summary methods.
🪄 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: c34901c8-7730-4193-bb78-a5a33b9ebc3f

📥 Commits

Reviewing files that changed from the base of the PR and between b51ee74 and ebb2f16.

📒 Files selected for processing (8)
  • CLI/cmux.swift
  • Resources/Localizable.xcstrings
  • Sources/CmuxTopMemoryDiagnostics.swift
  • Sources/CmuxTopProcessNaming.swift
  • Sources/CmuxTopSnapshot.swift
  • Sources/TaskManagerView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/CmuxTopAccountingGroupingTests.swift

Comment thread Sources/CmuxTopProcessNaming.swift
Comment thread Sources/CmuxTopMemoryDiagnostics.swift Outdated
Restore the lowercased grouping key from main so casing variants of the
same executable fold into one child-memory group (Greptile finding);
group id/name keep the first-seen display casing. Extends the grouping
test with a node/Node case-variant assertion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 84f78fa. Configure here.

Comment thread Sources/CmuxTopProcessNaming.swift Outdated
austinywang and others added 3 commits July 8, 2026 02:40
Review round 2 fixes:

- The Task Manager payload parser treated a present-but-empty
  program_totals array as a missing legacy field and recomputed program
  aggregates client-side from process rows, which recreated the very
  coding-agent program rows the backend now intentionally filters out
  (e.g. two Claude processes and no other duplicated program). Fall back
  to client aggregation only when the field is absent, and cover both
  cases with a parser regression test.

- Wrap the per-snapshot agent-classification cache in
  CmuxTopCodingAgentDefinitionMemo with a private lock and private
  dictionary so no module code can touch the mutable state without the
  lock, preserving the snapshot's @unchecked Sendable safety argument.

- Update testUnavailableMemorySourcesAreExposedInAggregatePayloads for
  the agents-excluded program-rows semantics: a non-agent worker pair
  keeps the program-aggregate unavailable-memory coverage and a codex
  pair keeps the coding-agent coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Keep the group id equal to the lowercased grouping key (main's stable
semantics) so folded case-variant groups don't flip ids across samples
and churn childMemoryAggregate row identity; only the display name keeps
first-seen casing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment-only. Names the constraint (synchronous nonisolated payload
builders in the socket pipeline) that makes actor isolation a larger
out-of-scope refactor; conscious exception to the actor-first policy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lawrencecchen lawrencecchen added the stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening. label Sep 23, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in cmux backlog Sep 23, 2026

This branch was successfully deployed

1 active deployment
Preview – cmux — 6c42590c Deployed Jul 8, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants