Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Added

- Added workspace-scoped default xcresult bundles for simulator, device, and macOS test tools so test artifacts are available in structured and text output even when callers do not pass `-resultBundlePath`.
- Added opt-in MCP server idle shutdown via `XCODEBUILDMCP_MCP_IDLE_TIMEOUT_MS`, allowing unused MCP server processes to gracefully exit after a configured idle period ([#394](https://github.com/getsentry/XcodeBuildMCP/issues/394)).

### Fixed
Expand Down
2 changes: 2 additions & 0 deletions src/mcp/tools/device/__tests__/test_device.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ describe('test_device plugin', () => {
'never',
'-derivedDataPath',
computeScopedDerivedDataPath('/path/to/project.xcodeproj'),
'-resultBundlePath',
expect.stringContaining('/result-bundles/test_device_'),
'test',
]);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ Compiler Errors (1):
example_projects/iOS_Calculator/CalculatorApp/CalculatorApp.swift:33:42

❌ Test failed. (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_device_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,5 @@ IntentionalFailureTests
example_projects/iOS_Calculator/CalculatorAppTests/CalculatorAppTests.swift:286

❌ <FAIL_COUNT> tests failed, <PASS_COUNT> passed, <SKIP_COUNT> skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_device_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log
3 changes: 2 additions & 1 deletion src/snapshot-tests/__fixtures__/cli/device/test--success.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ Discovered 1 test(s):
CalculatorAppTests/CalculatorAppTests/testAddition
Running tests (1 completed, 0 failures, 0 skipped)

✅ 1 test passed, 0 skipped (⏱️ <DURATION>)
✅ 1 test passed, 0 failed, 0 skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_device_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ Compiler Errors (1):
example_projects/macOS/MCPTest/MCPTestApp.swift:20:42

❌ Test failed. (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ Errors (1):
✗ The project named "MCPTest" does not contain a scheme named "NONEXISTENT". The "-list" option can be used to find the names of the schemes in the project.

❌ Test failed. (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ MCPTestTests
example_projects/macOS/MCPTestTests/MCPTestTests.swift:11

❌ <FAIL_COUNT> tests failed, <PASS_COUNT> passed, <SKIP_COUNT> skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log
3 changes: 2 additions & 1 deletion src/snapshot-tests/__fixtures__/cli/macos/test--success.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ Discovered 2 test(s):
Running tests (1 completed, 0 failures, 0 skipped)
Running tests (2 completed, 0 failures, 0 skipped)

✅ 2 tests passed, 0 skipped (⏱️ <DURATION>)
✅ 2 tests passed, 0 failed, 0 skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ IntentionalFailureTests
example_projects/iOS_Calculator/CalculatorAppTests/CalculatorAppTests.swift:286

❌ <FAIL_COUNT> tests failed, <PASS_COUNT> passed, <SKIP_COUNT> skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_sim_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_sim_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ Discovered 1 test(s):
CalculatorAppTests/CalculatorAppTests/testAddition
Running tests (1 completed, 0 failures, 0 skipped)

✅ 1 test passed, 0 skipped (⏱️ <DURATION>)
✅ 1 test passed, 0 failed, 0 skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_sim_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_sim_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
Running tests (0 completed, 0 failures, 0 skipped)
Running tests (1 completed, 0 failures, 0 skipped)

✅ 1 test passed, 0 skipped (⏱️ <DURATION>)
✅ 1 test passed, 0 failed, 0 skipped (⏱️ <DURATION>)
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/swift_package_test_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,17 @@
"summary": {
"status": "FAILED",
"durationMs": 1234,
"counts": {
"passed": 0,
"failed": 0,
"skipped": 0
},
"target": "device"
},
"artifacts": {
"deviceId": "<UUID>",
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log"
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log",
"xcresultPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_device_<TIMESTAMP>_pid<PID>.xcresult"
},
"tests": {
"selected": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
},
"artifacts": {
"deviceId": "<UUID>",
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log"
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log",
"xcresultPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_device_<TIMESTAMP>_pid<PID>.xcresult"
},
"tests": {
"discovered": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
},
"artifacts": {
"deviceId": "<UUID>",
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log"
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log",
"xcresultPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_device_<TIMESTAMP>_pid<PID>.xcresult"
},
"tests": {
"selected": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,16 @@
"summary": {
"status": "FAILED",
"durationMs": 1234,
"counts": {
"passed": 0,
"failed": 0,
"skipped": 0
},
"target": "macos"
},
"artifacts": {
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log"
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log",
"xcresultPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult"
},
"tests": {
"selected": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@
"summary": {
"status": "FAILED",
"durationMs": 1234,
"counts": {
"passed": 0,
"failed": 0,
"skipped": 0
},
"target": "macos"
},
"artifacts": {
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log"
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log",
"xcresultPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult"
},
"diagnostics": {
"warnings": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"target": "macos"
},
"artifacts": {
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log"
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log",
"xcresultPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult"
},
"tests": {
"discovered": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"target": "macos"
},
"artifacts": {
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log"
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log",
"xcresultPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult"
},
"tests": {
"selected": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"target": "simulator"
},
"artifacts": {
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_sim_<TIMESTAMP>_pid<PID>.log"
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_sim_<TIMESTAMP>_pid<PID>.log",
"xcresultPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_sim_<TIMESTAMP>_pid<PID>.xcresult"
},
"tests": {
"discovered": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"target": "simulator"
},
"artifacts": {
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_sim_<TIMESTAMP>_pid<PID>.log"
"buildLogPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_sim_<TIMESTAMP>_pid<PID>.log",
"xcresultPath": "<HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_sim_<TIMESTAMP>_pid<PID>.xcresult"
},
"tests": {
"selected": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ Errors (1):
<ROOT>/example_projects/iOS_Calculator/CalculatorApp/CalculatorApp.swift:33

❌ Test failed. (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_device_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ Test Failures (2):
<ROOT>/example_projects/iOS_Calculator/CalculatorAppTests/CalculatorAppTests.swift:286

❌ <FAIL_COUNT> tests failed, <PASS_COUNT> passed, <SKIP_COUNT> skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_device_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log
3 changes: 2 additions & 1 deletion src/snapshot-tests/__fixtures__/mcp/device/test--success.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
Discovered 1 test(s):
CalculatorAppTests/CalculatorAppTests/testAddition

✅ 1 test passed, 0 skipped (⏱️ <DURATION>)
✅ 1 test passed, 0 failed, 0 skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_device_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_device_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ Errors (1):
<ROOT>/example_projects/macOS/MCPTest/MCPTestApp.swift:20

❌ Test failed. (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ Errors (1):
✗ The project named "MCPTest" does not contain a scheme named "NONEXISTENT". The "-list" option can be used to find the names of the schemes in the project.

❌ Test failed. (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ Test Failures (2):
MCPTestTests.swift:11

❌ <FAIL_COUNT> tests failed, <PASS_COUNT> passed, <SKIP_COUNT> skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log
3 changes: 2 additions & 1 deletion src/snapshot-tests/__fixtures__/mcp/macos/test--success.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ Discovered 2 test(s):
MCPTestTests/MCPTestTests/appNameIsCorrect
MCPTestTests/MCPTestsXCTests/testAppNameIsCorrect

✅ 2 tests passed, 0 skipped (⏱️ <DURATION>)
✅ 2 tests passed, 0 failed, 0 skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_macos_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ Test Failures (3):
<ROOT>/example_projects/iOS_Calculator/CalculatorAppTests/CalculatorAppTests.swift:286

❌ <FAIL_COUNT> tests failed, <PASS_COUNT> passed, <SKIP_COUNT> skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_sim_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_sim_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
Discovered 1 test(s):
CalculatorAppTests/CalculatorAppTests/testAddition

✅ 1 test passed, 0 skipped (⏱️ <DURATION>)
✅ 1 test passed, 0 failed, 0 skipped (⏱️ <DURATION>)
├ Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/result-bundles/test_sim_<TIMESTAMP>_pid<PID>.xcresult
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/test_sim_<TIMESTAMP>_pid<PID>.log
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
Platform: Swift Package
Derived Data: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/DerivedData

✅ 1 test passed, 0 skipped (⏱️ <DURATION>)
✅ 1 test passed, 0 failed, 0 skipped (⏱️ <DURATION>)
└ Build Logs: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/XcodeBuildMCP-<HASH>/logs/swift_package_test_<TIMESTAMP>_pid<PID>.log
4 changes: 3 additions & 1 deletion src/snapshot-tests/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const UUID_REGEX = /[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-
const DURATION_REGEX = /\d+\.\d+s\b/g;
const PID_NUMBER_REGEX = /(pid:\s*)\d+/gi;
const PID_FILENAME_SUFFIX_REGEX = /_pid\d+(?:_[0-9a-f]{8})?\.log/g;
const XCRESULT_FILENAME_PID_SUFFIX_REGEX = /_pid\d+_[0-9a-f]{8}\.xcresult/g;
const HELPER_PID_FILENAME_SUFFIX_REGEX =
/_(?:helperpid\d+_ownerpid\d+|ownerpid\d+)_[0-9a-f]{8}\.log/g;
const PID_JSON_REGEX = /"pid"\s*:\s*\d+/g;
Expand Down Expand Up @@ -129,7 +130,7 @@ export function normalizeSnapshotOutput(text: string): string {
'<TMPDIR>',
);
normalized = normalized.replace(
/(<HOME>\/Library\/Developer\/XcodeBuildMCP\/workspaces\/[^/]+)-[0-9a-f]{12}(?=\/logs\/)/g,
/(<HOME>\/Library\/Developer\/XcodeBuildMCP\/workspaces\/[^/]+)-[0-9a-f]{12}(?=\/(?:logs|result-bundles)\/)/g,
'$1-<HASH>',
);
normalized = normalized.replace(
Expand Down Expand Up @@ -160,6 +161,7 @@ export function normalizeSnapshotOutput(text: string): string {
normalized = normalized.replace(PID_NUMBER_REGEX, '$1<PID>');
normalized = normalized.replace(HELPER_PID_FILENAME_SUFFIX_REGEX, '_pid<PID>.log');
normalized = normalized.replace(PID_FILENAME_SUFFIX_REGEX, '_pid<PID>.log');
normalized = normalized.replace(XCRESULT_FILENAME_PID_SUFFIX_REGEX, '_pid<PID>.xcresult');
normalized = normalized.replace(PID_JSON_REGEX, '"pid" : <PID>');
normalized = normalized.replace(PROCESS_ID_REGEX, 'Process ID: <PID>');
normalized = normalized.replace(PROCESS_INLINE_PID_REGEX, 'process <PID>');
Expand Down
1 change: 1 addition & 0 deletions src/utils/__tests__/log-paths.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('log paths', () => {
state: path.join(appDir, 'workspaces', 'workspace-a', 'state'),
locks: path.join(appDir, 'workspaces', 'workspace-a', 'locks'),
derivedData: path.join(appDir, 'workspaces', 'workspace-a', 'DerivedData'),
resultBundles: path.join(appDir, 'workspaces', 'workspace-a', 'result-bundles'),
logRetention: {
lockDir: path.join(appDir, 'workspaces', 'workspace-a', 'locks', 'log-retention.lock'),
markerPath: path.join(
Expand Down
2 changes: 1 addition & 1 deletion src/utils/__tests__/simulator-test-execution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ describe('createSimulatorTwoPhaseExecutionPlan', () => {
expect(plan.usesExactSelectors).toBe(true);
});

it('keeps resultBundlePath out of build-for-testing args and includes it for test-without-building', () => {
it('includes resultBundlePath only in the simulator test execution phase', () => {
const plan = createSimulatorTwoPhaseExecutionPlan({
extraArgs: ['-resultBundlePath', '/tmp/UserProvided.xcresult'],
});
Expand Down
13 changes: 13 additions & 0 deletions src/utils/__tests__/snapshot-normalize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ describe('normalizeSnapshotOutput tilde handling', () => {
);
});

it('normalizes workspace-scoped result bundle paths', () => {
const input =
'Result Bundle: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/Weather-abc123def456/result-bundles/test_macos_2026-05-07T09-58-46-123Z_pid1234_abcd1234.xcresult\n';

const result = normalizeSnapshotOutput(input);

expect(result).toContain(
'<HOME>/Library/Developer/XcodeBuildMCP/workspaces/Weather-<HASH>/result-bundles/test_macos_<TIMESTAMP>_pid<PID>.xcresult',
);
expect(result).not.toContain('Weather-abc123def456');
expect(result).not.toContain('abcd1234');
});

it('normalizes workspace-scoped XcodeBuildMCP DerivedData hashes', () => {
const input =
'Derived Data: <HOME>/Library/Developer/XcodeBuildMCP/workspaces/Weather-abc123def456/DerivedData/CalculatorApp-22d700c6d603\n';
Expand Down
Loading
Loading