Test disabled enhanced Node REPL transcript images separately (#39509)

## What changed

- Add a focused Code Mode integration test with Guardian transcript images enabled and enhanced Node REPL transcripts disabled.
- Verify that the Guardian request and parent request omit both the screenshot and its surrounding transcript markers.
- Remove this configuration from the broader parameterized transcript-evidence test.

GitOrigin-RevId: 1309de12337a28a7e1d49eca509ba73207d4d9be
This commit is contained in:
jif
2026-08-19 15:09:56 +00:00
committed by copyberry
parent eb5a25aaa2
commit 6972c57c78

View File

@@ -4377,10 +4377,103 @@ async fn code_mode_node_repl_screenshots_can_be_captured_without_guardian_transc
Ok(())
}
#[cfg_attr(windows, ignore = "no exec_command on Windows")]
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn code_mode_node_repl_image_flag_without_enhanced_stays_disabled() -> Result<()> {
skip_if_no_network!(Ok(()));
skip_if_sandbox!(Ok(()));
skip_if_wine_exec!(
Ok(()),
"Guardian approval actions require host-native paths"
);
let server = responses::start_mock_server().await;
let mcp_server_bin = remote_aware_stdio_server_bin()?;
let mut builder = test_codex()
.with_model_info_override("gpt-5.5", |model| {
model.node_repl_auto_review_required = false;
})
.with_config(move |config| {
config.permissions.approval_policy = Constrained::allow_any(AskForApproval::OnRequest);
config.approvals_reviewer = ApprovalsReviewer::AutoReview;
config
.features
.enable(Feature::CodeMode)
.expect("enable Code Mode");
config
.features
.set_enabled(
Feature::GuardianEnhancedNodeReplTranscripts,
/*enabled*/ false,
)
.expect("disable enhanced Guardian transcripts");
config
.features
.enable(Feature::GuardianNodeReplTranscriptImages)
.expect("enable Guardian transcript images");
let mcp = serde_json::from_value(serde_json::json!({
"command": mcp_server_bin,
"environment_id": remote_aware_environment_id(),
"env": { "MCP_TEST_ENABLE_NODE_REPL_JS": "1" },
"omit_tools_from": ["deferred"],
}))
.expect("valid node_repl MCP server config");
config
.mcp_servers
.set(HashMap::from([("node_repl".to_owned(), mcp)]))
.expect("configure node_repl MCP server");
});
let test = builder.build_with_auto_env(&server).await?;
wait_for_mcp_server(&test.codex, "node_repl").await?;
let code = r#"
await tools.mcp__node_repl__js({ code: 'await nodeRepl.emitImage(await tab.screenshot())' });
await tools.exec_command({ cmd: "true", sandbox_permissions: "require_escalated", justification: "review" });
"#;
let response_mock = responses::mount_sse_sequence(
&server,
vec![
sse(vec![
ev_custom_tool_call("code-mode-call", "exec", code),
ev_completed("resp-parent"),
]),
sse(vec![
ev_assistant_message("guardian", r#"{"outcome":"allow"}"#),
ev_completed("resp-guardian"),
]),
sse(vec![ev_completed("resp-done")]),
],
)
.await;
test.submit_text_turn("review a nested node_repl screenshot")
.await?;
let requests = response_mock.requests();
assert_eq!(requests.len(), 3);
let guardian_request = requests
.iter()
.find(|request| {
request.body_json()["client_metadata"]["x-openai-subagent"].as_str() == Some("guardian")
})
.expect("the shell command should trigger Guardian review");
assert!(guardian_request.message_input_image_urls("user").is_empty());
let guardian_text = guardian_request.message_input_texts("user").concat();
let parent_input = serde_json::to_string(&requests.last().unwrap().input())?;
for marker in [
"guardian-visible-before-image",
"guardian-visible-after-image",
"data:image/png;base64,",
] {
assert!(!guardian_text.contains(marker));
assert!(!parent_input.contains(marker));
}
Ok(())
}
#[cfg_attr(windows, ignore = "no exec_command on Windows")]
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[test_case(false, false, false, None; "disabled")]
#[test_case(false, true, false, None; "image_flag_without_enhanced_stays_disabled")]
#[test_case(true, false, false, None; "manually_enabled_text_only")]
#[test_case(true, true, false, None; "manually_enabled_multimodal")]
#[test_case(false, false, true, None; "required_model_forces_multimodal")]