@@ -3351,7 +3351,7 @@ Let's work through this together to get CI passing.`
33513351
33523352 // Keep logs under 2000 chars to avoid context issues
33533353 const truncatedLogs = filteredLogs . length > 2000
3354- ? filteredLogs . substring ( 0 , 2000 ) + ' \n... (truncated)'
3354+ ? ` ${ filteredLogs . substring ( 0 , 2000 ) } \n... (truncated)`
33553355 : filteredLogs
33563356
33573357 const fixPrompt = `Fix CI failures for commit ${ currentSha . substring ( 0 , 7 ) } in ${ owner } /${ repo } .
@@ -3485,28 +3485,86 @@ Fix all issues by making necessary file changes. Be direct, don't ask questions.
34853485 . join ( ', ' )
34863486 log . substep ( `Changed files: ${ changedFiles } ` )
34873487
3488- await runCommand ( 'git' , [ 'add' , '.' ] , { cwd : rootPath } )
3488+ // Use Claude to create proper commits (logical groupings, no AI attribution)
3489+ const commitPrompt = `Review the changes and create commits with logical groupings.
34893490
3490- // Commit with descriptive message (no AI attribution per CLAUDE.md)
3491- const ciFixMessage = `Fix CI failures from run ${ lastRunId } `
3492- const ciCommitArgs = [ 'commit' , '-m' , ciFixMessage ]
3493- if ( useNoVerify ) {
3494- ciCommitArgs . push ( '--no-verify' )
3491+ Changed files: ${ changedFiles }
3492+
3493+ Requirements:
3494+ - Create one or more commits as needed for logical grouping
3495+ - No AI attribution in commit messages
3496+ - Follow conventional commit style from the repo
3497+ - Be concise and descriptive
3498+
3499+ Commit the changes now.`
3500+
3501+ const commitTmpFile = path . join ( rootPath , `.claude-commit-${ Date . now ( ) } .txt` )
3502+ await fs . writeFile ( commitTmpFile , commitPrompt , 'utf8' )
3503+
3504+ const commitArgs = prepareClaudeArgs ( [ ] , opts )
3505+ const commitArgsStr = commitArgs . join ( ' ' )
3506+ const commitCommand = commitArgsStr
3507+ ? `${ claudeCmd } ${ commitArgsStr } `
3508+ : claudeCmd
3509+
3510+ let commitScriptCmd
3511+ if ( WIN32 ) {
3512+ const winptyCheck = await runCommandWithOutput ( 'where' , [ 'winpty' ] )
3513+ if ( winptyCheck . exitCode === 0 ) {
3514+ commitScriptCmd = `winpty ${ commitCommand } < "${ commitTmpFile } "`
3515+ } else {
3516+ commitScriptCmd = `${ commitCommand } < "${ commitTmpFile } "`
3517+ }
3518+ } else {
3519+ commitScriptCmd = `script -q /dev/null sh -c '${ commitCommand } < "${ commitTmpFile } "'`
34953520 }
3496- await runCommand ( 'git' , ciCommitArgs , { cwd : rootPath } )
3497- await runCommand ( 'git' , [ 'push' ] , { cwd : rootPath } )
3498- log . done ( `Pushed fix commit: ${ ciFixMessage } ` )
3499-
3500- // Update SHA and push time for next check
3501- const newShaResult = await runCommandWithOutput (
3502- 'git' ,
3503- [ 'rev-parse' , 'HEAD' ] ,
3504- {
3521+
3522+ const commitExitCode = await new Promise ( ( resolve , _reject ) => {
3523+ const child = spawn ( commitScriptCmd , [ ] , {
3524+ stdio : 'inherit' ,
35053525 cwd : rootPath ,
3506- } ,
3507- )
3508- currentSha = newShaResult . stdout . trim ( )
3509- pushTime = Date . now ( )
3526+ shell : true ,
3527+ } )
3528+
3529+ const sigintHandler = ( ) => {
3530+ child . kill ( 'SIGINT' )
3531+ resolve ( 130 )
3532+ }
3533+ process . on ( 'SIGINT' , sigintHandler )
3534+
3535+ child . on ( 'exit' , code => {
3536+ process . off ( 'SIGINT' , sigintHandler )
3537+ resolve ( code || 0 )
3538+ } )
3539+
3540+ child . on ( 'error' , ( ) => {
3541+ process . off ( 'SIGINT' , sigintHandler )
3542+ resolve ( 1 )
3543+ } )
3544+ } )
3545+
3546+ try {
3547+ await fs . unlink ( commitTmpFile )
3548+ } catch { }
3549+
3550+ if ( commitExitCode === 0 ) {
3551+ // Push the commits
3552+ await runCommand ( 'git' , [ 'push' ] , { cwd : rootPath } )
3553+ log . done ( 'Pushed fix commits' )
3554+
3555+ // Update SHA and push time for next check
3556+ const newShaResult = await runCommandWithOutput (
3557+ 'git' ,
3558+ [ 'rev-parse' , 'HEAD' ] ,
3559+ {
3560+ cwd : rootPath ,
3561+ } ,
3562+ )
3563+ currentSha = newShaResult . stdout . trim ( )
3564+ pushTime = Date . now ( )
3565+ } else {
3566+ log . warn ( `Claude commit failed with exit code ${ commitExitCode } ` )
3567+ }
35103568 }
35113569
35123570 retryCount ++
@@ -3733,18 +3791,74 @@ Fix the issue by making necessary file changes. Be direct, don't ask questions.`
37333791 . join ( ', ' )
37343792 log . substep ( `Changed files: ${ changedFiles } ` )
37353793
3736- await runCommand ( 'git' , [ 'add' , '.' ] , { cwd : rootPath } )
3794+ // Use Claude to create proper commits (logical groupings, no AI attribution)
3795+ const commitPrompt = `Review the changes and create commits with logical groupings.
3796+
3797+ Changed files: ${ changedFiles }
3798+
3799+ Requirements:
3800+ - Create one or more commits as needed for logical grouping
3801+ - No AI attribution in commit messages
3802+ - Follow conventional commit style from the repo
3803+ - Be concise and descriptive
37373804
3738- // Commit with descriptive message (no AI attribution per CLAUDE.md)
3739- const ciFixMessage = `Fix CI failure in ${ job . name } (run ${ lastRunId } )`
3740- const ciCommitArgs = [ 'commit' , '-m' , ciFixMessage ]
3741- if ( useNoVerify ) {
3742- ciCommitArgs . push ( '--no-verify' )
3805+ Commit the changes now.`
3806+
3807+ const commitTmpFile = path . join ( rootPath , `.claude-commit-${ Date . now ( ) } .txt` )
3808+ await fs . writeFile ( commitTmpFile , commitPrompt , 'utf8' )
3809+
3810+ const commitArgs = prepareClaudeArgs ( [ ] , opts )
3811+ const commitArgsStr = commitArgs . join ( ' ' )
3812+ const commitCommand = commitArgsStr
3813+ ? `${ claudeCmd } ${ commitArgsStr } `
3814+ : claudeCmd
3815+
3816+ let commitScriptCmd
3817+ if ( WIN32 ) {
3818+ const winptyCheck = await runCommandWithOutput ( 'where' , [ 'winpty' ] )
3819+ if ( winptyCheck . exitCode === 0 ) {
3820+ commitScriptCmd = `winpty ${ commitCommand } < "${ commitTmpFile } "`
3821+ } else {
3822+ commitScriptCmd = `${ commitCommand } < "${ commitTmpFile } "`
3823+ }
3824+ } else {
3825+ commitScriptCmd = `script -q /dev/null sh -c '${ commitCommand } < "${ commitTmpFile } "'`
37433826 }
3744- await runCommand ( 'git' , ciCommitArgs , { cwd : rootPath } )
3745- log . done ( `Committed fix for ${ job . name } ` )
37463827
3747- hasPendingCommits = true
3828+ const commitExitCode = await new Promise ( ( resolve , _reject ) => {
3829+ const child = spawn ( commitScriptCmd , [ ] , {
3830+ stdio : 'inherit' ,
3831+ cwd : rootPath ,
3832+ shell : true ,
3833+ } )
3834+
3835+ const sigintHandler = ( ) => {
3836+ child . kill ( 'SIGINT' )
3837+ resolve ( 130 )
3838+ }
3839+ process . on ( 'SIGINT' , sigintHandler )
3840+
3841+ child . on ( 'exit' , code => {
3842+ process . off ( 'SIGINT' , sigintHandler )
3843+ resolve ( code || 0 )
3844+ } )
3845+
3846+ child . on ( 'error' , ( ) => {
3847+ process . off ( 'SIGINT' , sigintHandler )
3848+ resolve ( 1 )
3849+ } )
3850+ } )
3851+
3852+ try {
3853+ await fs . unlink ( commitTmpFile )
3854+ } catch { }
3855+
3856+ if ( commitExitCode === 0 ) {
3857+ log . done ( `Committed fix for ${ job . name } ` )
3858+ hasPendingCommits = true
3859+ } else {
3860+ log . warn ( `Claude commit failed with exit code ${ commitExitCode } ` )
3861+ }
37483862 } else {
37493863 log . substep ( `No changes to commit for ${ job . name } ` )
37503864 }
0 commit comments