Skip to content

Expand cross-SDK scenario and RPC E2E coverage - #2724

Merged
stephentoub merged 1 commit into
mainfrom
stephentoub-e2e-github-app-coverage
Sep 20, 2026
Merged

stephentoub merged 1 commit into
mainfrom
stephentoub-e2e-github-app-coverage

Conversation

@stephentoub

Copy link
Copy Markdown
Collaborator

Why

The SDKs had broad feature tests, but they did not systematically cover representative production workflows or guarantee that every public generated RPC method was referenced by a test. This made it easy for important composition, lifecycle, callback, persistence, and generated-contract regressions to go unnoticed.

What changed

  • Adds a 92-case ScenarioTesting baseline in C# covering realistic startup, session, send, event, recovery, permission, callback, provider, MCP, canvas, persistence, queue, factory, and remote-control workflows.
  • Audits the complete public generated RPC surface using exact declaring type, namespace, and signature references rather than name-only matching.
  • Replicates every publicly expressible scenario across Node.js, Python, Go, Rust, and Java, with explicit classifications where a language does not expose the relevant cloud, canvas-host, JavaScript-extension, or cancellation abstraction.
  • Adds exact generated RPC coverage for each language's actual public surface:
    • C#, Node.js, Python, and Go: 314/314
    • Rust: 326/326
    • Java: 373/373
  • Uses deterministic local replay servers and local fake CLI/MCP processes. New coverage does not contact upstream services or depend on timing sleeps.
  • Removes two legacy C# E2E classes whose coverage became exactly redundant with the scenario suite.

The expanded coverage found and fixes several SDK defects, including C# extension launch-provider registration and transport-failure completion, Python generated union dispatch and transport error normalization, Go metadata-union decoding and pending TCP request completion, and Rust extension-context optionality.

Validation

  • C#: 92/92 scenario cases passed on both net8.0 and net472; RPC surface tests passed on both frameworks; final integrated regression passed 98/98 on net8.0.
  • Node.js: lint/type-check and changed-file formatting passed; focused changed/new E2Es, exact RPC audit, codegen, and repeated deterministic suites passed.
  • Python: Ruff and type checking passed; focused integration validation passed 57/57. The broad suite reached 961 passed and 9 skipped, with three reproduced pre-existing replay/configuration failures.
  • Go: gofmt, go vet, build, unit tests, focused E2Es, and repeated reliability runs passed. A broad run encountered existing replay misses and timeout behavior outside the changed coverage.
  • Java: Spotless, Checkstyle, focused suites, and full mvn verify passed; native Node validation passed 93/93.
  • Rust: formatting, focused Clippy, RPC, canvas, client-options, attachment, delivery, and skills coverage passed. The broad E2E run reached 412 passed and 9 ignored, with two reproduced pre-existing mode-handler replay misses.
  • Final diff and worktree checks are clean.

Review notes

This is intentionally a large test-focused change because the scenario catalog and generated RPC audits are cross-language consistency guarantees. Most tests share the existing replay infrastructure; fake-runtime tests are reserved for host-owned or contract-only surfaces that cannot be exercised deterministically through the replayed runtime.

Generated by Copilot

Copilot AI balanced review requested due to automatic review settings September 18, 2026 18:24
@stephentoub
stephentoub requested a review from a team as a code owner September 18, 2026 18:24
Comment thread java/sdk/src/test/java/com/github/copilot/RpcSurfaceTestCli.java Fixed
Comment thread java/sdk/src/test/java/com/github/copilot/ScenarioTestCli.java Fixed
Comment thread python/e2e/test_scenario_sends_e2e.py

Copilot AI left a comment

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.

Copilot review overview

🟡 Changes recommended

The Rust atomic-replacement scenario is not atomic, and one .NET ordering test relies on a fixed timing delay.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 2 Medium severity

Open (2)
What changed in this PR

Expands deterministic cross-SDK scenario and generated RPC coverage while fixing transport, serialization, and extension-context defects.

Changes:

  • Adds cross-language workflow scenarios and replay snapshots.
  • Audits generated RPC surfaces across all SDKs.
  • Fixes Python/Go/.NET transport and decoding behavior plus Rust attachment support.
File Description
test/​snapshots/​scenario_testing_utility/​should_send_wait_observe_idle_events_and_delete_suggestion_session.yaml Adds utility workflow replay.
test/​snapshots/​scenario_testing_tools/​should_preserve_scenario_tool_invocation_identity_arguments_and_text.yaml Adds tool identity replay.
test/​snapshots/​scenario_testing_tools/​should_isolate_scenario_tool_handler_error.yaml Adds tool-error replay.
test/​snapshots/​scenario_testing_tools/​should_deliver_expanded_scenario_tool_result_to_the_model.yaml Adds expanded-result replay.
test/​snapshots/​scenario_testing_tools/​should_cancel_scenario_tool_handler_when_session_disposes.yaml Adds cancellation replay.
test/​snapshots/​scenario_testing_tools/​should_advertise_scenario_tool_schema_override_and_availability.yaml Adds tool-schema replay.
test/​snapshots/​scenario_testing_skills_and_agents/​should_reload_atomically_replaced_skill_and_replay_it_on_resume.yaml Adds skill-reload fixture.
test/​snapshots/​scenario_testing_skills_and_agents/​should_classify_agent_method_not_found_as_remote_protocol_error.yaml Adds protocol-error fixture.
test/​snapshots/​scenario_testing_sends/​should_order_idle_queued_and_immediate_scenario_delivery.yaml Adds delivery-order replay.
test/​snapshots/​scenario_testing_runtime/​should_ping_then_reuse_client_across_two_sessions.yaml Adds runtime-reuse replay.
test/​snapshots/​scenario_testing_providers/​should_apply_reasoning_context_and_auto_atomically_without_implicit_reset.yaml Adds provider-state fixture.
test/​snapshots/​scenario_testing_persistence/​should_truncate_history_and_resend_from_boundary.yaml Adds history-truncation replay.
test/​snapshots/​scenario_testing_persistence/​should_retry_from_existing_history_with_empty_sendmessages.yaml Adds empty-batch replay.
test/​snapshots/​scenario_testing_persistence/​should_page_persisted_events_backward_without_resuming.yaml Adds event-pagination replay.
test/​snapshots/​scenario_testing_permissions/​should_forward_exact_scenario_permission_callback_payload.yaml Adds permission replay.
test/​snapshots/​scenario_testing_mcp/​should_preserve_disabled_scenario_mcp_servers_across_reload_and_resume.yaml Adds MCP-state replay.
test/​snapshots/​scenario_testing_lifecycle_recovery/​should_suspend_disconnect_and_resume_scenario_state_without_delete.yaml Adds lifecycle-resume replay.
test/​snapshots/​scenario_testing_lifecycle_recovery/​should_abort_active_scenario_turn_and_remain_usable.yaml Updates abort-recovery replay.
test/​snapshots/​scenario_testing_js_extension_bridge/​should_surface_structured_canvaserror_from_js_extension.yaml Adds canvas-error fixture.
test/​snapshots/​scenario_testing_js_extension_bridge/​should_bridge_js_extension_canvas_context_log_and_session_continuation.yaml Adds extension-bridge replay.
test/​snapshots/​scenario_testing_event_subscriptions/​should_stop_closed_and_replaced_scenario_event_sources.yaml Adds event-source replay.
test/​snapshots/​scenario_testing_event_subscriptions/​should_deliver_mixed_scenario_event_stream_in_order_after_handler_lag.yaml Adds ordered-event replay.
test/​snapshots/​scenario_testing_empty_runtime/​empty_mode_minimal_toolless_session_has_no_tools.yaml Adds empty-runtime replay.
test/​snapshots/​scenario_testing_control_state/​should_report_processing_while_scenario_tool_is_running.yaml Adds processing-state replay.
test/​snapshots/​scenario_testing_composition/​should_send_scenario_message_with_metadata_and_extension_context.yaml Adds extension-context replay.
test/​snapshots/​scenario_testing_composition/​should_retry_resume_on_replacement_client_after_recoverable_setup_failure.yaml Adds replacement-client replay.
test/​snapshots/​scenario_testing_composition/​should_resume_with_reattached_scenario_host_state.yaml Adds host-state replay.
test/​snapshots/​scenario_testing_composition/​should_read_persisted_scenario_events_without_resuming.yaml Adds persisted-event replay.
test/​snapshots/​scenario_testing_composition/​should_not_emit_redundant_model_change_when_resuming_same_model.yaml Adds model-resume replay.
test/​snapshots/​scenario_testing_composition/​should_classify_queued_and_immediate_scenario_messages_while_busy.yaml Adds busy-delivery replay.
test/​snapshots/​scenario_testing_cloud/​should_notify_steerability_then_send_first_message_without_remote_enable.yaml Adds cloud-steering replay.
test/​snapshots/​scenario_testing_canvas/​should_run_ordered_scenario_canvas_lifecycle_with_exact_context_and_snapshot.yaml Adds canvas-lifecycle fixture.
test/​snapshots/​scenario_testing_canvas/​should_reattach_scenario_canvas_and_route_all_callbacks_after_resume.yaml Adds canvas-resume replay.
test/​snapshots/​scenario_testing_canvas/​should_handle_structured_scenario_canvas_error.yaml Adds canvas-error fixture.
test/​snapshots/​scenario_testing_callbacks/​should_run_scenario_prompt_and_tool_hooks_with_full_context_and_suppression.yaml Adds hook replay.
test/​snapshots/​scenario_testing_callbacks/​should_cancel_scenario_host_callback_when_channel_disconnects.yaml Adds callback-cancellation replay.
test/​snapshots/​scenario_testing_callbacks/​should_auto_switch_scenario_mode_after_rate_limit.yaml Adds rate-limit replay.
test/​snapshots/​scenario_testing_callbacks/​should_approve_scenario_exit_plan_with_full_callback_and_event_state.yaml Adds plan-approval replay.
test/​snapshots/​mode_handlers/​should_invoke_exit_plan_mode_handler_when_model_uses_tool.yaml Updates plan-handler response.
test/​snapshots/​mode_handlers/​should_invoke_auto_mode_switch_handler_when_rate_limited.yaml Updates auto-mode response.
test/​harness/​test-mcp-app-server.mjs Adds local MCP app server.
test/​harness/​replayingCapiProxy.ts Adds replay-only proxy mode.
test/​harness/​replayingCapiProxy.test.ts Tests replay-only behavior.
scripts/​codegen/​python.ts Fixes external union loading.
rust/​tests/​e2e/​skills.rs Adds skill reload/resume coverage.
rust/​tests/​e2e/​event_fidelity.rs Adds delivery-order coverage.
rust/​tests/​e2e.rs Registers RPC surface tests.
rust/​src/​types.rs Adds extension-context attachments.
python/​e2e/​test_scenario_session_setup_e2e.py Tests session setup ordering.
python/​e2e/​test_scenario_sends_e2e.py Tests send serialization and cancellation.
python/​e2e/​test_scenario_lifecycle_recovery_e2e.py Tests recoverable lifecycle failures.
python/​e2e/​test_scenario_cloud_e2e.py Tests cloud workflows.
python/​e2e/​test_scenario_canvas_e2e.py Tests canvas callback routing.
python/​copilot/​session.py Exposes extension-context attachments.
python/​copilot/​generated/​rpc.py Uses generated union loaders.
python/​copilot/​_jsonrpc.py Normalizes process-exit write errors.
nodejs/​test/​session-event-codegen.test.ts Tests union-loader codegen.
nodejs/​test/​e2e/​scenario_testing_recovery.e2e.test.ts Adds lifecycle recovery scenarios.
nodejs/​test/​e2e/​scenario_testing_persistence.e2e.test.ts Adds persistence scenario.
nodejs/​test/​e2e/​scenario_testing_composition.e2e.test.ts Adds resume composition scenario.
nodejs/​test/​e2e/​rpc_workspace_checkpoints.e2e.test.ts Expands workspace diff modes.
nodejs/​test/​e2e/​permissions.e2e.test.ts Verifies full permission payload.
nodejs/​test/​e2e/​client_options.e2e.test.ts Covers resumed provider options.
nodejs/​test/​e2e/​canvas.e2e.test.ts Covers structured canvas errors.
nodejs/​test/​e2e/​abort.e2e.test.ts Expands abort-state assertions.
java/​sdk/​src/​test/​java/​com/​github/​copilot/​ScenarioTestCli.java Adds in-process scenario runtime.
java/​sdk/​src/​test/​java/​com/​github/​copilot/​ScenarioCoverageE2ETest.java Adds Java workflow coverage.
java/​sdk/​src/​test/​java/​com/​github/​copilot/​RpcSurfaceTestCli.java Adds RPC recording runtime.
go/​rpc/​sessions_client_metadata_json.go Decodes metadata unions.
go/​rpc/​sessions_client_metadata_json_test.go Tests metadata decoding.
go/​internal/​jsonrpc2/​jsonrpc2.go Completes requests on disconnect.
go/​internal/​jsonrpc2/​jsonrpc2_test.go Tests disconnect completion.
go/​internal/​e2e/​scenario_testing_control_state_e2e_test.go Tests Go processing state.
dotnet/​test/​Unit/​JsonRpcTests.cs Tests disposal cleanup.
dotnet/​test/​Unit/​CloneTests.cs Covers launch-provider cloning.
dotnet/​test/​Harness/​ReplayProxy.cs Passes replay-only configuration.
dotnet/​test/​Harness/​E2ETestContext.cs Exposes replay-only setup.
dotnet/​test/​Harness/​E2ETestBase.cs Configures replay-only suites.
dotnet/​test/​E2E/​ScenarioTestingUtilityE2ETests.cs Adds utility scenario.
dotnet/​test/​E2E/​ScenarioTestingToolsE2ETests.cs Adds tool scenarios.
dotnet/​test/​E2E/​ScenarioTestingSkillsAndAgentsE2ETests.cs Adds skills and agent scenarios.
dotnet/​test/​E2E/​ScenarioTestingServerControlE2ETests.cs Adds server-control scenarios.
dotnet/​test/​E2E/​ScenarioTestingPersistenceE2ETests.cs Adds persistence scenarios.
dotnet/​test/​E2E/​ScenarioTestingPermissionsE2ETests.cs Adds permission scenarios.
dotnet/​test/​E2E/​ScenarioTestingLifecycleRecoveryE2ETests.cs Adds lifecycle recovery scenarios.
dotnet/​test/​E2E/​ScenarioTestingEventSubscriptionsE2ETests.cs Adds event subscription scenarios.
dotnet/​test/​E2E/​ScenarioTestingEmptyRuntimeE2ETests.cs Adds empty-runtime scenario.
dotnet/​test/​E2E/​ScenarioTestingE2ETestBase.cs Defines replay-only scenario base.
dotnet/​test/​E2E/​ScenarioTestingControlStateE2ETests.cs Adds control-state scenarios.
dotnet/​test/​E2E/​ScenarioTestingCloudE2ETests.cs Adds cloud scenarios.
dotnet/​test/​E2E/​ModeHandlersE2ETests.cs Removes redundant mode-handler tests.
dotnet/​test/​E2E/​ExternalToolCancellationE2ETests.cs Removes redundant cancellation test.
dotnet/​src/​Types.cs Adds launch-provider option.
dotnet/​src/​JsonRpc.cs Guarantees disposal cleanup.
dotnet/​src/​Client.cs Registers providers and process-exit handling.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread dotnet/test/E2E/ScenarioTestingEventSubscriptionsE2ETests.cs Outdated
Comment thread rust/tests/e2e/skills.rs Outdated
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

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.

Generated by SDK Consistency Review Agent for #2724 · copilot · sonnet50 · 110.2 AIC · ⌖ 11.7 AIC · ⊞ 7.8K

Comment thread dotnet/src/Types.cs
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

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.

Generated by SDK Consistency Review Agent for #2724 · copilot · sonnet50 · 116.7 AIC · ⌖ 11.8 AIC · ⊞ 7.8K

Comment thread dotnet/src/Types.cs
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Comment thread dotnet/test/E2E/ScenarioTestingEventSubscriptionsE2ETests.cs Fixed
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

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.

Generated by SDK Consistency Review Agent for #2724 · copilot · sonnet50 · 172.6 AIC · ⌖ 13.2 AIC · ⊞ 7.8K

Comment thread python/copilot/session.py
Comment thread dotnet/src/Client.cs
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

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.

Generated by SDK Consistency Review Agent for #2724 · copilot · sonnet50 · 61.9 AIC · ⌖ 11.8 AIC · ⊞ 7.8K

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

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.

Generated by SDK Consistency Review Agent for #2724 · copilot · sonnet50 · 77.1 AIC · ⌖ 11.6 AIC · ⊞ 7.8K

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@stephentoub
stephentoub force-pushed the stephentoub-e2e-github-app-coverage branch from 7522e91 to c2c4644 Compare September 20, 2026 02:16
@github-actions

Copy link
Copy Markdown
Contributor

SDK Consistency Review — PR #2724

Reviewed the authoritative PR delta (get_files/get_diff) across all six SDKs plus shared codegen/test-harness/snapshot changes.

Findings: ✅ Consistent across all SDKs

This PR introduces two new experimental features and rolls them out uniformly:

  1. ExtensionLaunchProvider (connection-level, registered during start/Start before any session can be created):

    • Node.js: CopilotClientOptions.extensionLaunchProvider, ClientGlobalApiHandlers.extensionLaunchProvider, rpc.registerExtensionLaunchProvider()
    • Python: extension_launch_provider ctor param, ClientGlobalApiHandlers.extension_launch_provider, rpc.register_extension_launch_provider()
    • Go: ClientOptions.ExtensionLaunchProvider, ClientGlobalAPIHandlers.ExtensionLaunchProvider, RPC.RegisterExtensionLaunchProvider
    • .NET: ClientOptions.ExtensionLaunchProvider (IExtensionLaunchProviderHandler), RegisterExtensionLaunchProviderAsync
    • Java: CopilotClientOptions.setExtensionLaunchProvider/getExtensionLaunchProvider, new ExtensionLaunchProviderAdapter bridging the reverse RPC, registerExtensionLaunchProvider().join()
    • Rust: extension_launch_provider.rs, wired through router.rs/lib.rs

    Naming follows each language's idiom (camelCase/PascalCase/snake_case) and the registration flow (register before sessions can be created) is identical everywhere.

  2. ExtensionContextAttachment (new MessageOptions/Attachment variant, type discriminator "extension_context", fields: capturedAt, extensionId, title, optional canvasId, instanceId, payload):

    • Present in Node.js (types.ts), Python (session.py TypedDict), Go (generated AttachmentExtensionContext), .NET (generated AttachmentExtensionContext), Java (new ExtensionContextAttachment implementing MessageAttachment, registered in the @JsonSubTypes/permits list alongside Attachment/BlobAttachment), and Rust (Attachment::ExtensionContext variant in types.rs, generated AttachmentExtensionContext).
    • Field shape and the "extension_context" discriminator are consistent across all six languages.
  3. Supporting changes (Python _jsonrpc.py process-exit-error handling, Go ffihost/jsonrpc2 fixes, generated-type polymorphism fixes in python/copilot/generated/rpc.py) are internal/bugfix-style and don't need cross-SDK mirroring by design.

  4. The large volume of added E2E scenario tests (ScenarioTesting* in .NET, scenario_testing_* in Go/Node/Python/Rust/Java, plus corresponding test/snapshots/ fixtures) exercise the same feature set per language and look proportionate/parallel across SDKs.

No cross-SDK gaps or naming inconsistencies were found. No inline review comments needed.

Generated by SDK Consistency Review Agent for #2724 · copilot · sonnet50 · 41.5 AIC · ⌖ 11.7 AIC · ⊞ 7.8K ·

@stephentoub
stephentoub merged commit 9515b5e into main Sep 20, 2026
286 of 290 checks passed
@stephentoub
stephentoub deleted the stephentoub-e2e-github-app-coverage branch September 20, 2026 12:02
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.

3 participants