@@ -2,19 +2,25 @@ use codex_app_server_protocol::ServerNotification;
22use codex_app_server_protocol:: ThreadItem ;
33use codex_app_server_protocol:: Turn ;
44use codex_app_server_protocol:: TurnStatus ;
5+ use codex_core:: config:: ConfigBuilder ;
6+ use codex_protocol:: SessionId ;
7+ use codex_protocol:: ThreadId ;
58use codex_protocol:: models:: PermissionProfile ;
69use codex_protocol:: permissions:: FileSystemAccessMode ;
710use codex_protocol:: permissions:: FileSystemPath ;
811use codex_protocol:: permissions:: FileSystemSandboxEntry ;
912use codex_protocol:: permissions:: FileSystemSandboxPolicy ;
1013use codex_protocol:: permissions:: NetworkSandboxPolicy ;
14+ use codex_protocol:: protocol:: AskForApproval ;
15+ use codex_protocol:: protocol:: SessionConfiguredEvent ;
1116use codex_utils_absolute_path:: test_support:: PathBufExt ;
1217use codex_utils_absolute_path:: test_support:: test_path_buf;
1318use codex_utils_sandbox_summary:: summarize_permission_profile;
1419use owo_colors:: Style ;
1520use pretty_assertions:: assert_eq;
1621
1722use super :: EventProcessorWithHumanOutput ;
23+ use super :: config_summary_entries;
1824use super :: final_message_from_turn_items;
1925use super :: reasoning_text;
2026use super :: should_print_final_message_to_stdout;
@@ -168,6 +174,70 @@ fn summarizes_managed_read_only_permission_profile() {
168174 ) ;
169175}
170176
177+ #[ tokio:: test]
178+ async fn config_summary_entries_include_runtime_workspace_roots ( ) {
179+ let codex_home = tempfile:: tempdir ( ) . expect ( "create codex home" ) ;
180+ let cwd = tempfile:: tempdir ( ) . expect ( "create cwd" ) ;
181+ let extra_root = tempfile:: tempdir ( ) . expect ( "create extra root" ) ;
182+ let mut config = ConfigBuilder :: default ( )
183+ . codex_home ( codex_home. path ( ) . to_path_buf ( ) )
184+ . fallback_cwd ( Some ( cwd. path ( ) . to_path_buf ( ) ) )
185+ . build ( )
186+ . await
187+ . expect ( "build default config" ) ;
188+ let cwd = cwd. path ( ) . to_path_buf ( ) . abs ( ) ;
189+ let extra_root = extra_root. path ( ) . to_path_buf ( ) . abs ( ) ;
190+ let expected_extra_root =
191+ std:: fs:: canonicalize ( extra_root. as_path ( ) ) . expect ( "canonicalize extra root" ) ;
192+ config. cwd = cwd. clone ( ) ;
193+ config. workspace_roots = vec ! [ cwd. clone( ) , extra_root] ;
194+ config
195+ . permissions
196+ . set_workspace_roots ( config. workspace_roots . clone ( ) ) ;
197+ config
198+ . permissions
199+ . set_permission_profile ( PermissionProfile :: workspace_write_with (
200+ & [ ] ,
201+ NetworkSandboxPolicy :: Restricted ,
202+ /*exclude_tmpdir_env_var*/ true ,
203+ /*exclude_slash_tmp*/ true ,
204+ ) )
205+ . expect ( "set permission profile" ) ;
206+
207+ let session_configured_event = SessionConfiguredEvent {
208+ session_id : SessionId :: new ( ) ,
209+ thread_id : ThreadId :: new ( ) ,
210+ forked_from_id : None ,
211+ thread_source : None ,
212+ thread_name : None ,
213+ model : "gpt-5.4" . to_string ( ) ,
214+ model_provider_id : config. model_provider_id . clone ( ) ,
215+ service_tier : None ,
216+ approval_policy : AskForApproval :: Never ,
217+ approvals_reviewer : config. approvals_reviewer ,
218+ permission_profile : config. permissions . effective_permission_profile ( ) ,
219+ active_permission_profile : None ,
220+ cwd,
221+ reasoning_effort : None ,
222+ initial_messages : None ,
223+ network_proxy : None ,
224+ rollout_path : None ,
225+ } ;
226+
227+ let summary_entries = config_summary_entries ( & config, & session_configured_event) ;
228+ assert ! (
229+ summary_entries. iter( ) . any( |( key, value) | {
230+ * key == "sandbox"
231+ && * value
232+ == format!(
233+ "workspace-write [workdir, {}]" ,
234+ expected_extra_root. display( )
235+ )
236+ } ) ,
237+ "expected runtime workspace root in sandbox summary: {summary_entries:?}"
238+ ) ;
239+ }
240+
171241#[ test]
172242fn final_message_from_turn_items_uses_latest_agent_message ( ) {
173243 let message = final_message_from_turn_items ( & [
0 commit comments