@@ -52,7 +52,7 @@ enum Command {
5252#[ derive( Debug , Parser ) ]
5353#[ command(
5454 after_help = concat!(
55- "Examples:\n loopmux run -t ai:5.0 -n 5 --prompt \" Do the next iteration.\" --trigger \" Concluded|What is next\" --once\n loopmux run -t ai:5.0 -n 5 --prompt \" Do the next iteration.\" --trigger \" Concluded|What is next\" --exclude \" PROD\" \n loopmux run --config loop.yaml --duration 2h\n loopmux run --tui\n loopmux run --exec \" gw-watch-comp\" --poll 10 --iterations 3\n \n Defaults:\n tail=1 (last non-blank line)\n poll=5s\n trigger-confirm-seconds=5\n history-limit=50\n log-preview-lines=3\n trigger-edge=on\n recheck-before-send=on\n \n Duration units: s, m, h, d, w, mon (30d), y (365d)\n \n " ,
55+ "Examples:\n loopmux run -t ai:5.0 -n 5 --prompt \" Do the next iteration.\" --trigger \" Concluded|What is next\" --once\n loopmux run -t ai:5.0 -n 5 --prompt \" Do the next iteration.\" --trigger \" Concluded|What is next\" --exclude \" PROD\" \n loopmux run --config loop.yaml --duration 2h\n loopmux run --tui\n loopmux run --exec \" gw-watch-comp\" --poll 10 --iterations 3\n \n Defaults:\n tail=1 (last non-blank line)\n poll=5s\n initial-poll=5s \n trigger-confirm-seconds=5\n history-limit=50\n log-preview-lines=3\n trigger-edge=on\n recheck-before-send=on\n \n Duration units: s, m, h, d, w, mon (30d), y (365d)\n \n " ,
5656 "Version: " ,
5757 env!( "CARGO_PKG_VERSION" ) ,
5858 "\n "
@@ -122,6 +122,9 @@ struct RunArgs {
122122 /// Poll interval in seconds when waiting for changes.
123123 #[ arg( long) ]
124124 poll : Option < u64 > ,
125+ /// Initial wait in seconds before the second scan (default 5).
126+ #[ arg( long) ]
127+ initial_poll : Option < u64 > ,
125128 /// Seconds a trigger must remain matched before send (default 5).
126129 #[ arg( long) ]
127130 trigger_confirm_seconds : Option < u64 > ,
@@ -149,6 +152,7 @@ struct RunArgs {
149152}
150153
151154const DEFAULT_HISTORY_LIMIT : usize = 50 ;
155+ const DEFAULT_INITIAL_POLL_SECONDS : u64 = 5 ;
152156const DEFAULT_TRIGGER_CONFIRM_SECONDS : u64 = 5 ;
153157
154158#[ derive( Debug , Serialize , Deserialize , Default ) ]
@@ -172,6 +176,7 @@ struct HistoryEntry {
172176 head : Option < usize > ,
173177 once : bool ,
174178 poll : Option < u64 > ,
179+ initial_poll : Option < u64 > ,
175180 trigger_confirm_seconds : Option < u64 > ,
176181 log_preview_lines : Option < usize > ,
177182 trigger_edge : Option < bool > ,
@@ -315,6 +320,7 @@ struct Config {
315320 iterations : Option < u32 > ,
316321 infinite : Option < bool > ,
317322 poll : Option < u64 > ,
323+ initial_poll : Option < u64 > ,
318324 trigger_confirm_seconds : Option < u64 > ,
319325 log_preview_lines : Option < usize > ,
320326 trigger_edge : Option < bool > ,
@@ -1560,6 +1566,9 @@ fn hydrate_run_args_from_history(mut args: RunArgs) -> Result<RunArgs> {
15601566 if args. poll . is_none ( ) {
15611567 args. poll = entry. poll ;
15621568 }
1569+ if args. initial_poll . is_none ( ) {
1570+ args. initial_poll = entry. initial_poll ;
1571+ }
15631572 if args. trigger_confirm_seconds . is_none ( ) {
15641573 args. trigger_confirm_seconds = entry. trigger_confirm_seconds ;
15651574 }
@@ -3228,7 +3237,7 @@ fn history_signature(args: &RunArgs) -> Option<String> {
32283237 return None ;
32293238 }
32303239 Some ( format ! (
3231- "target={target}|prompt={prompt}|trigger={trigger}|trigger_expr={trigger_expr}|trigger_exact_line={}|exclude={}|pre={}|post={}|iterations={}|tail={}|head={}|once={}|poll={}|trigger_confirm_seconds={}|log_preview_lines={}|trigger_edge={}|recheck_before_send={}|fanout={}|duration={}" ,
3240+ "target={target}|prompt={prompt}|trigger={trigger}|trigger_expr={trigger_expr}|trigger_exact_line={}|exclude={}|pre={}|post={}|iterations={}|tail={}|head={}|once={}|poll={}|initial_poll={}| trigger_confirm_seconds={}|log_preview_lines={}|trigger_edge={}|recheck_before_send={}|fanout={}|duration={}" ,
32323241 args. trigger_exact_line,
32333242 args. exclude. as_deref( ) . unwrap_or( "" ) ,
32343243 args. pre. as_deref( ) . unwrap_or( "" ) ,
@@ -3238,6 +3247,7 @@ fn history_signature(args: &RunArgs) -> Option<String> {
32383247 args. head. map( |v| v. to_string( ) ) . unwrap_or_default( ) ,
32393248 args. once,
32403249 args. poll. map( |v| v. to_string( ) ) . unwrap_or_default( ) ,
3250+ args. initial_poll. map( |v| v. to_string( ) ) . unwrap_or_default( ) ,
32413251 args. trigger_confirm_seconds
32423252 . map( |v| v. to_string( ) )
32433253 . unwrap_or_default( ) ,
@@ -3281,6 +3291,7 @@ fn store_run_history(args: &RunArgs) -> Result<()> {
32813291 head : args. head ,
32823292 once : args. once ,
32833293 poll : args. poll ,
3294+ initial_poll : args. initial_poll ,
32843295 trigger_confirm_seconds : args. trigger_confirm_seconds ,
32853296 log_preview_lines : args. log_preview_lines ,
32863297 trigger_edge : Some ( !args. no_trigger_edge ) ,
@@ -3297,7 +3308,7 @@ fn store_run_history(args: &RunArgs) -> Result<()> {
32973308
32983309fn history_entry_signature ( entry : & HistoryEntry ) -> Option < String > {
32993310 Some ( format ! (
3300- "target={}|prompt={}|trigger={}|trigger_expr={}|trigger_exact_line={}|exclude={}|pre={}|post={}|iterations={}|tail={}|head={}|once={}|poll={}|trigger_confirm_seconds={}|log_preview_lines={}|trigger_edge={}|recheck_before_send={}|fanout={}|duration={}" ,
3311+ "target={}|prompt={}|trigger={}|trigger_expr={}|trigger_exact_line={}|exclude={}|pre={}|post={}|iterations={}|tail={}|head={}|once={}|poll={}|initial_poll={}| trigger_confirm_seconds={}|log_preview_lines={}|trigger_edge={}|recheck_before_send={}|fanout={}|duration={}" ,
33013312 entry. target,
33023313 entry. prompt,
33033314 entry. trigger,
@@ -3311,6 +3322,10 @@ fn history_entry_signature(entry: &HistoryEntry) -> Option<String> {
33113322 entry. head. map( |v| v. to_string( ) ) . unwrap_or_default( ) ,
33123323 entry. once,
33133324 entry. poll. map( |v| v. to_string( ) ) . unwrap_or_default( ) ,
3325+ entry
3326+ . initial_poll
3327+ . map( |v| v. to_string( ) )
3328+ . unwrap_or_default( ) ,
33143329 entry
33153330 . trigger_confirm_seconds
33163331 . map( |v| v. to_string( ) )
@@ -3442,6 +3457,7 @@ fn run_loop(config: ResolvedConfig, identity: RunIdentity) -> Result<()> {
34423457 let run_started = std:: time:: Instant :: now ( ) ;
34433458 let mut held_total = std:: time:: Duration :: from_secs ( 0 ) ;
34443459 let mut hold_started: Option < std:: time:: Instant > = None ;
3460+ let mut first_wait_cycle = true ;
34453461 fleet_registry. update ( & config. target_label , loop_state, send_count, config. poll ) ?;
34463462
34473463 while config. infinite || send_count < max_sends {
@@ -3770,14 +3786,20 @@ fn run_loop(config: ResolvedConfig, identity: RunIdentity) -> Result<()> {
37703786 let _ = std:: io:: stdout ( ) . flush ( ) ;
37713787 }
37723788
3789+ let wait_seconds = if first_wait_cycle {
3790+ config. initial_poll
3791+ } else {
3792+ config. poll
3793+ } ;
37733794 sleep_with_heartbeat (
37743795 & fleet_registry,
37753796 & config. target_label ,
37763797 loop_state,
37773798 send_count,
3778- config . poll ,
3799+ wait_seconds ,
37793800 config. poll ,
37803801 ) ?;
3802+ first_wait_cycle = false ;
37813803 continue ;
37823804 }
37833805
@@ -4289,8 +4311,13 @@ fn run_loop(config: ResolvedConfig, identity: RunIdentity) -> Result<()> {
42894311 }
42904312
42914313 if ui_mode == UiMode :: Tui {
4314+ let wait_seconds = if first_wait_cycle {
4315+ config. initial_poll
4316+ } else {
4317+ config. poll
4318+ } ;
42924319 let sleep_until =
4293- std:: time:: Instant :: now ( ) + std:: time:: Duration :: from_secs ( config . poll ) ;
4320+ std:: time:: Instant :: now ( ) + std:: time:: Duration :: from_secs ( wait_seconds ) ;
42944321 let mut should_exit_loop = false ;
42954322 while std:: time:: Instant :: now ( ) < sleep_until {
42964323 if let Some ( tui_state) = tui. as_mut ( ) {
@@ -4402,15 +4429,22 @@ fn run_loop(config: ResolvedConfig, identity: RunIdentity) -> Result<()> {
44024429 if force_rescan {
44034430 continue ;
44044431 }
4432+ first_wait_cycle = false ;
44054433 } else {
4434+ let wait_seconds = if first_wait_cycle {
4435+ config. initial_poll
4436+ } else {
4437+ config. poll
4438+ } ;
44064439 sleep_with_heartbeat (
44074440 & fleet_registry,
44084441 & config. target_label ,
44094442 loop_state,
44104443 send_count,
4411- config . poll ,
4444+ wait_seconds ,
44124445 config. poll ,
44134446 ) ?;
4447+ first_wait_cycle = false ;
44144448 }
44154449 }
44164450
@@ -5071,6 +5105,7 @@ fn resolve_run_config(args: &RunArgs) -> Result<Config> {
50715105 iterations : args. iterations ,
50725106 infinite : None ,
50735107 poll : args. poll ,
5108+ initial_poll : args. initial_poll ,
50745109 trigger_confirm_seconds : args. trigger_confirm_seconds ,
50755110 log_preview_lines : args. log_preview_lines ,
50765111 trigger_edge : Some ( !args. no_trigger_edge ) ,
@@ -5152,6 +5187,7 @@ fn resolve_run_config(args: &RunArgs) -> Result<Config> {
51525187 iterations : args. iterations ,
51535188 infinite : None ,
51545189 poll : args. poll ,
5190+ initial_poll : args. initial_poll ,
51555191 trigger_confirm_seconds : args. trigger_confirm_seconds ,
51565192 log_preview_lines : args. log_preview_lines ,
51575193 trigger_edge : Some ( !args. no_trigger_edge ) ,
@@ -5241,6 +5277,7 @@ struct ResolvedConfig {
52415277 infinite : bool ,
52425278 has_prompt : bool ,
52435279 poll : u64 ,
5280+ initial_poll : u64 ,
52445281 trigger_confirm_seconds : u64 ,
52455282 log_preview_lines : usize ,
52465283 trigger_edge : bool ,
@@ -6099,6 +6136,10 @@ fn resolve_config(
60996136 }
61006137
61016138 let poll = config. poll . unwrap_or ( 5 ) . max ( 1 ) ;
6139+ let initial_poll = config
6140+ . initial_poll
6141+ . unwrap_or ( DEFAULT_INITIAL_POLL_SECONDS )
6142+ . max ( 1 ) ;
61026143 let trigger_confirm_seconds = config
61036144 . trigger_confirm_seconds
61046145 . unwrap_or ( DEFAULT_TRIGGER_CONFIRM_SECONDS ) ;
@@ -6136,6 +6177,7 @@ fn resolve_config(
61366177 infinite,
61376178 has_prompt,
61386179 poll,
6180+ initial_poll,
61396181 trigger_confirm_seconds,
61406182 log_preview_lines,
61416183 trigger_edge,
@@ -6203,6 +6245,7 @@ fn print_validation(config: &ResolvedConfig) {
62036245 }
62046246 }
62056247 println ! ( "- poll: {}s" , config. poll) ;
6248+ println ! ( "- initial_poll: {}s" , config. initial_poll) ;
62066249 println ! (
62076250 "- trigger_confirm_seconds: {}s" ,
62086251 config. trigger_confirm_seconds
@@ -7363,6 +7406,7 @@ runs:
73637406 single_line : false ,
73647407 tui : false ,
73657408 poll : None ,
7409+ initial_poll : None ,
73667410 trigger_confirm_seconds : None ,
73677411 log_preview_lines : None ,
73687412 no_trigger_edge : false ,
@@ -7399,6 +7443,7 @@ runs:
73997443 single_line : false ,
74007444 tui : false ,
74017445 poll : Some ( 5 ) ,
7446+ initial_poll : None ,
74027447 trigger_confirm_seconds : None ,
74037448 log_preview_lines : None ,
74047449 no_trigger_edge : false ,
@@ -7442,6 +7487,7 @@ runs:
74427487 single_line : false ,
74437488 tui : false ,
74447489 poll : None ,
7490+ initial_poll : None ,
74457491 trigger_confirm_seconds : None ,
74467492 log_preview_lines : None ,
74477493 no_trigger_edge : false ,
@@ -7480,6 +7526,7 @@ runs:
74807526 single_line : false ,
74817527 tui : false ,
74827528 poll : None ,
7529+ initial_poll : None ,
74837530 trigger_confirm_seconds : None ,
74847531 log_preview_lines : None ,
74857532 no_trigger_edge : false ,
@@ -7536,6 +7583,7 @@ runs:
75367583 single_line : false ,
75377584 tui : false ,
75387585 poll : None ,
7586+ initial_poll : None ,
75397587 trigger_confirm_seconds : None ,
75407588 log_preview_lines : None ,
75417589 no_trigger_edge : false ,
@@ -7577,6 +7625,7 @@ runs:
75777625 single_line : false ,
75787626 tui : false ,
75797627 poll : None ,
7628+ initial_poll : None ,
75807629 trigger_confirm_seconds : None ,
75817630 log_preview_lines : None ,
75827631 no_trigger_edge : false ,
@@ -7618,6 +7667,7 @@ runs:
76187667 single_line : false ,
76197668 tui : false ,
76207669 poll : None ,
7670+ initial_poll : None ,
76217671 trigger_confirm_seconds : None ,
76227672 log_preview_lines : None ,
76237673 no_trigger_edge : false ,
@@ -7659,6 +7709,7 @@ runs:
76597709 single_line : false ,
76607710 tui : false ,
76617711 poll : None ,
7712+ initial_poll : None ,
76627713 trigger_confirm_seconds : None ,
76637714 log_preview_lines : None ,
76647715 no_trigger_edge : false ,
@@ -7689,6 +7740,7 @@ runs:
76897740 iterations : Some ( 1 ) ,
76907741 infinite : None ,
76917742 poll : Some ( 1 ) ,
7743+ initial_poll : None ,
76927744 trigger_confirm_seconds : Some ( 0 ) ,
76937745 log_preview_lines : Some ( 1 ) ,
76947746 trigger_edge : Some ( true ) ,
@@ -7741,6 +7793,7 @@ runs:
77417793 iterations : Some ( 3 ) ,
77427794 infinite : None ,
77437795 poll : Some ( 7 ) ,
7796+ initial_poll : None ,
77447797 trigger_confirm_seconds : None ,
77457798 log_preview_lines : None ,
77467799 trigger_edge : None ,
@@ -8009,6 +8062,7 @@ runs:
80098062 single_line : false ,
80108063 tui : false ,
80118064 poll : 5 ,
8065+ initial_poll : 5 ,
80128066 log_preview_lines : 3 ,
80138067 trigger_edge : true ,
80148068 recheck_before_send : true ,
@@ -8070,6 +8124,7 @@ runs:
80708124 single_line : false ,
80718125 tui : false ,
80728126 poll : 5 ,
8127+ initial_poll : 5 ,
80738128 log_preview_lines : 3 ,
80748129 trigger_edge : true ,
80758130 recheck_before_send : true ,
@@ -8131,6 +8186,7 @@ runs:
81318186 single_line : false ,
81328187 tui : true ,
81338188 poll : 10 ,
8189+ initial_poll : 5 ,
81348190 log_preview_lines : 3 ,
81358191 trigger_edge : true ,
81368192 recheck_before_send : true ,
@@ -8191,6 +8247,7 @@ runs:
81918247 single_line : true ,
81928248 tui : false ,
81938249 poll : 10 ,
8250+ initial_poll : 5 ,
81948251 log_preview_lines : 3 ,
81958252 trigger_edge : true ,
81968253 recheck_before_send : true ,
@@ -8640,6 +8697,7 @@ fn default_template() -> String {
86408697 let template = r#"target: "ai:5.0"
86418698iterations: 10
86428699poll: 5
8700+ initial_poll: 5
86438701trigger_confirm_seconds: 5
86448702log_preview_lines: 3
86458703trigger_edge: true
0 commit comments