@@ -707,6 +707,18 @@ pub struct ReviewTeamConfig {
707707 pub reviewer_file_split_threshold : usize ,
708708 /// Maximum number of same-role reviewer instances per role when file splitting is active.
709709 pub max_same_role_instances : usize ,
710+ /// Maximum retries for a failed same-role reviewer instance.
711+ pub max_retries_per_role : usize ,
712+ /// Maximum number of review instances that may run at the same time.
713+ pub max_parallel_reviewers : usize ,
714+ /// Seconds to wait for provider capacity before skipping unstarted work. 0 skips immediately.
715+ pub max_queue_wait_seconds : u64 ,
716+ /// Whether unstarted review work may wait for provider capacity.
717+ pub allow_provider_capacity_queue : bool ,
718+ /// Whether bounded automatic retry is allowed after a reviewer failure.
719+ pub allow_bounded_auto_retry : bool ,
720+ /// Elapsed-seconds guard that blocks bounded automatic retry after this delay.
721+ pub auto_retry_elapsed_guard_seconds : u64 ,
710722}
711723
712724impl Default for ReviewTeamConfig {
@@ -720,6 +732,12 @@ impl Default for ReviewTeamConfig {
720732 auto_fix_enabled : false ,
721733 reviewer_file_split_threshold : 20 ,
722734 max_same_role_instances : 3 ,
735+ max_retries_per_role : 1 ,
736+ max_parallel_reviewers : 2 ,
737+ max_queue_wait_seconds : 1200 ,
738+ allow_provider_capacity_queue : true ,
739+ allow_bounded_auto_retry : false ,
740+ auto_retry_elapsed_guard_seconds : 180 ,
723741 }
724742 }
725743}
@@ -3051,6 +3069,80 @@ mod tests {
30513069 ) ;
30523070 }
30533071
3072+ #[ test]
3073+ fn preserves_review_team_concurrency_fields_through_config_round_trip ( ) {
3074+ let config: AIConfig = serde_json:: from_value ( serde_json:: json!( {
3075+ "models" : [ ] ,
3076+ "default_models" : { } ,
3077+ "agent_profiles" : { } ,
3078+ "review_teams" : {
3079+ "default" : {
3080+ "extra_subagent_ids" : [ ] ,
3081+ "strategy_level" : "normal" ,
3082+ "member_strategy_overrides" : { } ,
3083+ "reviewer_timeout_seconds" : 3600 ,
3084+ "judge_timeout_seconds" : 2400 ,
3085+ "reviewer_file_split_threshold" : 20 ,
3086+ "max_same_role_instances" : 3 ,
3087+ "max_retries_per_role" : 1 ,
3088+ "max_parallel_reviewers" : 1 ,
3089+ "max_queue_wait_seconds" : 0 ,
3090+ "allow_provider_capacity_queue" : true ,
3091+ "allow_bounded_auto_retry" : false ,
3092+ "auto_retry_elapsed_guard_seconds" : 180
3093+ }
3094+ } ,
3095+ "proxy" : {
3096+ "enabled" : false ,
3097+ "url" : ""
3098+ }
3099+ } ) )
3100+ . expect ( "review team concurrency config should deserialize" ) ;
3101+
3102+ let serialized = serde_json:: to_value ( & config) . expect ( "config should serialize" ) ;
3103+ let stored = & serialized[ "review_teams" ] [ "default" ] ;
3104+ assert_eq ! ( stored[ "max_retries_per_role" ] , serde_json:: json!( 1 ) ) ;
3105+ assert_eq ! ( stored[ "max_parallel_reviewers" ] , serde_json:: json!( 1 ) ) ;
3106+ assert_eq ! ( stored[ "max_queue_wait_seconds" ] , serde_json:: json!( 0 ) ) ;
3107+ assert_eq ! (
3108+ stored[ "allow_provider_capacity_queue" ] ,
3109+ serde_json:: json!( true )
3110+ ) ;
3111+ assert_eq ! ( stored[ "allow_bounded_auto_retry" ] , serde_json:: json!( false ) ) ;
3112+ assert_eq ! (
3113+ stored[ "auto_retry_elapsed_guard_seconds" ] ,
3114+ serde_json:: json!( 180 )
3115+ ) ;
3116+ }
3117+
3118+ #[ test]
3119+ fn missing_review_team_concurrency_fields_use_product_defaults ( ) {
3120+ let config: AIConfig = serde_json:: from_value ( serde_json:: json!( {
3121+ "models" : [ ] ,
3122+ "review_teams" : {
3123+ "default" : {
3124+ "strategy_level" : "normal"
3125+ }
3126+ }
3127+ } ) )
3128+ . expect ( "legacy review team config should deserialize" ) ;
3129+
3130+ let serialized = serde_json:: to_value ( & config) . expect ( "config should serialize" ) ;
3131+ let stored = & serialized[ "review_teams" ] [ "default" ] ;
3132+ assert_eq ! ( stored[ "max_retries_per_role" ] , serde_json:: json!( 1 ) ) ;
3133+ assert_eq ! ( stored[ "max_parallel_reviewers" ] , serde_json:: json!( 2 ) ) ;
3134+ assert_eq ! ( stored[ "max_queue_wait_seconds" ] , serde_json:: json!( 1200 ) ) ;
3135+ assert_eq ! (
3136+ stored[ "allow_provider_capacity_queue" ] ,
3137+ serde_json:: json!( true )
3138+ ) ;
3139+ assert_eq ! ( stored[ "allow_bounded_auto_retry" ] , serde_json:: json!( false ) ) ;
3140+ assert_eq ! (
3141+ stored[ "auto_retry_elapsed_guard_seconds" ] ,
3142+ serde_json:: json!( 180 )
3143+ ) ;
3144+ }
3145+
30543146 #[ test]
30553147 fn review_team_auxiliary_config_is_not_stored_inside_review_team_map ( ) {
30563148 let config: AIConfig = serde_json:: from_value ( serde_json:: json!( {
0 commit comments