@@ -11,6 +11,7 @@ import (
1111 "strings"
1212 "testing"
1313
14+ "github.com/recallnet/mainline/internal/domain"
1415 "github.com/recallnet/mainline/internal/git"
1516 "github.com/recallnet/mainline/internal/policy"
1617 "github.com/recallnet/mainline/internal/state"
@@ -750,6 +751,64 @@ func TestRunOnceFailsWhenSubmittedSourceWorktreeTurnsDirtyAfterSubmit(t *testing
750751 }
751752}
752753
754+ func TestRunOnceSupersedesBlockedSubmissionAlreadyReachableAfterWorktreeDrop (t * testing.T ) {
755+ repoRoot , _ := createTestRepo (t )
756+ initRepoForWorker (t , repoRoot )
757+
758+ featurePath := filepath .Join (t .TempDir (), "feature-reachable-dropped" )
759+ runTestCommand (t , repoRoot , "git" , "worktree" , "add" , "-b" , "feature/reachable-dropped" , featurePath )
760+ writeFileAndCommit (t , featurePath , "reachable.txt" , "reachable\n " , "reachable feature" )
761+ sourceSHA := trimNewline (runTestCommand (t , featurePath , "git" , "rev-parse" , "HEAD" ))
762+ runTestCommand (t , repoRoot , "git" , "merge" , "--ff-only" , "feature/reachable-dropped" )
763+
764+ layout , err := git .DiscoverRepositoryLayout (repoRoot )
765+ if err != nil {
766+ t .Fatalf ("DiscoverRepositoryLayout: %v" , err )
767+ }
768+ store := state .NewStore (state .DefaultPath (layout .GitDir ))
769+ repoRecord , err := store .GetRepositoryByPath (context .Background (), layout .RepositoryRoot )
770+ if err != nil {
771+ t .Fatalf ("GetRepositoryByPath: %v" , err )
772+ }
773+ submission , err := store .CreateIntegrationSubmission (context .Background (), state.IntegrationSubmission {
774+ RepoID : repoRecord .ID ,
775+ BranchName : "feature/reachable-dropped" ,
776+ SourceRef : "feature/reachable-dropped" ,
777+ RefKind : submissionRefKindBranch ,
778+ SourceWorktree : featurePath ,
779+ SourceSHA : sourceSHA ,
780+ Status : domain .SubmissionStatusBlocked ,
781+ LastError : "rebase conflict" ,
782+ })
783+ if err != nil {
784+ t .Fatalf ("CreateIntegrationSubmission: %v" , err )
785+ }
786+
787+ if err := os .RemoveAll (featurePath ); err != nil {
788+ t .Fatalf ("RemoveAll(featurePath): %v" , err )
789+ }
790+
791+ var runOut bytes.Buffer
792+ var runErr bytes.Buffer
793+ if err := runRunOnce ([]string {"--repo" , repoRoot }, newStepPrinter (& runOut ), & runErr ); err != nil {
794+ t .Fatalf ("runRunOnce returned error: %v" , err )
795+ }
796+ if ! strings .Contains (runOut .String (), "Superseded 1 obsolete submission" ) {
797+ t .Fatalf ("expected supersede summary, got %q" , runOut .String ())
798+ }
799+
800+ updated , err := store .GetIntegrationSubmission (context .Background (), submission .ID )
801+ if err != nil {
802+ t .Fatalf ("GetIntegrationSubmission: %v" , err )
803+ }
804+ if updated .Status != domain .SubmissionStatusSuperseded {
805+ t .Fatalf ("expected superseded blocked submission, got %+v" , updated )
806+ }
807+ if ! strings .Contains (updated .LastError , "already reachable from protected branch" ) {
808+ t .Fatalf ("expected reachability supersede reason, got %+v" , updated )
809+ }
810+ }
811+
753812func TestRunOnceFailsWhenQueuedBranchHeadDriftsAfterSubmit (t * testing.T ) {
754813 repoRoot , _ := createTestRepo (t )
755814 initRepoForWorker (t , repoRoot )
0 commit comments