This commit is contained in:
Ian Gulliver
2026-10-14 21:01:38 -07:00
parent 9e741ede32
commit b2bd894677
20 changed files with 585 additions and 343 deletions
+104
View File
@@ -530,6 +530,110 @@ func TestCompactCarriesHandoff(t *testing.T) {
}
}
func TestMergeIn(t *testing.T) {
t.Parallel()
e := newEnv(t)
m := e.manager()
_, err := m.Create(e.ctx, e.task, e.user, `Create a file task.txt containing exactly the word task.`, testModel)
if err != nil {
t.Fatalf("create session: %v", err)
}
e.waitIdle()
err = os.WriteFile(filepath.Join(e.repo, "main.txt"), []byte("main\n"), 0o644)
if err != nil {
t.Fatalf("write main.txt: %v", err)
}
gitOut(t, e.repo, "add", "main.txt")
gitOut(t, e.repo, "commit", "--message", "main change")
mainHead := gitOut(t, e.repo, "rev-parse", "HEAD")
_, err = m.MergeIn(e.ctx, e.task, e.user, "main")
if err != nil {
t.Fatalf("merge in: %v", err)
}
e.waitIdle()
parents := strings.Fields(gitOut(t, e.task.WorktreePath, "log", "-1", "--format=%P"))
if len(parents) != 2 || parents[1] != mainHead {
t.Fatalf("HEAD parents %v, want a merge of main %s", parents, mainHead)
}
for _, f := range []string{"task.txt", "main.txt"} {
_, err = os.Stat(filepath.Join(e.task.WorktreePath, f))
if err != nil {
t.Fatalf("%s missing after merge: %v", f, err)
}
}
if status := gitOut(t, e.task.WorktreePath, "status", "--porcelain", "--untracked-files=all"); status != "" {
t.Fatalf("worktree dirty after the merge turn:\n%s", status)
}
}
func TestMergeResolvesConflict(t *testing.T) {
t.Parallel()
e := newEnv(t)
m := e.manager()
_, err := m.Create(e.ctx, e.task, e.user, `Create a file notes.txt containing exactly the line "task".`, testModel)
if err != nil {
t.Fatalf("create session: %v", err)
}
e.waitIdle()
err = os.WriteFile(filepath.Join(e.task.WorktreePath, "uncommitted"), []byte("three\n"), 0o644)
if err != nil {
t.Fatalf("write uncommitted: %v", err)
}
err = os.WriteFile(filepath.Join(e.repo, "notes.txt"), []byte("main\n"), 0o644)
if err != nil {
t.Fatalf("write notes.txt: %v", err)
}
gitOut(t, e.repo, "add", "notes.txt")
gitOut(t, e.repo, "commit", "--message", "main change")
moved := gitOut(t, e.repo, "rev-parse", "HEAD")
_, err = m.Merge(e.ctx, e.task, e.project, e.user)
if err != nil {
t.Fatalf("merge: %v", err)
}
e.waitFor("task merged", func(ev api.Event) bool { return ev.Kind == "task.merged" })
task, err := e.store.GetTask(e.ctx, e.task.Id)
if err != nil {
t.Fatalf("get task: %v", err)
}
if task.Status != api.TaskStatusMerged || task.MergeCommit == nil {
t.Fatalf("task after merge %+v", task)
}
if head := gitOut(t, e.repo, "rev-parse", "main"); head != *task.MergeCommit {
t.Fatalf("main at %s, want merge commit %s", head, *task.MergeCommit)
}
if parent := gitOut(t, e.repo, "rev-parse", "main^"); parent != moved {
t.Fatalf("merge commit parent %s, want %s", parent, moved)
}
if log := gitOut(t, e.repo, "log", "-1", "--format=%s|%an|%cn"); log != task.Title+"|"+gitName+"|"+gitName {
t.Fatalf("unexpected merge commit %s", log)
}
notes, err := os.ReadFile(filepath.Join(e.repo, "notes.txt"))
if err != nil {
t.Fatalf("read notes.txt: %v", err)
}
if !strings.Contains(string(notes), "task") || !strings.Contains(string(notes), "main") || strings.Contains(string(notes), "<<<<<<<") {
t.Fatalf("notes.txt on main doesn't hold both sides:\n%s", notes)
}
_, err = os.Stat(filepath.Join(e.repo, "uncommitted"))
if err != nil {
t.Fatalf("uncommitted file not on main: %v", err)
}
if status := gitOut(t, e.repo, "status", "--porcelain"); status != "" {
t.Fatalf("main checkout dirty after merge: %s", status)
}
if branches := gitOut(t, e.repo, "branch", "--list", e.task.Branch); branches != "" {
t.Fatalf("branch still exists: %s", branches)
}
}
func TestCreateTaskTool(t *testing.T) {
t.Parallel()
e := newEnv(t)