Skip to content

[codex] add context to v2 macOS notifications#4614

Merged
Kitenite merged 5 commits into
mainfrom
improve-macos-notificatio
May 16, 2026
Merged

[codex] add context to v2 macOS notifications#4614
Kitenite merged 5 commits into
mainfrom
improve-macos-notificatio

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented May 16, 2026

Summary

Adds richer native macOS notification content for v2 workspace agent lifecycle events. Instead of generic Agent Complete / Your agent has finished copy, notifications now include the agent label, workspace name, pane label, and tab label when available.

Why

The v2 notification pipeline already receives agent identity and can resolve workspace/pane layout context, but the native notification copy only used generic text. That made it hard to tell which agent, pane, or workspace finished when multiple agents were running.

Changes

  • Threads workspace display names into the v2 host notification subscriber.
  • Adds a focused notification content formatter for agent, workspace, pane, tab, terminal title, and fallback labels.
  • Uses the formatter when showing native notifications from v2 lifecycle events.
  • Adds unit coverage for completion, permission request, and fallback notification content.

Validation

  • bun test apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.test.ts apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/resolveV2NotificationTarget.test.ts apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/statusTransitions.test.ts
  • bun run lint
  • bun run --cwd apps/desktop typecheck

Open in Stage

Summary by cubic

Switches v2 macOS notifications to agent‑first titles and a simpler body. Titles are “{Agent} - Complete/Needs Attention”; the body shows only the workspace name.

  • New Features
    • Title format: “{Agent} - Complete” or “Needs Attention” for permission requests.
    • Body: “{WorkspaceName}” (trimmed; falls back to namebranch → “Workspace”).
    • Agent labels resolve via @superset/shared/agent-catalog or humanized ids; threaded workspaceName through and added unit tests.

Written for commit d203239. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features
    • Notifications now display a cleaned workspace name (trimmed, falling back to branch or generic "Workspace") and use concise native notification titles combining agent label + action.
  • Bug Fixes
    • Removed noisy/ambiguous label content and simplified title selection for clearer notifications.
  • Tests
    • Added tests for notification title/body generation, permission-request wording, and fallback labeling.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 16, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5b529d5a-39d5-4155-bdff-eeef804d9b30

📥 Commits

Reviewing files that changed from the base of the PR and between 727e2e4 and d203239.

📒 Files selected for processing (2)
  • apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts

📝 Walkthrough

Walkthrough

Adds workspace display fields to host grouping and threads a derived workspaceName through the notification pipeline; introduces getV2NativeNotificationContent to produce native notification title/body and updates the lifecycle handler and tests to use it.

Changes

V2 Notification Workspace Metadata and Content

Layer / File(s) Summary
Workspace metadata propagation
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/V2NotificationController.tsx, apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/components/HostNotificationSubscriber/HostNotificationSubscriber.tsx
Query selection extended to include workspace name and branch; WorkspaceHostRow and HostNotificationWorkspaceState now carry these fields. workspaceName is derived from trimmed name, then trimmed branch, with final fallback "Workspace".
Native notification content generator
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts
Adds getV2NativeNotificationContent({ workspaceName, payload }) that returns { title, body }. Resolves an agent label via builtins or humanization and composes a title (e.g., "Agent - Needs Attention" / "Agent - Complete") and a single-line workspace body (cleaned workspaceName or "Workspace").
Lifecycle event handler integration
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/lifecycleEvents.ts
handleV2AgentLifecycleEvent signature accepts workspaceName; it imports getV2NativeNotificationContent and uses it to compute notification title/body before calling the native show mutation. The handler forwards workspaceName from the subscriber.
Notification content tests
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.test.ts
New tests for getV2NativeNotificationContent validating completion and permission-request titles and workspace/agent fallback behavior; includes a payload() helper for fixtures.

Sequence Diagram(s)

sequenceDiagram
  participant HostSubscriber as HostNotificationSubscriber
  participant Lifecycle as handleV2AgentLifecycleEvent
  participant ContentGen as getV2NativeNotificationContent
  participant NativeAPI as NativeNotificationShow

  HostSubscriber->>Lifecycle: agent:lifecycle + workspaceId + workspaceName + payload
  Lifecycle->>ContentGen: getV2NativeNotificationContent({ workspaceName, payload })
  ContentGen-->>Lifecycle: { title, body }
  Lifecycle->>NativeAPI: show native notification with title/body
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰
I trimmed the name, then hopped to branch,
Wrapped agent whispers in tidy stance,
A title, a body — neat as can be,
Workspace now sings for all to see.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title '[codex] add context to v2 macOS notifications' clearly and concisely summarizes the main change: adding richer contextual content to native macOS notifications for v2 workspace agent lifecycle events.
Description check ✅ Passed The pull request description is comprehensive and well-structured, covering summary, rationale, changes, and validation details. However, it does not follow the template's required sections (Type of Change, Testing, etc.) from the description_template.
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.

✏️ 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 improve-macos-notificatio

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

@stage-review
Copy link
Copy Markdown

stage-review Bot commented May 16, 2026

Ready to review this PR? Stage has broken it down into 4 individual chapters for you:

Title
1 Implement notification content formatting logic
2 Expose workspace names in notification controller
3 Thread workspace name through notification subscriber
4 Integrate rich content into native notifications
Open in Stage

Chapters generated by Stage for commit d203239 on May 16, 2026 12:53am UTC.

@Kitenite Kitenite marked this pull request as ready for review May 16, 2026 00:26
@capy-ai
Copy link
Copy Markdown

capy-ai Bot commented May 16, 2026

Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews.

Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

No issues found across 5 files

Re-trigger cubic

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts (1)

112-113: 💤 Low value

Redundant typeof check in tab index validation.

The indexOf method always returns a number, so the typeof index === "number" check is redundant. Only the index >= 0 check is needed.

♻️ Simplified version
 	const explicitTitle = cleanLabel(tab.titleOverride);
 	if (explicitTitle) return explicitTitle;
 	const index = paneLayout?.tabs.indexOf(tab);
-	return typeof index === "number" && index >= 0 ? `Tab ${index + 1}` : null;
+	return index !== undefined && index >= 0 ? `Tab ${index + 1}` : null;
🤖 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
`@apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts`
around lines 112 - 113, The check for typeof index is redundant because
Array#indexOf always returns a number; update the conditional in the expression
that computes the tab label (where paneLayout?.tabs.indexOf(tab) is assigned to
index and used to return `Tab ${index + 1}`) to only test index >= 0 and drop
the typeof check so the return becomes a simple index >= 0 ? `Tab ${index + 1}`
: null.
🤖 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.

Nitpick comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts`:
- Around line 112-113: The check for typeof index is redundant because
Array#indexOf always returns a number; update the conditional in the expression
that computes the tab label (where paneLayout?.tabs.indexOf(tab) is assigned to
index and used to return `Tab ${index + 1}`) to only test index >= 0 and drop
the typeof check so the return becomes a simple index >= 0 ? `Tab ${index + 1}`
: null.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 89a50a8c-1ef4-4973-aff2-bb9e9ef0ae7e

📥 Commits

Reviewing files that changed from the base of the PR and between da0282c and 7f19311.

📒 Files selected for processing (5)
  • apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/V2NotificationController.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/components/HostNotificationSubscriber/HostNotificationSubscriber.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/lifecycleEvents.ts
  • apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 16, 2026

Greptile Summary

This PR enriches native macOS notifications for v2 agent lifecycle events by adding contextual labels (agent, workspace, pane, tab) instead of the previous generic "Agent Complete / Your agent has finished" copy. The notification pipeline already carried agent identity; this change threads workspace display names and pane layout data through to a new getV2NativeNotificationContent formatter and wires it into the notification render path.

  • notificationContent.ts — new formatter that resolves agent label (with BUILTIN_AGENT_LABELS lookup and humanizeIdentifier fallback), workspace name (name → branch → id), pane label (title override → runtime terminal title → kind label → short terminal ID), and tab label (title override → "Tab N" index), then composes them into title / body.
  • lifecycleEvents.tsshowNativeNotification now calls terminalRuntimeRegistry.getTitle with the pane ID as the instance discriminator (matching how TerminalPane registers entries) before falling back to the primary entry, and passes both workspaceName and paneLayout to the formatter.
  • V2NotificationController.tsx — the workspace live-query now selects name and branch (both notNull columns) and computes workspaceName before grouping by host URL.

Confidence Score: 4/5

Safe to merge; changes are isolated to the notification formatting path and do not touch agent execution, data persistence, or auth flows.

The notification formatter is well-structured with graceful fallbacks at every label level and the unit tests cover the main scenarios. Two minor points worth a quick look: the PANE_KIND_LABELS index type hides an implicit runtime undefined from TypeScript, and shortId can produce 'Terminal terminal' for the rare case where the terminal ID is exactly the stripped prefix. Neither affects correctness for real workspaces.

apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts — the PANE_KIND_LABELS typing and shortId fallback logic

Important Files Changed

Filename Overview
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts New file: formats notification title/body from agent, workspace, pane, and tab labels with clean fallback chains; PANE_KIND_LABELS typed as Record<string, string> makes the runtime undefined case invisible to TypeScript
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.test.ts New test file: covers completion, permission-request, and fallback label cases; test assertions match production logic
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/lifecycleEvents.ts Threads workspaceName and paneLayout into showNativeNotification; correctly uses paneId as the registry instanceId for a more specific getTitle lookup, then falls back to the primary entry
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/V2NotificationController.tsx Adds name/branch columns to the workspace live-query and computes workspaceName (name → branch → id) before passing to subscriber groups; both columns are notNull in schema so .trim() is safe
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/components/HostNotificationSubscriber/HostNotificationSubscriber.tsx Straightforward interface extension: adds workspaceName to HostNotificationWorkspaceState and threads it through to handleV2AgentLifecycleEvent

Sequence Diagram

sequenceDiagram
    participant HS as HostNotificationSubscriber
    participant LE as lifecycleEvents
    participant RNT as resolveV2NotificationTarget
    participant TRR as terminalRuntimeRegistry
    participant NC as notificationContent
    participant TRPC as electronTrpcClient

    HS->>LE: handleV2AgentLifecycleEvent(workspaceId, workspaceName, payload, paneLayout)
    LE->>RNT: resolveV2NotificationTarget(workspaceId, payload, paneLayout)
    RNT-->>LE: "V2NotificationTarget {tabId, paneId, terminalId}"
    LE->>LE: shouldSuppress(target, paneLayout)?
    LE->>TRR: getTitle(terminalId, paneId)
    TRR-->>LE: terminalTitle or undefined
    Note over LE,TRR: Falls back to getTitle(terminalId) if first returns empty
    LE->>NC: getV2NativeNotificationContent(workspaceName, payload, target, paneLayout, terminalTitle)
    Note over NC: Resolves agentLabel, workspaceLabel, paneLabel, tabLabel
    NC-->>LE: "{title, body}"
    LE->>TRPC: "notifications.showNative({title, body, clickTarget})"
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts:26
The `PANE_KIND_LABELS` map is typed as `Record<string, string>`, so TypeScript considers every index access to always return `string`. At runtime, accessing a key that isn't in the map returns `undefined`, making the `??` fallback on line 100 necessary but invisible to the type checker. Narrowing the type to `Partial<Record<string, string>>` makes the index signature honest and lets TypeScript verify the nullish coalescing is needed.

```suggestion
const PANE_KIND_LABELS: Partial<Record<string, string>> = {
```

### Issue 2 of 2
apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts:132-136
When `terminalId` is a string whose only content is the "terminal" prefix itself (e.g. exactly `"terminal"` or `"terminal-"`), `replace` strips it to an empty string and `candidate` falls back to the original value. With `candidate = "terminal-"` (9 chars), `slice(0, 8)` returns `"terminal"`, so the body becomes `"Pane: Terminal terminal"` — a doubled word. A guard for the empty-suffix case avoids this.

```suggestion
function shortId(value: string): string {
	const withoutTerminalPrefix = value.replace(/^terminal[-_:]?/i, "");
	const candidate = withoutTerminalPrefix || value;
	// If stripping the prefix left nothing meaningful, keep the original.
	if (!withoutTerminalPrefix) return value.length > 8 ? value.slice(0, 8) : value;
	return candidate.length > 8 ? candidate.slice(0, 8) : candidate;
}
```

Reviews (1): Last reviewed commit: "Adjust v2 notification copy" | Re-trigger Greptile

pane?: Pane<PaneViewerData>;
}

const PANE_KIND_LABELS: Record<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 The PANE_KIND_LABELS map is typed as Record<string, string>, so TypeScript considers every index access to always return string. At runtime, accessing a key that isn't in the map returns undefined, making the ?? fallback on line 100 necessary but invisible to the type checker. Narrowing the type to Partial<Record<string, string>> makes the index signature honest and lets TypeScript verify the nullish coalescing is needed.

Suggested change
const PANE_KIND_LABELS: Record<string, string> = {
const PANE_KIND_LABELS: Partial<Record<string, string>> = {
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts
Line: 26

Comment:
The `PANE_KIND_LABELS` map is typed as `Record<string, string>`, so TypeScript considers every index access to always return `string`. At runtime, accessing a key that isn't in the map returns `undefined`, making the `??` fallback on line 100 necessary but invisible to the type checker. Narrowing the type to `Partial<Record<string, string>>` makes the index signature honest and lets TypeScript verify the nullish coalescing is needed.

```suggestion
const PANE_KIND_LABELS: Partial<Record<string, string>> = {
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +132 to +136
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
}

function shortId(value: 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 When terminalId is a string whose only content is the "terminal" prefix itself (e.g. exactly "terminal" or "terminal-"), replace strips it to an empty string and candidate falls back to the original value. With candidate = "terminal-" (9 chars), slice(0, 8) returns "terminal", so the body becomes "Pane: Terminal terminal" — a doubled word. A guard for the empty-suffix case avoids this.

Suggested change
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
}
function shortId(value: string): string {
function shortId(value: string): string {
const withoutTerminalPrefix = value.replace(/^terminal[-_:]?/i, "");
const candidate = withoutTerminalPrefix || value;
// If stripping the prefix left nothing meaningful, keep the original.
if (!withoutTerminalPrefix) return value.length > 8 ? value.slice(0, 8) : value;
return candidate.length > 8 ? candidate.slice(0, 8) : candidate;
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts
Line: 132-136

Comment:
When `terminalId` is a string whose only content is the "terminal" prefix itself (e.g. exactly `"terminal"` or `"terminal-"`), `replace` strips it to an empty string and `candidate` falls back to the original value. With `candidate = "terminal-"` (9 chars), `slice(0, 8)` returns `"terminal"`, so the body becomes `"Pane: Terminal terminal"` — a doubled word. A guard for the empty-suffix case avoids this.

```suggestion
function shortId(value: string): string {
	const withoutTerminalPrefix = value.replace(/^terminal[-_:]?/i, "");
	const candidate = withoutTerminalPrefix || value;
	// If stripping the prefix left nothing meaningful, keep the original.
	if (!withoutTerminalPrefix) return value.length > 8 ? value.slice(0, 8) : value;
	return candidate.length > 8 ? candidate.slice(0, 8) : candidate;
}
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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
`@apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts`:
- Around line 36-37: Replace the use of the `in` operator for own-property
checking with an explicit hasOwnProperty call: instead of `if (agentId in
BUILTIN_AGENT_LABELS)`, use
`Object.prototype.hasOwnProperty.call(BUILTIN_AGENT_LABELS, agentId)` and then
return `BUILTIN_AGENT_LABELS[agentId as BuiltinAgentId]` as before; this change
should be applied where `agentId`, `BUILTIN_AGENT_LABELS`, and `BuiltinAgentId`
are referenced in notificationContent.ts to ensure only own properties are
matched.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1e20c775-3b42-466b-a078-44aae468c601

📥 Commits

Reviewing files that changed from the base of the PR and between 77dd3e7 and 0b5d832.

📒 Files selected for processing (4)
  • apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/V2NotificationController.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/lifecycleEvents.ts
  • apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts

Comment on lines +36 to +37
if (agentId in BUILTIN_AGENT_LABELS) {
return BUILTIN_AGENT_LABELS[agentId as BuiltinAgentId];
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify BUILTIN_AGENT_LABELS declaration and whether it uses a null-prototype map.
rg -n -C3 "BUILTIN_AGENT_LABELS"

# Verify AgentIdentity/agentId typing or validation constraints upstream.
rg -n -C3 "interface AgentIdentity|type AgentIdentity|agentId"

Repository: superset-sh/superset

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find cleanLabel function definition
rg -A 10 "function cleanLabel|const cleanLabel|export.*cleanLabel" apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts

# Show the full function context in notificationContent.ts
rg -B 5 -A 15 "function getAgentLabel" apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts

Repository: superset-sh/superset

Length of output: 973


Use Object.prototype.hasOwnProperty.call() for own-property checks.

On line 36, the in operator checks both own properties and inherited prototype keys. While the practical risk is mitigated by type constraints on agentId (BuiltinAgentId | "droid"), using Object.prototype.hasOwnProperty.call() is the correct approach for own-property checks and avoids relying on type safety for this operation.

Proposed fix
-	if (agentId in BUILTIN_AGENT_LABELS) {
+	if (Object.prototype.hasOwnProperty.call(BUILTIN_AGENT_LABELS, agentId)) {
 		return BUILTIN_AGENT_LABELS[agentId as BuiltinAgentId];
 	}
📝 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
if (agentId in BUILTIN_AGENT_LABELS) {
return BUILTIN_AGENT_LABELS[agentId as BuiltinAgentId];
if (Object.prototype.hasOwnProperty.call(BUILTIN_AGENT_LABELS, agentId)) {
return BUILTIN_AGENT_LABELS[agentId as BuiltinAgentId];
🤖 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
`@apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/lib/notificationContent.ts`
around lines 36 - 37, Replace the use of the `in` operator for own-property
checking with an explicit hasOwnProperty call: instead of `if (agentId in
BUILTIN_AGENT_LABELS)`, use
`Object.prototype.hasOwnProperty.call(BUILTIN_AGENT_LABELS, agentId)` and then
return `BUILTIN_AGENT_LABELS[agentId as BuiltinAgentId]` as before; this change
should be applied where `agentId`, `BUILTIN_AGENT_LABELS`, and `BuiltinAgentId`
are referenced in notificationContent.ts to ensure only own properties are
matched.

Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/V2NotificationController.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/V2NotificationController.tsx:126">
P2: Using a constant fallback label (`"Workspace"`) removes unique workspace identification for unnamed/unbranched workspaces, making notifications ambiguous.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic

group.push({
workspaceId: workspace.workspaceId,
workspaceName:
workspace.name.trim() || workspace.branch.trim() || "Workspace",
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: Using a constant fallback label ("Workspace") removes unique workspace identification for unnamed/unbranched workspaces, making notifications ambiguous.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/components/V2NotificationController/V2NotificationController.tsx, line 126:

<comment>Using a constant fallback label (`"Workspace"`) removes unique workspace identification for unnamed/unbranched workspaces, making notifications ambiguous.</comment>

<file context>
@@ -123,9 +123,7 @@ function groupWorkspacesByHostUrl({
-				workspace.name.trim() ||
-				workspace.branch.trim() ||
-				workspace.workspaceId,
+				workspace.name.trim() || workspace.branch.trim() || "Workspace",
 			paneLayout: paneLayoutsByWorkspaceId.get(workspace.workspaceId) ?? null,
 		});
</file context>
Suggested change
workspace.name.trim() || workspace.branch.trim() || "Workspace",
workspace.name.trim() || workspace.branch.trim() || workspace.workspaceId,

Tip: Review your code locally with the cubic CLI to iterate faster.

@Kitenite Kitenite merged commit 0bbe81e into main May 16, 2026
8 of 10 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch

Thank you for your contribution! 🎉

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