Skip to content

feat(responses): Add next-step runtime responses#420

Merged
cameroncooke merged 24 commits into
mainfrom
structured_next_steps
May 17, 2026
Merged

feat(responses): Add next-step runtime responses#420
cameroncooke merged 24 commits into
mainfrom
structured_next_steps

Conversation

@cameroncooke
Copy link
Copy Markdown
Collaborator

Add next-step instructions to CLI and MCP runtime responses across structured JSON and text output modes.

The motivation is to make runtime responses more useful for both people and agents without baking transport-specific verbosity policy into the runtime. Runtime now decides whether a response is minimal or normal, while CLI can expose that as an override: CLI defaults to normal, MCP defaults to minimal, and CLI callers can request the MCP-style minimal output when using the CLI from AI agents to save tokens.

This also refactors snapshot fixtures so coverage is explicit across the four supported output surfaces: MCP JSON, MCP text, CLI JSON, and CLI text. That makes future response contract changes easier to review because fixture expectations are grouped by runtime and output mode instead of being inferred from older shared fixture paths.

Reviewers should pay close attention to the structured-output envelope and schema version changes. The intent is to add/compact data inside the structured payload while preserving the standard envelope fields.

cameroncooke and others added 3 commits May 16, 2026 09:24
Add next-step instructions to runtime responses while keeping the structured
output envelope intact. The runtime now decides between minimal and normal
response detail without directly owning CLI verbosity policy.

Expose CLI control so regular CLI output can default to normal detail while
agent-oriented CLI usage can request minimal output matching MCP.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Restructure snapshot fixtures so CLI and MCP each have text and JSON coverage.
Add parity tests for both JSON fixture sets and update harness parsing to keep
runtime/output expectations explicit.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Record the runtime response and snapshot coverage changes in the unreleased
changelog.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 16, 2026

Open in StackBlitz

npm i https://pkg.pr.new/xcodebuildmcp@420

commit: 48c9078

@cameroncooke cameroncooke marked this pull request as ready for review May 16, 2026 08:27
Comment thread src/rendering/render.ts
Comment thread manifests/tools/boot_sim.yaml
Use the runtime option as the default text output style only when callers do
not pass an explicit output style. This keeps MCP resource rendering minimal
while still allowing CLI callers to opt into minimal output.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Copy link
Copy Markdown
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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Global test filter silently skips device snapshot tests
    • Split the command into two separate vitest runs: one for device.snapshot.test.ts without filter to run all tests, and another for parity files with the filter to run only device workflow tests.

Create PR

Or push these changes by commenting:

@cursor push 51cb64f1df
Preview (51cb64f1df)
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -47,7 +47,7 @@
     "test:schema-fixtures": "vitest run --config vitest.snapshot.config.ts src/snapshot-tests/__tests__/json-fixture-schema.test.ts",
     "test:snapshot": "npm run build && node build/cli.js daemon stop 2>/dev/null; vitest run --config vitest.snapshot.config.ts",
     "test:snapshots": "npm run test:snapshot",
-    "test:snapshot:device": "npm run build && node build/cli.js daemon stop 2>/dev/null; vitest run --config vitest.snapshot.config.ts src/snapshot-tests/__tests__/device.snapshot.test.ts src/snapshot-tests/__tests__/cli-json-fixture-parity.snapshot.test.ts src/snapshot-tests/__tests__/mcp-json-fixture-parity.snapshot.test.ts -t 'device workflow'",
+    "test:snapshot:device": "npm run build && node build/cli.js daemon stop 2>/dev/null; vitest run --config vitest.snapshot.config.ts src/snapshot-tests/__tests__/device.snapshot.test.ts && vitest run --config vitest.snapshot.config.ts src/snapshot-tests/__tests__/cli-json-fixture-parity.snapshot.test.ts src/snapshot-tests/__tests__/mcp-json-fixture-parity.snapshot.test.ts -t 'device workflow'",
     "test:snapshot:update": "npm run build && node build/cli.js daemon stop 2>/dev/null; UPDATE_SNAPSHOTS=1 vitest run --config vitest.snapshot.config.ts",
     "test:snapshots:update": "npm run test:snapshot:update",
     "test:smoke": "npm run build && vitest run --config vitest.smoke.config.ts",

You can send follow-ups to the cloud agent here.

Comment thread package.json Outdated
Run the device snapshot file separately from the JSON parity files so the
package script does not rely on a global Vitest name filter for every file.
Keep the device workflow filter scoped to the parity files where it selects
only the device suites.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Comment thread src/snapshot-tests/__fixtures__/cli/text/device/list--success.txt Outdated
Comment thread src/snapshot-tests/__tests__/session-management.snapshot.test.ts
Comment thread manifests/tools/xcode_ide_call_tool.yaml
Comment thread src/mcp/tools/project-discovery/show_build_settings.ts
Comment thread src/mcp/tools/debugging/debug_detach.ts
Comment thread src/snapshot-tests/json-normalize.ts Outdated
Comment thread src/utils/file-path-render-style.ts Outdated
Comment thread src/core/__tests__/structured-output-schema.test.ts
Comment thread src/utils/responses/next-steps-renderer.ts Outdated
cameroncooke and others added 4 commits May 16, 2026 14:41
Respect configured file path rendering before applying runtime verbosity defaults.
Append next steps to an existing text content item even when a later non-text
item is present, so mixed-content responses do not silently drop guidance.

Co-Authored-By: OpenAI Codex <codex@openai.com>
Return the current xcode bridge call-result schema version from daemon routed
invocations and update the JSON fixtures that exercise that contract.

Co-Authored-By: OpenAI Codex <codex@openai.com>
Cover additional CLI and MCP snapshot surfaces by normalizing volatile process,
device, Xcode, cache, and user values. Add the missing MCP text fixture for
session profile persistence so the runtime mode matrix stays complete.

Co-Authored-By: OpenAI Codex <codex@openai.com>
Reuse the filtered failed test case list instead of repeating the same predicate
for both detection and filtering.

Co-Authored-By: OpenAI Codex <codex@openai.com>
@cameroncooke
Copy link
Copy Markdown
Collaborator Author

Validated the Cursor Bugbot autofix note for the device snapshot test filter. This was already fixed in 34fd3c7 by splitting test:snapshot:device into separate vitest invocations so the -t device workflow filter only applies to parity tests.

Comment thread src/snapshot-tests/suites/debugging-suite.ts
Comment thread src/mcp/tools/simulator-management/set_sim_location.ts
Comment thread src/utils/structured-output-envelope.ts Outdated
Comment thread src/mcp/tools/xcode-ide/shared.ts Outdated
Comment thread src/utils/typed-tool-factory.ts Outdated
Require Xcode IDE bridge helpers to receive an explicit schema version and pass version 2 from status, sync, and disconnect callers.
Comment thread manifests/tools/swift_package_run.yaml
Comment thread src/snapshot-tests/__fixtures__/mcp/json/macos/stop--error-no-app.json Outdated
Add the missing swift_package_run manifest next-step template so daemon-routed CLI invocations can render the stop instruction from handler-provided nextStepParams.

Normalize PID string values in snapshot output so text and JSON fixtures use the same <PID> sentinel as numeric processId fields.
Comment thread src/snapshot-tests/__fixtures__/cli/json/ui-automation/snapshot-ui--success.json Outdated
Comment thread src/snapshot-tests/__fixtures__/mcp/json/swift-package/run--success.json Outdated
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

stopAllRunningSwiftPackageProcesses parses normalized fixture text for real process IDs, always getting 99999 (src/snapshot-tests/suites/swift-package-suite.ts:17)

JSON.parse(text) on line 22 operates on formatStructuredEnvelopeFixture output, which replaces every processId with 99999 (see json-normalize.ts line 53). The loop will always try to stop PID 99999, fail silently (no such process), then loop forever since activeProcesses still holds the real PIDs. Use structuredEnvelope.data.processes instead — it carries the unnormalized envelope.

Verification

Traced full call chain: createMcpJsonSnapshotHarness (json-harness.ts) wraps createMcpSnapshotHarness and returns text: formatStructuredEnvelopeFixture(envelope). formatStructuredEnvelopeFixture calls normalizeStructuredEnvelope → normalizeValue → normalizeNumber, which maps any key named processId to the literal number 99999 (json-normalize.ts lines 53-55). The structuredEnvelope field in the same return value is the original unmodified envelope. swift_package_stop (swift_package_stop.ts lines 101-104) does a processManager.getProcess(params.pid) lookup — pid 99999 is never found, returns didError: true without throwing. Because the caller discards isError from the stop invocation, the while-true loop spins indefinitely until the test framework hits its timeout.

Identified by Warden find-bugs

cameroncooke and others added 3 commits May 17, 2026 04:48
Normalize MAC_OS_X SDK build setting values, handle y-before-x UI frame objects, and keep Swift package run JSON fixtures aligned with next-step output.
Keep fixture-specific Warden coverage focused on snapshot and structured
output contracts, but stop general test-boundary and PII checks from
reviewing generated snapshot fixture artifacts one file at a time.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Avoid running Warden over generated snapshot fixture artifacts one file at a
time. Snapshot and schema tests validate generated fixture output; Warden now
reviews the fixture contracts, normalizers, and schema tests that control the
fixture contract.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Comment thread src/mcp/tools/simulator/record_sim_video.ts
Normalize volatile SDK_DIR build-setting keys in structured and text snapshot
fixtures, and include video-recording captures in the v2 capture-result schema.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Comment thread src/snapshot-tests/normalize.ts Outdated
Comment thread src/snapshot-tests/json-normalize.ts Outdated
cameroncooke and others added 2 commits May 17, 2026 11:18
Replace nested and duplicate response-helper branches with clearer direct
control flow. This addresses locally reproduced Warden simplifier feedback
without changing output behavior.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Allow snapshot normalization to handle the standard /Applications/Xcode.app
install path as well as versioned Xcode bundle names.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Comment thread src/snapshot-tests/__fixtures__/mcp/json/debugging/lldb-command--success.json Outdated
Comment thread src/utils/tool-registry.ts Outdated
Normalize LLDB breakpoint byte offsets in snapshot output and update the affected CLI/MCP JSON/text fixtures. Also avoid retaining stale MCP tool registrations when a previously registered tool fails to import during workflow re-selection.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Comment thread src/utils/responses/next-steps-renderer.ts Outdated
Comment thread src/snapshot-tests/suites/session-management-suite.ts
cameroncooke and others added 3 commits May 17, 2026 13:04
Add an explicit text-content guard when appending next-step text and reset persisted session defaults profile state after MCP snapshot tests that exercise persist:true.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Tighten snapshot harness error-state checks, keep error envelopes compatible with the error schema, and simplify the response helper cleanup Warden flagged.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Inline trivial test-runtime helper calls in typed-tool-factory while preserving the MCP runtime branch for minimal output and MCP next-step formatting.
Copy link
Copy Markdown
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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue. You can view the agent here.

Reviewed by Cursor Bugbot for commit 48c9078. Configure here.

Comment thread manifests/tools/swift_package_run.yaml
Comment thread src/mcp/tools/xcode-ide/xcode_ide_call_tool.ts
Require tool handlers to receive an explicit ToolHandlerContext instead of
supporting a no-context test response path. Update unit tests to use the
shared callHandler helper so tests provide context explicitly.

Remove the env-driven MCP next-step fallback test because MCP output should
be verified through the MCP boundary, not by forcing runtime state in handler
scaffolding. Document the no-fallback rule in AGENTS.md and CLAUDE.md.

Co-Authored-By: Codex <codex@openai.com>
@cameroncooke cameroncooke merged commit f68db5f into main May 17, 2026
24 of 25 checks passed
@cameroncooke cameroncooke deleted the structured_next_steps branch May 17, 2026 18:15
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