Skip to content

Conversation

@cameroncooke
Copy link
Collaborator

@cameroncooke cameroncooke commented Aug 18, 2025

Summary

Implements intelligent Sentry error classification to reduce noise by distinguishing between MCP server bugs and user domain errors based on xcodebuild exit codes. This prevents user compilation errors from cluttering Sentry monitoring while preserving visibility into genuine server issues.

Background/Details

Root Cause Analysis

Previously, ALL xcodebuild failures were logged to Sentry as errors, creating significant noise. The challenge was differentiating between:

  • MCP Server Domain Errors: Bugs in our tool argument construction (should log to Sentry)
  • User Domain Errors: Compilation failures, missing files, invalid schemes (should not log to Sentry)
  • Environment Issues: Missing xcodebuild, permission errors (should not log to Sentry)

Empirical Research Approach

Rather than relying on heuristics, conducted comprehensive testing of xcodebuild exit codes:

  • Exit Code 64: Invalid command-line options (MCP fault)
  • Exit Code 65: Missing schemes (user fault)
  • Exit Code 66: File not found (user fault)
  • Exit Code 70: Destination issues (user fault)
  • Exit Code 1: General build failures (user fault)
  • Spawn Errors: ENOENT, EACCES, EPERM (environment issues)

Solution

Core Implementation

  • CommandResponse Interface: Added exitCode field to capture process exit codes
  • Command Executor: Enhanced to capture and return exit codes from child processes
  • Logger Enhancement: Added LogContext interface for selective Sentry capture control
  • Build Utils Classification: Exit code-based routing logic

Classification Logic

// Exit code 64 = MCP server error (invalid arguments we constructed)
const isMcpError = result.exitCode === 64;

log(
  isMcpError ? 'error' : 'warning',
  `${platformOptions.logPrefix} ${buildAction} failed: ${result.error}`,
  { sentry: isMcpError }  // Only log exit 64 to Sentry
);

Spawn Error Handling

// Environment issues (process couldn't start)
const isSpawnError = ['ENOENT', 'EACCES', 'EPERM'].includes(error.code);
log('error', errorMessage, { sentry: !isSpawnError });

Testing

Enhanced Mock Infrastructure

  • Mock Executor: Added exitCode and shouldThrow parameters for comprehensive testing
  • Complete Coverage: 11 new test cases covering all classification scenarios and edge cases

Manual Validation

Verified real-world behavior using Reloaderoo CLI testing tool:

  • Exit Code 64: Invalid flag --invalid-flag-that-does-not-exist → ERROR level + Sentry
  • Exit Code 66: Missing file /nonexistent/project.xcodeproj → WARNING level, no Sentry
  • Success Cases: Normal operations → INFO level only

Quality Assurance

  • 1057 tests pass (11 new tests added)
  • TypeScript compilation clean
  • ESLint validation clean
  • No regressions to existing functionality

Notes

  • Backward Compatible: No breaking changes to existing functionality
  • Empirical Foundation: Based on actual xcodebuild testing rather than assumptions
  • Focused Scope: Only applies to xcodebuild commands, other tools unaffected
  • Simple & Maintainable: Clean implementation without complex pattern matching

Deployment Considerations

This change will immediately reduce Sentry noise by filtering out user compilation errors while preserving visibility into genuine MCP server bugs. Monitor Sentry alert volume to confirm the improvement.

Summary by CodeRabbit

  • New Features
    • Command results now include an optional exit code for clearer outcomes.
    • Improved build-failure handling with distinct severity and smarter Sentry reporting.
  • Bug Fixes
    • Avoids sending Sentry reports for common environment/spawn errors, reducing noise.
    • More accurate classification of certain build errors with clearer messaging.
  • Documentation
    • Updated logging docs to cover optional context and Sentry capture behavior.
  • Tests
    • Added comprehensive tests covering diverse build outcomes, errors, and success paths.

Implements intelligent Sentry error classification to reduce noise by distinguishing between MCP server bugs and user domain errors based on xcodebuild exit codes.

## Changes Made

### Core Implementation
- **CommandResponse Interface**: Added `exitCode` field to capture process exit codes for error classification
- **Command Executor**: Enhanced to capture and return exit codes from child processes
- **Logger Enhancement**: Added `LogContext` interface to allow selective Sentry capture control
- **Build Utils Classification**: Implemented exit code-based Sentry routing logic

### Classification Logic
- **Exit Code 64**: Invalid command-line arguments (MCP server error) → Logs to Sentry as ERROR level
- **All Other Exit Codes**: User domain errors (missing files, compilation failures, etc.) → Logs as WARNING level, no Sentry
- **Spawn Errors**: Environment issues (ENOENT, EACCES, EPERM) → No Sentry logging

### Testing
- **Enhanced Mock Executor**: Added support for `exitCode` and `shouldThrow` parameters for comprehensive testing
- **Complete Test Coverage**: 11 new test cases covering all classification scenarios and edge cases
- **Manual Validation**: Verified real-world behavior using Reloaderoo CLI testing tool

## Benefits
- **Reduced Noise**: Eliminates user compilation errors from Sentry monitoring
- **Focused Alerts**: Only genuine MCP server bugs trigger Sentry notifications
- **Empirical Approach**: Based on actual xcodebuild exit code testing rather than heuristics
- **Backward Compatible**: No breaking changes to existing functionality

## Validation
- All 1057 existing tests pass
- TypeScript compilation clean
- ESLint validation clean
- Manual testing confirms correct classification behavior
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 18, 2025

Walkthrough

Adds exitCode propagation across command execution, updates mock executors to support exitCode and forced throws, refines executeXcodeBuildCommand logging to distinguish MCP vs other failures and spawn errors, introduces a log context with optional sentry control, and adds tests covering exit-code- and spawn-error–based behaviors.

Changes

Cohort / File(s) Summary of changes
Mock executors
src/test-utils/mock-executors.ts
Support shouldThrow to force rejection; add optional exitCode in results and per-command maps; propagate exitCode to mock process and returned results.
Command response API
src/utils/CommandExecutor.ts, src/utils/command.ts
Extend CommandResponse with optional exitCode; set exitCode on close for non-detached commands; no other behavior changes.
Build utils error handling
src/utils/build-utils.ts
On failure, detect MCP (exitCode 64) vs others to set severity and sentry flag; in catch, classify spawn errors (ENOENT/EACCES/EPERM) and gate sentry accordingly.
Logger API
src/utils/logger.ts
Add LogContext { sentry? }; log(level, message, context?) now gates Sentry capture via context.sentry or defaults to error-level capture.
Tests
src/utils/__tests__/build-utils.test.ts
New tests covering executeXcodeBuildCommand outcomes across specific exit codes, spawn errors, non-spawn errors, success, and undefined exitCode.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant BuildUtils as executeXcodeBuildCommand
  participant Exec as Command Executor
  participant Logger
  Caller->>BuildUtils: run xcodebuild
  BuildUtils->>Exec: execute(command)
  Exec-->>BuildUtils: { success, output, error, exitCode }
  alt success
    BuildUtils->>Logger: log("info", successMsg, {sentry:false})
  else failure with exitCode
    alt exitCode == 64 (MCP)
      BuildUtils->>Logger: log("error", mcpMsg, {sentry:true})
    else other exitCode
      BuildUtils->>Logger: log("warn", nonMcpMsg, {sentry:false})
    end
  else throw
    BuildUtils->>Logger: log("error", errMsg, {sentry: !isSpawnError})
  end
  BuildUtils-->>Caller: ToolResponse
Loading
sequenceDiagram
  participant Caller
  participant Logger
  participant Sentry
  Caller->>Logger: log(level, message, context?)
  Logger->>Logger: captureToSentry = SENTRY && (context.sentry ?? level=="error")
  alt captureToSentry
    Logger->>Sentry: capture(message)
  end
  Logger-->>Caller: done
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

A thump of paws, I trace the code,
Exit signs now mark the road.
MCP storms? I’ll raise the flare—
Spawn winds hush? I won’t declare.
With sentry flags and tidy logs,
I hop through tests like clever hogs.
Carrots compiled; success unclogs! 🥕🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/improve_sentry_logging

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@claude
Copy link
Contributor

claude bot commented Aug 18, 2025

Claude finished @cameroncooke's task —— View job


Code Review: Sentry Logging Enhancement

Review Tasks

  • Read repository guidelines (CLAUDE.md)
  • Analyze core interface changes (CommandResponse, LogContext)
  • Review command executor enhancements
  • Examine build-utils classification logic
  • Evaluate logger modifications
  • Review test coverage and quality
  • Assess architecture and design decisions
  • Check for potential bugs or edge cases
  • Evaluate performance implications
  • Provide comprehensive feedback

Overall Assessment: ✅ Excellent Implementation

This is a well-architected solution that addresses a real operational problem with intelligent error classification. The implementation demonstrates strong engineering practices and thorough testing.

🎯 Strengths

1. Empirical Approach

  • Smart Research: Instead of relying on heuristics, you conducted actual testing to determine exit codes
  • Evidence-Based: Exit code 64 classification based on real xcodebuild behavior
  • Clear Documentation: Each exit code's meaning is documented with context

2. Clean Architecture

  • Non-Breaking Changes: All modifications are backward compatible
  • Focused Interfaces: LogContext and exitCode additions are minimal and purposeful
  • Separation of Concerns: Classification logic isolated to build-utils, logger handles context

3. Robust Testing

  • Comprehensive Coverage: 11 new tests covering all classification scenarios
  • Edge Cases: Tests include undefined exit codes, spawn errors, and success cases
  • Follows DI Pattern: Proper use of createMockExecutor with dependency injection

4. Operational Impact

  • Reduces Noise: Filters user compilation errors from server monitoring
  • Maintains Visibility: Preserves genuine MCP server bug tracking
  • Immediate Benefit: Will improve Sentry signal-to-noise ratio

📋 Detailed Code Review

CommandResponse Interface (src/utils/CommandExecutor.ts:22)

exitCode?: number;

Good: Optional field maintains backward compatibility
Appropriate Type: number | undefined matches process.exitCode behavior

Logger Enhancement (src/utils/logger.ts:42-45)

export interface LogContext {
  sentry?: boolean;
}

Clean API: Simple boolean flag for Sentry control
Good Defaults: Uses existing error level behavior when context not provided

Exit Code Classification (src/utils/build-utils.ts:250)

const isMcpError = result.exitCode === 64;
log(
  isMcpError ? 'error' : 'warning',
  `${platformOptions.logPrefix} ${buildAction} failed: ${result.error}`,
  { sentry: isMcpError }
);

Precise Logic: Only exit code 64 triggers Sentry (empirically determined)
Appropriate Levels: ERROR for MCP issues, WARNING for user issues
Context Control: Explicit Sentry context overrides default behavior

Spawn Error Handling (src/utils/build-utils.ts:347-354)

const isSpawnError = 
  error instanceof Error &&
  'code' in error &&
  ['ENOENT', 'EACCES', 'EPERM'].includes((error as NodeJS.ErrnoException).code ?? '');

log('error', `Error during ${platformOptions.logPrefix} ${buildAction}: ${errorMessage}`, {
  sentry: !isSpawnError,
});

Environment Classification: Correctly identifies environment issues
Type Safety: Proper type guards and null coalescing
Appropriate Codes: ENOENT, EACCES, EPERM are correct spawn failure codes

Command Executor Enhancement (src/utils/command.ts:129)

exitCode: code ?? undefined,

Proper Handling: Captures actual exit codes from child processes
Null Safety: Uses nullish coalescing for undefined codes

🔍 Minor Observations

1. Test Coverage Gap (Very Minor)

The tests validate logging behavior indirectly. Consider adding a test that explicitly verifies Sentry context:

// Future enhancement - verify Sentry context is passed correctly
it('should verify Sentry context for exit code 64', () => {
  // Mock the logger to capture context
  // Verify { sentry: true } is passed for exit code 64
});

2. Documentation Opportunity

Consider adding a comment explaining the exit code 64 classification:

// Exit code 64 indicates invalid command-line arguments (MCP server fault)
// All other exit codes represent user domain errors (compilation, missing files, etc.)
const isMcpError = result.exitCode === 64;

3. Future Enhancement

You might consider making exit codes configurable via environment variable:

const MCP_ERROR_EXIT_CODES = process.env.XCODEBUILDMCP_MCP_ERROR_CODES?.split(',').map(Number) ?? [64];

🚀 Performance & Security

Performance: ✅ Excellent

  • Zero Performance Impact: Classification logic is O(1)
  • No Additional Network Calls: Sentry behavior unchanged, just context control
  • Minimal Memory: New fields are optional and lightweight

Security: ✅ Appropriate

  • No New Attack Vectors: Changes are purely internal classification
  • Error Information: No sensitive data exposed in new logging paths
  • Context Control: Sentry context properly scoped

🧪 Test Quality Assessment

Test Architecture: ✅ Follows Best Practices

  • Dependency Injection: Proper use of createMockExecutor
  • No Vitest Mocking: Adheres to project's DI testing philosophy
  • Comprehensive Scenarios: All exit codes and error types covered

Test Coverage: ✅ Thorough

 Exit code 64 (MCP error)
 Exit codes 65, 66, 70, 1 (user errors)  
 Spawn errors (ENOENT, EACCES, EPERM)
 Success cases
 Undefined exit codes
 Non-spawn exceptions

📦 Integration Considerations

Backward Compatibility: ✅ Perfect

  • All changes are additive
  • Existing tool behavior unchanged
  • Optional fields with sensible defaults

Rollout Safety: ✅ Low Risk

  • Changes are internal to logging system
  • No external API changes
  • Easy to monitor effectiveness via Sentry volume

🎯 Recommendation: APPROVE

This is an exemplary implementation that:

  • Solves a Real Problem: Reduces operational noise effectively
  • Uses Sound Engineering: Empirical research, clean architecture, comprehensive testing
  • Follows Project Standards: Adheres to DI patterns, TypeScript conventions, focused facades
  • Minimizes Risk: Non-breaking, well-tested, easy to monitor

The code quality is high, the approach is intelligent, and the implementation is robust. This change will provide immediate operational benefits while maintaining system reliability.


🔧 Final Notes

Deployment Monitoring: After deployment, monitor Sentry alert volume to confirm the noise reduction is working as expected.

Future Iteration: Consider collecting metrics on exit code frequency to further refine the classification if needed.

Great work on this improvement! 🎉

@cameroncooke
Copy link
Collaborator Author

cursor review

Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no bugs!


Copy link
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: 0

🧹 Nitpick comments (10)
src/utils/CommandExecutor.ts (1)

22-23: Document the semantics of exitCode for clarity.

Great addition. Consider a short JSDoc to make it explicit that this is only populated for non-detached executions and may be absent if the process exited via signal.

   process: ChildProcess;
-  exitCode?: number;
+  /**
+   * POSIX exit code for the finished process (0 indicates success).
+   * Present for non-detached executions; undefined if unavailable (e.g., process exited via signal).
+   */
+  exitCode?: number;
 }
src/utils/command.ts (1)

122-131: Optional: also capture termination signal for richer diagnostics.

If useful, extend CommandResponse to include a signal?: NodeJS.Signals captured from the close handler’s second parameter. This helps distinguish non-zero exit vs signal termination.

Example change here:

- childProcess.on('close', (code) => {
+ childProcess.on('close', (code, signal) => {
    const success = code === 0;
    const response: CommandResponse = {
      success,
      output: stdout,
      error: success ? undefined : stderr,
      process: childProcess,
      exitCode: code ?? undefined,
+     // signal,
    };
    resolve(response);
  });

And add signal?: NodeJS.Signals; to the CommandResponse interface (in src/utils/CommandExecutor.ts).

src/utils/logger.ts (1)

140-156: Send Sentry severity to reflect log level (improves triage in Sentry).

Currently captureMessage is called without a severity, which defaults to "info" in Sentry. Forwarding a mapped severity aligned with your logger levels makes Sentry issues easier to prioritize.

Apply this diff within the selected range:

-  if (captureToSentry) {
-    withSentry((s) => s.captureMessage(logMessage));
-  }
+  if (captureToSentry) {
+    withSentry((s) => s.captureMessage(logMessage, mapToSentrySeverity(level)));
+  }

Add the following helper (outside the selected range) and a type-only import to avoid runtime loading:

// At top of file (type-only, no runtime import)
import type { SeverityLevel } from '@sentry/node';

// Below helpers
function mapToSentrySeverity(level: string): SeverityLevel {
  const l = level.toLowerCase();
  switch (l) {
    case 'emergency':
    case 'alert':
    case 'critical':
      return 'fatal';
    case 'error':
      return 'error';
    case 'warning':
      return 'warning';
    case 'notice':
      return 'log';
    case 'info':
      return 'info';
    case 'debug':
    default:
      return 'debug';
  }
}

Note: import type is erased at compile time and won’t load native modules at import.

src/utils/build-utils.ts (2)

250-257: Good classification; include exit code in the log line for faster diagnosis.

The MCP vs user error split is clear. Adding the exit code to the log message will speed up triage and correlate with tests and manual CLI checks.

-      log(
-        isMcpError ? 'error' : 'warning',
-        `${platformOptions.logPrefix} ${buildAction} failed: ${result.error}`,
-        { sentry: isMcpError },
-      );
+      log(
+        isMcpError ? 'error' : 'warning',
+        `${platformOptions.logPrefix} ${buildAction} failed${
+          result.exitCode !== undefined ? ` (exitCode: ${result.exitCode})` : ''
+        }: ${result.error}`,
+        { sentry: isMcpError },
+      );

347-355: Spawn error gating looks right; consider extending the set if needed.

Treating ENOENT/EACCES/EPERM as environment issues is sensible. If you see more spawn-related noise, consider extending to include e.g., E2BIG or ENOTDIR, but only as data justifies.

src/utils/__tests__/build-utils.test.ts (1)

1-264: Solid coverage of exit-code and spawn-error classification paths.

The tests validate the main scenarios and keep assertions focused on user-visible output. Nice balance. If you adopt the “include exit code in log message” tweak, consider adding one assertion that the exit code appears in the error summary.

src/test-utils/mock-executors.ts (4)

34-36: Type shouldThrow as NodeJS.ErrnoException to carry spawn error metadata

Classifying spawn errors typically relies on error.code (e.g., ENOENT, EACCES). Typing shouldThrow as NodeJS.ErrnoException preserves these fields without casting at call sites.

Apply this diff:

-        shouldThrow?: Error;
+        shouldThrow?: NodeJS.ErrnoException;

117-118: Consider adding shouldThrow per-command for parity and richer scenarios

Adding shouldThrow to per-command mocks makes it easy to simulate spawn errors for specific commands (e.g., ENOENT for a missing tool) without switching helper utilities.

Type update:

   commandMap: Record<
     string,
     {
       success?: boolean;
       output?: string;
       error?: string;
       process?: unknown;
       exitCode?: number;
+      shouldThrow?: NodeJS.ErrnoException;
     }
   >,

And short-circuit after lookup:

   const result = commandMap[matchedKey];
 
+  if (result.shouldThrow) {
+    throw result.shouldThrow;
+  }

146-158: Mirror success-from-exitCode defaulting here as well

Same potential contradiction exists in the multi-command executor. Aligning success with exitCode when success is omitted avoids accidental success: true with non-zero exitCode.

Apply this diff:

     return {
-      success: result.success ?? true, // Success by default (as discussed)
+      success:
+        result.success ??
+        (result.exitCode === undefined ? true : result.exitCode === 0),
       output: result.output ?? '',
       error: result.error,
       process: (result.process ?? mockProcess) as ChildProcess,
       exitCode: result.exitCode ?? (result.success === false ? 1 : 0),
     };

62-74: No inconsistent mocks found
Our repository-wide search for createMockExecutor({ … exitCode: … }) and createCommandMatchingMockExecutor({ … exitCode: … }) returned no occurrences. There are currently no mocks that set an explicit non-zero exitCode without also specifying success, so no existing tests will start reporting contradictory states.

You can still apply this optional refactor to derive success from exitCode when provided to prevent future inconsistencies:

--- a/src/test-utils/mock-executors.ts
+++ b/src/test-utils/mock-executors.ts
@@ -62,7 +62,11 @@ export function createMockExecutor(result: Partial<ExecutorResult>) {
   return async () => ({
-    success: result.success ?? true,
+    success:
+      result.success ??
+      (result.exitCode === undefined ? true : result.exitCode === 0),
     output: result.output ?? '',
     error: result.error,
     process: (result.process ?? mockProcess) as ChildProcess,
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 163fc26 and ae5038f.

📒 Files selected for processing (6)
  • src/test-utils/mock-executors.ts (7 hunks)
  • src/utils/CommandExecutor.ts (1 hunks)
  • src/utils/__tests__/build-utils.test.ts (1 hunks)
  • src/utils/build-utils.ts (2 hunks)
  • src/utils/command.ts (1 hunks)
  • src/utils/logger.ts (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/utils/logger.ts (1)
src/utils/logging/index.ts (1)
  • log (5-5)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Cursor Bugbot
  • GitHub Check: claude-review
🔇 Additional comments (3)
src/utils/command.ts (1)

122-131: LGTM: Exit code propagation is correctly captured on 'close'.

Using the 'close' event ensures stdio is fully drained, and exitCode is accurately surfaced. The nullish coalescing keeps the type aligned with number | undefined. All good.

src/utils/logger.ts (1)

40-46: LGTM: Context-based Sentry gating is clean and backward compatible.

The LogContext shape is minimal and effective; optional usage avoids breaking existing call sites.

src/test-utils/mock-executors.ts (1)

47-53: Early-throw path is correct and preserves real-world spawn behavior

Good precedence: shouldThrow short-circuits normal result shaping, mirroring actual spawn failures. This keeps tests faithful to runtime behavior.

@cameroncooke cameroncooke merged commit 225341f into main Aug 18, 2025
9 checks passed
@cameroncooke cameroncooke deleted the feat/improve_sentry_logging branch August 18, 2025 21:20
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