Skip to content

Add AppKit signal todo lab - #8388

Closed
lawrencecchen wants to merge 2 commits into
mainfrom
feat-appkit-signals
Closed

lawrencecchen wants to merge 2 commits into
mainfrom
feat-appkit-signals

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Jul 18, 2026 •

Copy link
Copy Markdown
Contributor

Implements a DEBUG-only native AppKit experiment based on Solid’s signal model: https://docs.solidjs.com/concepts/signals

The new main-actor signal graph provides writable signals, cached memos, effects with cleanup, equality suppression, dynamic dependency replacement, and batched propagation. A three-pane operations dashboard exercises the graph through filters, search, metrics, task selection, controls, a pulse chart, and an activity feed. The experiment contains no SwiftUI, Observation, or Combine dependencies.

Adds a Debug menu entry and debug.appkit_signal_lab.show command. debug.window.screenshot now accepts window_identifier so auxiliary AppKit windows can be captured directly.

Verification:

  • swift test --package-path Packages/macOS/CmuxAppKitSupportUI --filter SignalGraphTests
  • swift test --package-path Packages/macOS/CmuxControlSocket
  • Tagged cloud build siglab
  • Opened the lab through its debug command, captured its window, and exercised the simulation button through Accessibility

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


Summary by cubic

Adds a DEBUG-only AppKit Signals Lab as a native “Signal Todo List” driven by a main-actor reactive graph (Solid-style signals) for fine-grained UI updates. Adds a debug menu item, debug.appkit_signal_lab.show, and targeted window screenshots via debug.window.screenshot.

  • New Features
    • Reactive core: writable signals, cached memos, effects with cleanup, dynamic dependency tracking, equality suppression, and batched propagation (tests included).
    • Lab UI: AppKit window with a three-pane todo dashboard (filters/search, work list table, inspector with progress/priority/capacity/automation), pulse chart, and activity feed; localized in EN/JA.
    • Debug integration: DebugWindowsCoordinator.showAppKitSignalLabWindow() and localized “Signal Todo List…” menu entry; control command debug.appkit_signal_lab.show; debug.window.screenshot accepts window_identifier to capture auxiliary windows.
    • Tests: SignalGraphTests, AppKitSignalLabModelTests, and coordinator tests for command routing and screenshot targeting.

Written for commit cd43859. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added an AppKit “Signal Todo List” (Signals Lab) debug window with searchable task list, status filtering, live metrics, task inspection, and progress/control actions.
    • Added a Debug menu item and a corresponding debug command to open the Signals Lab.
  • Debugging
    • Screenshot debugging can now target an optional auxiliary window.
  • Tests
    • Added/expanded test coverage for the Signals Lab model, reactive update behavior (including batching and cleanup), debug command routing for opening the lab, and targeted screenshot handling.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds an AppKit Signals Lab with reactive state, task simulation, metrics, filtering, inspector controls, localized UI, menu/debug-command access, and targeted screenshot capture for the auxiliary window.

Changes

AppKit Signals Lab

Layer / File(s) Summary
Reactive signal foundation
Packages/macOS/CmuxAppKitSupportUI/.../AppKitSignalLab/Reactive/*, Packages/macOS/CmuxAppKitSupportUI/Tests/.../SignalGraphTests.swift
Adds main-actor signals, memos, effects, dependency tracking, batching, cleanup, weak observers, and behavioral coverage.
Signal Lab model and state
Packages/macOS/CmuxAppKitSupportUI/.../AppKitSignalLab/Model/*, Packages/macOS/CmuxAppKitSupportUI/Tests/.../AppKitSignalLabModelTests.swift
Adds task/status/filter/metrics models, derived state, seeded fixtures, selection, simulation, status transitions, activity logging, task controls, and model tests.
AppKit interface and window
Packages/macOS/CmuxAppKitSupportUI/.../AppKitSignalLab/Views/*, Packages/macOS/CmuxAppKitSupportUI/.../AppKitSignalLab/Windows/*, Resources/Localizable.xcstrings
Adds the native window, work list, filters, metrics, inspector, reactive bindings, pulse visualization, and localized strings.
Debug commands and screenshot targeting
Sources/cmuxApp.swift, Sources/TerminalController*, Packages/macOS/CmuxControlSocket/.../Debug/*, Packages/macOS/CmuxControlSocket/Tests/.../*
Adds menu and socket commands for opening the lab, updates debug seams, and supports optional auxiliary-window screenshot identifiers with tests.

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

Sequence Diagram(s)

sequenceDiagram
  participant DebugClient
  participant ControlCommandCoordinator
  participant TerminalController
  participant DebugWindowsCoordinator
  participant AppKitSignalLabWindowController
  DebugClient->>ControlCommandCoordinator: debug.appkit_signal_lab.show
  ControlCommandCoordinator->>TerminalController: controlDebugShowAppKitSignalLab()
  TerminalController->>DebugWindowsCoordinator: showAppKitSignalLabWindow()
  DebugWindowsCoordinator->>AppKitSignalLabWindowController: create or reuse and show
  AppKitSignalLabWindowController-->>DebugClient: shown: true
Loading

Important

Pre-merge checks failed

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

❌ Failed checks (2 errors, 1 warning)

Check name Status Explanation Resolution
Cmux Algorithmic Complexity ❌ Error SignalGraph.flush() rescans pendingObservers with min(by:) inside a loop, making batched delivery O(n²) on a hot runtime path. Replace the repeated min(by:) scan with a priority queue or priority buckets so flush is one-pass over pending observers.
Cmux Swift Auxiliary Window Close Shortcuts ❌ Error AppKitSignalLabWindowController uses stable id cmux.appKitSignalsLab, but it isn’t registered in cmuxAuxiliaryWindowIdentifiers; the CI lint script flags this literal assignment. Register cmux.appKitSignalsLab in cmuxAuxiliaryWindowIdentifiers (or mark it ignored if it must never own Cmd+W); scripts/lint_auxiliary_window_close_shortcuts.py will then pass.
Docstring Coverage ⚠️ Warning Docstring coverage is 11.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (22 passed)
Check name Status Explanation
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 New AppKit Signal Lab types and the debug seam are explicitly @MainActor, and no new Sendable/nonisolated background-access patterns appear in the feature sources.
Cmux Swift Blocking Runtime ✅ Passed No new waits, semaphores, sleeps, syncs, or locks were introduced; the new AppKit Signal Lab code is MainActor-isolated and uses synchronous-but-nonblocking propagation.
Cmux Browser Automation Off-Main ✅ Passed PASS: The diff only adds the AppKit Signal Lab UI/models and a debug menu entry; it does not change browser automation routing, worker policy, or WebKit-waiting commands.
Cmux Expensive Synchronous Load ✅ Passed Touched debug/menu/window entrypoints only open the lab; no new RestorableAgentSessionIndex.load, JSON decode, directory scan, or transcript/JSONL parsing on main or socket paths.
Cmux Cache Substitution Correctness ✅ Passed Only transient UI/reactive caches were added; the screenshot path still reads live NSApp.windows and no persistence/history/undo cache substitution appears.
Cmux No Hacky Sleeps ✅ Passed No changed TypeScript/JavaScript/shell/build-runtime files; the diff is Swift, tests, and localization only, so the no-hacky-sleeps rule isn’t implicated.
Cmux Swift Concurrency ✅ Passed PASS: the new AppKit Signal Lab code is main-actor synchronous; no new background queues, Combine app state, completion-handler APIs, or fire-and-forget Tasks were added.
Cmux Swift @Concurrent ✅ Passed No added @concurrent or nonisolated async violations found; the new AppKit Signal Lab APIs are sync and @MainActor-bound, and the screenshot helper remains synchronous.
Cmux Swift Package Boundaries ✅ Passed The new signal graph/model/UI live in the CmuxAppKitSupportUI SwiftPM package, and the app-target edits are allowed debug-menu/AppKit glue.
Cmux Swiftpm Lockfiles ✅ Passed No Package.swift, Package.resolved, .gitignore, or xcodeproj dependency changes appear in the diff, so the lockfile policy isn’t triggered.
Cmux Swift Logging ✅ Passed No added or materially changed print/debugPrint/dump/NSLog or ad hoc stdout logging appears in the touched Swift files; hits in cmuxApp.swift are preexisting.
Cmux User-Facing Error Privacy ✅ Passed New/changed user-facing errors are generic ('Control context unavailable', 'AppKit Signals Lab unavailable'); no vendor names, secrets, or raw upstream messages were added.
Cmux Full Internationalization ✅ Passed The lab is only reachable via #if DEBUG menu/socket routes, and its visible Swift text uses localized APIs; the catalog entries are debug-only prototype copy.
Cmux Swiftui State Layout ✅ Passed No new SwiftUI state/layout patterns were introduced; the only SwiftUI edit was a menu label string, and the lab UI is AppKit-only.
Cmux Architecture Rethink ✅ Passed The PR adds a single main-actor signal owner and one coordinator-owned lab window with no sleeps, polling, locks, or split lifecycle repair paths.
Cmux Source Artifacts ✅ Passed Changed paths are hand-written source, tests, and a localization catalog; none are logs, caches, temp, build, or other artifact directories per the rule.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Added debug UI/command plumbing is a real DEBUG-only feature isolated in debug files/menu paths, not a test-observability accessor in shipping state.
Cmux No Ambient Global State ✅ Passed No new file-scope mutable state or singleton-style runtime state was added; the new AppKit lab state is instance-owned by injected model/coordinator types.
Title check ✅ Passed The title clearly summarizes the main change: adding the AppKit signal todo lab.
Description check ✅ Passed The description covers the feature, motivation, testing, and manual verification for the AppKit signal lab.
✨ 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-appkit-signals

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 18, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds a DEBUG-only native AppKit experiment built on a Solid-style fine-grained reactive graph (signals, memos, effects with cleanup, batched propagation) and a three-pane operations dashboard that drives AppKit controls directly. No SwiftUI, Observation, or Combine is used. Entry points are gated by #if DEBUG at the app and control-socket layer; debug.window.screenshot is extended with an optional window_identifier parameter to target the lab window directly.

  • Reactive core (SignalGraph, Signal, SignalMemo, SignalEffect): all @MainActor-isolated, with Signal and SignalMemo carrying public access modifiers and no #if DEBUG guard in production Sources/ (flagged in an earlier review thread; the entry-point guards do not remove the types from the release binary).
  • Lab UI (AppKitSignalLabViewController, AppKitSignalLabWindowController, AppKitSignalLabModel): 686-line view controller wiring ~5 effects to an 8-task fixture; NumberFormatter for percent display is correctly allocated once and reused across table rows.
  • Control socket (ControlCommandCoordinator+Debug, ControlDebugContext): debug.appkit_signal_lab.show is a direct show-window call with no WebKit waits; debug.window.screenshot correctly falls back to key/main window when no window_identifier is supplied.

Confidence Score: 5/5

No new correctness bugs were found in this review; issues raised in earlier threads (missing guards and incomplete locale coverage) remain open but are unchanged.

The reactive graph implementation is internally consistent — signals update their stored value immediately, memos detach and retrack dependencies on each run, effects dispose cleanly, and batch propagation correctly defers flush until batchDepth reaches zero. The control-socket integration for debug.appkit_signal_lab.show is a direct show-window call with no WebKit waits, correctly listed in debugMethodNames. The debug.window.screenshot extension falls back correctly through explicit identifier → key window → main window → largest window. The AppKitSignalLabModel batch mutations keep signal state self-consistent. The NumberFormatter for percent display is allocated once as a stored property. No new actor isolation mistakes, blocking primitives, or ambient global state were introduced.

No files require special attention beyond what was already flagged in prior review threads.

Important Files Changed

Filename Overview
Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Reactive/SignalGraph.swift New reactive graph owning batched propagation and dependency tracking; public access with no #if DEBUG guard compiles into the release binary (flagged in prior thread). Flush loop is correct but O(n²) for large observer sets.
Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Reactive/SignalEffect.swift Correct cleanup/detach lifecycle; MainActor.assumeIsolated in deinit is safe in practice given all callers are @MainActor, but is not formally guaranteed by Swift's actor deinit rules.
Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Model/AppKitSignalLabModel.swift Signal graph wiring is correct; batched mutations keep state consistent; NumberFormatter for percent display is allocated once as a stored property on the VC, so no per-row formatter allocation.
Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Views/AppKitSignalLabViewController.swift 686-line view controller; percentFormatter correctly reused across table rows; effects correctly held in an array for lifecycle.
Sources/TerminalController.swift Refactors captureScreenshot to a labeled overload accepting an optional window_identifier; lookup logic correctly prefers explicitly targeted window over key/main window fallback; ISO8601DateFormatter allocation is pre-existing.
Resources/Localizable.xcstrings Adds ~45 new debug.signalLab.* keys with only en and ja translations; the catalog supports many additional locales (flagged in a prior thread).

Reviews (2): Last reviewed commit: "Turn signals lab into todo app" | Re-trigger Greptile

Comment on lines +1 to +8
/// Owns synchronous dependency tracking and batched propagation for signals.
///
/// `SignalGraph` follows Solid's fine-grained model: reading a signal inside an
/// effect or memo records the dependency automatically, and writing a distinct
/// value schedules only the observers that read it. All access is main-actor
/// isolated so AppKit controls can be updated directly without locks.
@MainActor
public final class SignalGraph {

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 Debug-only experiment missing #if DEBUG guards in production Sources

The PR description explicitly calls this a "DEBUG-only native AppKit experiment," and all entry points (DebugWindowsCoordinator.showAppKitSignalLabWindow(), controlDebugShowAppKitSignalLab(), the Debug menu item in cmuxApp.swift) are properly #if DEBUG-gated. However, the underlying implementation — SignalGraph, Signal, SignalMemo, SignalEffect, SignalEffectContext, SignalObserver, SignalDependency, WeakSignalObserver, AppKitSignalLabModel, AppKitSignalLabWindowController, and AppKitSignalLabViewController — all compile into the release binary as dead code because their source files in production Sources/ carry no #if DEBUG guard (only #if canImport(AppKit) where present). Per cmux-no-test-debug-seam-in-production-source, a facility with no production caller should be isolated in a dedicated debug file or folder behind a #if DEBUG guard; the folder exists here but the file-level guards are absent. The fix is to wrap each file in #if DEBUG … #endif, matching the pattern used in DebugWindowsCoordinator.swift.

Rule Used: Flag Swift files under a production Sources path (... (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!

Comment on lines +73588 to +73593
"debug.signalLab.activity.advanced": {
"extractionState": "manual",
"localizations": {
"en": {"stringUnit": {"state": "translated", "value": "Selected work item advanced in one batch."}},
"ja": {"stringUnit": {"state": "translated", "value": "選択した作業項目を1回のバッチで進めました。"}}
}

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 New string-catalog keys missing translations for existing catalog locales

The new debug.signalLab.* keys added to this catalog only provide en and ja entries. The existing catalog supports many additional locales (ar, bs, da, de, es, fr, it, ko, nl, pl, pt-BR, ru, tr, uk, zh-Hans, zh-Hant, and others visible in surrounding keys like about.appName). Per cmux-full-internationalization, catalog additions must include translated entries for every locale already supported by the touched catalog. All ~45 newly added keys follow the same two-locale pattern. If these strings are intended exclusively for the debug experiment and should never appear in production, the clean fix is to also add #if DEBUG guards to the implementation files (so the keys never ship in production catalog builds), otherwise translations for all supported locales are required.

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

@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: 3

🤖 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
`@Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Model/AppKitSignalLabModel.swift`:
- Around line 93-95: Update the task transition logic around Self.nextStatus in
AppKitSignalLabModel so any task whose next status is .complete has its progress
normalized to 1. Preserve the incremental progress for non-completed statuses
and ensure status and progress remain consistent.

In
`@Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Views/AppKitSignalLabViewController.swift`:
- Around line 488-491: Update visibleCountLabel and the filter-label formatting
around the affected view-controller code to use complete localized plural
messages, with explicit .one and .other catalog entries rather than appending
counts outside localization. Add matching entries for the visible-count and
every filter label in all supported locale catalogs, preserving the count value
and allowing locale-specific grammar and word order.

In `@Sources/TerminalController.swift`:
- Around line 12840-12848: Update the window selection logic around
explicitlyTargetedWindow so that when windowIdentifier is provided, only the
matching window is used; if no match exists, return or otherwise fail closed
without falling back to preferredWindow, candidateWindows heuristics,
NSApp.mainWindow, or NSApp.windows. Preserve the existing fallback chain only
when no explicit identifier is supplied.
🪄 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: a48189ff-9a81-4c70-bde9-8f5711b2e4dd

📥 Commits

Reviewing files that changed from the base of the PR and between c8138f4 and c936ca7.

📒 Files selected for processing (29)
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AboutTitlebarDebug/Coordinator/DebugWindowsCoordinator.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Model/AppKitSignalLabFilter.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Model/AppKitSignalLabMetrics.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Model/AppKitSignalLabModel.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Model/AppKitSignalLabStatus.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Model/AppKitSignalLabTask.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Reactive/Signal.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Reactive/SignalDependency.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Reactive/SignalEffect.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Reactive/SignalEffectContext.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Reactive/SignalGraph.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Reactive/SignalMemo.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Reactive/SignalObserver.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Reactive/WeakSignalObserver.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Views/AppKitSignalLabViewController.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Views/SignalLabPulseView.swift
  • Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Windows/AppKitSignalLabWindowController.swift
  • Packages/macOS/CmuxAppKitSupportUI/Tests/CmuxAppKitSupportUITests/SignalGraphTests.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Debug/ControlCommandCoordinator+Debug.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Debug/ControlCommandCoordinator+Debug2.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Debug/ControlCommandCoordinator+DebugV1.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Debug/ControlDebugContext.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandContextTestStubs+Debug.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandCoordinatorDebugV1Tests.swift
  • Resources/Localizable.xcstrings
  • Sources/TerminalController+ControlDebugContext.swift
  • Sources/TerminalController+DebugMethodNames.swift
  • Sources/TerminalController.swift
  • Sources/cmuxApp.swift

Comment on lines +488 to +491
visibleCountLabel.stringValue = String(
format: String(localized: "debug.signalLab.visibleCount", defaultValue: "%lld visible"),
Int64(tasks.count)
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Localize the complete count labels with plural variants.

visibleCountLabel uses one key for all counts, while the filter labels append counts outside localization. Add complete .one/.other catalog entries for the visible count and each filter so translators control plural grammar and word order across every supported locale.

As per coding guidelines, user-facing text must use localized APIs and matching catalogs. As per path instructions, touched catalogs must cover every supported locale. Based on learnings, count strings should use explicit .one and .other keys.

Also applies to: 514-517

🤖 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
`@Packages/macOS/CmuxAppKitSupportUI/Sources/CmuxAppKitSupportUI/AppKitSignalLab/Views/AppKitSignalLabViewController.swift`
around lines 488 - 491, Update visibleCountLabel and the filter-label formatting
around the affected view-controller code to use complete localized plural
messages, with explicit .one and .other catalog entries rather than appending
counts outside localization. Add matching entries for the visible-count and
every filter label in all supported locale catalogs, preserving the count value
and allowing locale-specific grammar and word order.

Sources: Coding guidelines, Path instructions, Learnings

Comment on lines +12840 to 12848
let explicitlyTargetedWindow = windowIdentifier.flatMap { identifier in
candidateWindows.first { $0.identifier?.rawValue == identifier }
}
let preferredWindow = [NSApp.keyWindow, NSApp.mainWindow]
.compactMap { $0 }
.first { candidateWindows.contains($0) }
let window = preferredWindow ?? candidateWindows.max { lhs, rhs in
let window = explicitlyTargetedWindow ?? preferredWindow ?? candidateWindows.max { lhs, rhs in
(lhs.frame.width * lhs.frame.height) < (rhs.frame.width * rhs.frame.height)
} ?? NSApp.mainWindow ?? NSApp.windows.first

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fail closed when an explicit window identifier is not found.

When windowIdentifier is provided but no matching window is found, the current logic falls back to capturing preferredWindow or another heuristic. This violates the path instruction to treat the explicit windowIdentifier as the single authoritative source of truth and fail closed if it is unavailable, avoiding "best effort" fallbacks that capture the wrong window.

🐛 Proposed fix
             let explicitlyTargetedWindow = windowIdentifier.flatMap { identifier in
                 candidateWindows.first { $0.identifier?.rawValue == identifier }
             }
+            
+            if windowIdentifier != nil && explicitlyTargetedWindow == nil {
+                captureError = "No window found for explicit identifier"
+                return
+            }
+
             let preferredWindow = [NSApp.keyWindow, NSApp.mainWindow]
                 .compactMap { $0 }
                 .first { candidateWindows.contains($0) }
             let window = explicitlyTargetedWindow ?? preferredWindow ?? candidateWindows.max { lhs, rhs in
                 (lhs.frame.width * lhs.frame.height) < (rhs.frame.width * rhs.frame.height)
             } ?? NSApp.mainWindow ?? NSApp.windows.first
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let explicitlyTargetedWindow = windowIdentifier.flatMap { identifier in
candidateWindows.first { $0.identifier?.rawValue == identifier }
}
let preferredWindow = [NSApp.keyWindow, NSApp.mainWindow]
.compactMap { $0 }
.first { candidateWindows.contains($0) }
let window = preferredWindow ?? candidateWindows.max { lhs, rhs in
let window = explicitlyTargetedWindow ?? preferredWindow ?? candidateWindows.max { lhs, rhs in
(lhs.frame.width * lhs.frame.height) < (rhs.frame.width * rhs.frame.height)
} ?? NSApp.mainWindow ?? NSApp.windows.first
let explicitlyTargetedWindow = windowIdentifier.flatMap { identifier in
candidateWindows.first { $0.identifier?.rawValue == identifier }
}
if windowIdentifier != nil && explicitlyTargetedWindow == nil {
captureError = "No window found for explicit identifier"
return
}
let preferredWindow = [NSApp.keyWindow, NSApp.mainWindow]
.compactMap { $0 }
.first { candidateWindows.contains($0) }
let window = explicitlyTargetedWindow ?? preferredWindow ?? candidateWindows.max { lhs, rhs in
(lhs.frame.width * lhs.frame.height) < (rhs.frame.width * rhs.frame.height)
} ?? NSApp.mainWindow ?? NSApp.windows.first
🤖 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/TerminalController.swift` around lines 12840 - 12848, Update the
window selection logic around explicitlyTargetedWindow so that when
windowIdentifier is provided, only the matching window is used; if no match
exists, return or otherwise fail closed without falling back to preferredWindow,
candidateWindows heuristics, NSApp.mainWindow, or NSApp.windows. Preserve the
existing fallback chain only when no explicit identifier is supplied.

Source: Path instructions

@lawrencecchen lawrencecchen changed the title Add AppKit signals lab Add AppKit signal todo lab Jul 18, 2026
@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
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.

2 participants