@@ -631,6 +631,35 @@ index 0000000..abc1234
631631 expect ( result . commit_url ) . toContain ( "test-owner/test-repo/commit/" ) ;
632632 } ) ;
633633
634+ it ( "should detect deleted branch before fetch" , async ( ) => {
635+ const patchPath = createPatchFile ( ) ;
636+
637+ mockExec . getExecOutput . mockResolvedValueOnce ( { exitCode : 2 , stdout : "" , stderr : "fatal: couldn't find remote ref feature-branch" } ) ;
638+
639+ const module = await loadModule ( ) ;
640+ const handler = await module . main ( { } ) ;
641+ const result = await handler ( { patch_path : patchPath } , { } ) ;
642+
643+ expect ( result . success ) . toBe ( false ) ;
644+ expect ( result . error ) . toContain ( "no longer exists on origin" ) ;
645+ expect ( mockExec . exec ) . not . toHaveBeenCalled ( ) ;
646+ } ) ;
647+
648+ it ( "should fail with diagnostic error when branch existence check fails for other reasons" , async ( ) => {
649+ const patchPath = createPatchFile ( ) ;
650+
651+ mockExec . getExecOutput . mockResolvedValueOnce ( { exitCode : 128 , stdout : "" , stderr : "fatal: Authentication failed" } ) ;
652+
653+ const module = await loadModule ( ) ;
654+ const handler = await module . main ( { } ) ;
655+ const result = await handler ( { patch_path : patchPath } , { } ) ;
656+
657+ expect ( result . success ) . toBe ( false ) ;
658+ expect ( result . error ) . toContain ( "Failed to verify branch" ) ;
659+ expect ( result . error ) . toContain ( "Authentication failed" ) ;
660+ expect ( mockExec . exec ) . not . toHaveBeenCalled ( ) ;
661+ } ) ;
662+
634663 it ( "should handle git fetch failure" , async ( ) => {
635664 const patchPath = createPatchFile ( ) ;
636665
@@ -740,6 +769,67 @@ index 0000000..abc1234
740769 expect ( result . success ) . toBe ( false ) ;
741770 } ) ;
742771
772+ it ( "should diagnose deleted branch when push fails" , async ( ) => {
773+ const patchPath = createPatchFile ( ) ;
774+
775+ // Set up successful operations until push
776+ mockExec . exec . mockResolvedValueOnce ( 0 ) ; // fetch
777+ mockExec . exec . mockResolvedValueOnce ( 0 ) ; // rev-parse
778+ mockExec . exec . mockResolvedValueOnce ( 0 ) ; // checkout
779+
780+ mockExec . getExecOutput . mockResolvedValueOnce ( { exitCode : 0 , stdout : "before-sha\n" , stderr : "" } ) ; // git rev-parse HEAD (before patch)
781+
782+ mockExec . exec . mockResolvedValueOnce ( 0 ) ; // git am
783+
784+ // pushSignedCommits + post-failure diagnosis responses
785+ const originalGetExecOutput = mockExec . getExecOutput ;
786+ let exitCodeLsRemoteCallCount = 0 ;
787+ mockExec . getExecOutput = vi . fn ( ) . mockImplementation ( async ( cmd , args ) => {
788+ const argList = Array . isArray ( args ) ? args : [ ] ;
789+ if ( argList [ 0 ] === "rev-parse" && argList [ 1 ] === "HEAD" ) {
790+ return { exitCode : 0 , stdout : "before-sha\n" , stderr : "" } ;
791+ }
792+ if ( argList [ 0 ] === "rev-list" ) {
793+ return { exitCode : 0 , stdout : "abc123\n" , stderr : "" } ;
794+ }
795+ if ( argList [ 0 ] === "diff-tree" ) {
796+ return { exitCode : 0 , stdout : "" , stderr : "" } ;
797+ }
798+ if ( argList [ 0 ] === "ls-remote" && argList [ 1 ] === "--exit-code" ) {
799+ exitCodeLsRemoteCallCount += 1 ;
800+ if ( exitCodeLsRemoteCallCount === 1 ) {
801+ // Initial preflight check before fetch
802+ return { exitCode : 0 , stdout : "remote-oid\trefs/heads/feature-branch\n" , stderr : "" } ;
803+ }
804+ // Post-push diagnosis call from push_to_pull_request_branch catch block
805+ return { exitCode : 2 , stdout : "" , stderr : "fatal: couldn't find remote ref feature-branch" } ;
806+ }
807+ if ( argList [ 0 ] === "ls-remote" ) {
808+ return { exitCode : 0 , stdout : "remote-oid\trefs/heads/feature-branch\n" , stderr : "" } ;
809+ }
810+ if ( argList [ 0 ] === "log" ) {
811+ return { exitCode : 0 , stdout : "Test commit\n" , stderr : "" } ;
812+ }
813+ if ( argList [ 0 ] === "diff" && argList [ 1 ] === "--name-status" ) {
814+ return { exitCode : 0 , stdout : "" , stderr : "" } ;
815+ }
816+ return originalGetExecOutput ( cmd , args ) ;
817+ } ) ;
818+
819+ // GraphQL call fails, triggering fallback to git push
820+ mockGithub . graphql . mockRejectedValueOnce ( new Error ( "GraphQL error: branch protection" ) ) ;
821+ // Fallback git push fails
822+ mockExec . exec . mockRejectedValueOnce ( new Error ( "remote: Internal Server Error" ) ) ;
823+
824+ const module = await loadModule ( ) ;
825+ const handler = await module . main ( { } ) ;
826+ const result = await handler ( { patch_path : patchPath } , { } ) ;
827+
828+ expect ( result . success ) . toBe ( false ) ;
829+ expect ( result . error_type ) . toBe ( "push_failed" ) ;
830+ expect ( result . error ) . toContain ( "appears to have been deleted" ) ;
831+ } ) ;
832+
743833 it ( "should detect force-pushed branch via ref mismatch" , async ( ) => {
744834 const patchPath = createPatchFile ( ) ;
745835
0 commit comments