Skip to content

Cursor live hook: honor active profile's default_visibility - #580

Merged
realtonyyoung merged 2 commits into
mainfrom
tonyyoung/ai-783-cursor-default-visibility
Aug 18, 2026
Merged

realtonyyoung merged 2 commits into
mainfrom
tonyyoung/ai-783-cursor-default-visibility

Conversation

@realtonyyoung

@realtonyyoung realtonyyoung commented Aug 18, 2026 •

Copy link
Copy Markdown
Collaborator

What

The live Cursor sessionStart hook dispatcher (CursorHookCommand.HandleCore) never stamped the active profile's default_visibility onto the payload before POSTing to /hooks/session-start/cursor, unlike the Codex hook. As a result, a user with default_visibility: private still had their live Cursor sessions land org-visible in org repos, because the server treats a null default_visibility as the org-visibility fallback.

Change

  • Stamp default_visibility from AppConfig.GetActiveProfileAsync in the sessionStart && !isSubagentChild branch, before the git-enrichment round-trip (so it survives re-serialization), budget-bounded and fail-open (the hook must never block the agent loop). Mirrors CodexHookCommand.
  • Adds CursorSessionStartVisibilityTests (Linux-gated integration, mirroring CodexSessionStartVisibilityTests): a private and a public profile default each round-trip verbatim onto the POST body, with workspace_roots set so the enrichment reparse actually runs.

Notes

  • The historical import path (ImportCommand) already stamps default_visibility; this is a disjoint code path and is unchanged.
  • Requires the companion kcap-server change (adds default_visibility to the Cursor session-start hook model and packs it into the capacitor block) to take effect; the extra payload field is harmlessly ignored by an old server.

Closes #579
Linear: AI-783

The live Cursor sessionStart dispatcher never stamped the active profile's
default_visibility onto the payload (unlike the Codex hook), so a private-default
user's Cursor sessions in org repos silently went org-visible (the server treats a
null default_visibility as the org-visibility fallback).

Stamp it in the sessionStart branch before the git-enrichment round-trip,
budget-bounded and fail-open. Adds Linux-gated integration coverage mirroring
CodexSessionStartVisibilityTests. Requires the companion kcap-server change to read
the field into the capacitor block.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Aug 18, 2026

Copy link
Copy Markdown

AI-783

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Honor active profile visibility in live Cursor sessions

🐞 Bug fix 🧪 Tests 🕐 10-20 Minutes

Grey Divider

AI Description

• Honor active-profile visibility for live top-level Cursor session-start payloads.
• Preserve visibility through repository enrichment without blocking Cursor’s agent loop.
• Add integration coverage for private and public profile defaults.
Diagram

graph TD
  A["Cursor event"] --> B{"Top-level start?"} -->|Yes| C["Active profile"] --> D["Stamp visibility"] --> E["Git enrichment"] --> F["Hook API"]
  B -->|No| G["Child handling"]
Loading
High-Level Assessment

The localized client-side injection is appropriate because the active profile configuration is available in the CLI and the approach matches the established Codex hook behavior. Stamping before enrichment prevents field loss during reserialization, while budget checks and fail-open error handling preserve hook responsiveness. Server-side inference was considered but cannot reliably recover the user’s local active-profile setting.

Files changed (2) +112 / -0

Bug fix (1) +13 / -0
CursorHookCommand.csStamp profile visibility on live Cursor session starts +13/-0

Stamp profile visibility on live Cursor session starts

• Loads the active profile for top-level sessionStart events and adds its default visibility before repository enrichment reserializes the payload. The lookup respects the dispatcher budget and fails open so configuration errors cannot block the agent loop.

src/Capacitor.Cli/Commands/Harness/CursorHookCommand.cs

Tests (1) +99 / -0
CursorSessionStartVisibilityTests.csVerify Cursor visibility survives enrichment and delivery +99/-0

Verify Cursor visibility survives enrichment and delivery

• Adds WireMock-backed integration tests confirming private and public profile defaults reach the Cursor session-start endpoint verbatim. Real workspace roots force the repository-enrichment reparse, while configuration state is isolated and restored.

test/Capacitor.Cli.Tests.Integration/CursorSessionStartVisibilityTests.cs

@qodo-code-review

qodo-code-review Bot commented Aug 18, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

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

Grey Divider


Action required

1. Test comments repeat implementation ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The class summary reproduces the ticket narrative, expected behavior, and test setup across eight
lines, while another four-line comment narrates routine fixture mechanics. These comments are
substantially more verbose than needed to explain the non-obvious reserialization constraint.
Code

test/Capacitor.Cli.Tests.Integration/CursorSessionStartVisibilityTests.cs[R12-15]

+/// #579 — a live Cursor <c>sessionStart</c> hook must stamp the active profile's
+/// <c>default_visibility</c> onto the payload, the same way the Codex hook does. Without it,
+/// Cursor sessions in org repos silently default to org-visible (the server treats a null
+/// <c>default_visibility</c> as the org-visibility fallback), ignoring a private-default
Evidence
Rule 11 requires short comments focused on non-obvious rationale. The cited summary extensively
restates the visibility bug and test behavior, and the later setup comment narrates implementation
details rather than presenting only the essential reserialization reason.

CLAUDE.md: Comments must be concise and focus on non-obvious 'why' rather than restating code
test/Capacitor.Cli.Tests.Integration/CursorSessionStartVisibilityTests.cs[11-18]
test/Capacitor.Cli.Tests.Integration/CursorSessionStartVisibilityTests.cs[59-62]

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

## Issue description
The new test comments are verbose and restate behavior already expressed by the class, test names, and setup code.

## Issue Context
Retain only a concise explanation that `workspace_roots` forces the enrichment reserialization path; remove ticket history and routine setup narration.

## Fix Focus Areas
- test/Capacitor.Cli.Tests.Integration/CursorSessionStartVisibilityTests.cs[11-18]
- test/Capacitor.Cli.Tests.Integration/CursorSessionStartVisibilityTests.cs[59-62]

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


2. CursorHookCommand embeds vendor logic ✗ Dismissed 📘 Rule violation ⚙ Maintainability
Description
The new profile lookup and Cursor payload mutation are implemented directly in Commands/Harness
rather than under Harness/Cursor. This expands vendor-specific behavior outside the required
vendor directory instead of keeping the command layer as a registration or dispatch site.
Code

src/Capacitor.Cli/Commands/Harness/CursorHookCommand.cs[R351-353]

+                    if (!BudgetExpired()
+                     && (await AppConfig.GetActiveProfileAsync(ct))?.DefaultVisibility is { } defaultVisibility)
+                        node["default_visibility"] = defaultVisibility;
Evidence
Compliance rule 1 requires vendor-specific implementations to reside under Harness/<Vendor>. The
cited addition performs Cursor-specific profile resolution and payload mutation in
src/Capacitor.Cli/Commands/Harness/CursorHookCommand.cs, outside Harness/Cursor.

CLAUDE.md: Harness vendor code must live only under Harness/<Vendor>/ and shared code must remain outside Harness
src/Capacitor.Cli/Commands/Harness/CursorHookCommand.cs[345-356]

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

## Issue description
The active-profile visibility implementation was added outside the required `Harness/Cursor` vendor directory.

## Issue Context
Keep the command entry point limited to registration or dispatch and place Cursor-specific payload behavior in the existing Cursor vendor subtree. Update namespaces and references if files are moved.

## Fix Focus Areas
- src/Capacitor.Cli/Commands/Harness/CursorHookCommand.cs[345-356]
- src/Capacitor.Cli/Harness/Cursor[1-1]

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


3. Cursor test lacks mirrored folder ✗ Dismissed 📘 Rule violation ⚙ Maintainability
Description
The new Cursor-specific integration test is placed at the test-project root rather than in a
mirrored Harness/Cursor subtree. This breaks both vendor isolation and the required
production-to-test directory mirroring.
Code

test/Capacitor.Cli.Tests.Integration/CursorSessionStartVisibilityTests.cs[20]

+public class CursorSessionStartVisibilityTests : IDisposable {
Evidence
The class directly tests CursorHookCommand, but its file is at the test-project root. Rules 1 and
3 require vendor code under Harness/Cursor and test layouts that mirror the production vendor
structure.

CLAUDE.md: Harness vendor code must live only under Harness/<Vendor>/ and shared code must remain outside Harness
CLAUDE.md: Test projects must mirror production projects and share code only through Capacitor.Tests.Helpers (no cross-test-project references, no InternalsVisibleTo)
test/Capacitor.Cli.Tests.Integration/CursorSessionStartVisibilityTests.cs[1-20]

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

## Issue description
The Cursor-specific test was added at the integration project root instead of the vendor-specific mirrored directory.

## Issue Context
Move the test under `Harness/Cursor` and update its namespace to match the new directory structure.

## Fix Focus Areas
- test/Capacitor.Cli.Tests.Integration/CursorSessionStartVisibilityTests.cs[1-99]

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


Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/Capacitor.Cli/Commands/Harness/CursorHookCommand.cs
Comment thread test/Capacitor.Cli.Tests.Integration/CursorSessionStartVisibilityTests.cs Outdated
Address Qodo review: keep only the non-obvious why (workspace_roots forces the
enrichment reserialization the stamp must survive); drop the ticket narrative and
routine fixture narration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@realtonyyoung
realtonyyoung merged commit cab354a into main Aug 18, 2026
10 of 11 checks passed
@realtonyyoung
realtonyyoung deleted the tonyyoung/ai-783-cursor-default-visibility branch August 18, 2026 12:51
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.

Cursor live hook: honor active profile's default_visibility

1 participant