From 44521cc50e304b61c44b9a269a8239fd0fef49cd Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Thu, 26 Mar 2026 06:36:32 +0000 Subject: fix: story branch push to bare repo; drain at 3 consecutive failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit createStoryBranch was pushing to 'origin' which doesn't exist — branches never landed in the bare repo so agents couldn't clone them. Now uses the project's RemoteURL (bare repo path) directly for fetch and push. Raise drain threshold from 2 to 3 consecutive failures to reduce false positives from transient errors. Co-Authored-By: Claude Sonnet 4.6 --- internal/executor/executor_test.go | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'internal/executor/executor_test.go') diff --git a/internal/executor/executor_test.go b/internal/executor/executor_test.go index 67b2764..ad496e7 100644 --- a/internal/executor/executor_test.go +++ b/internal/executor/executor_test.go @@ -1543,20 +1543,32 @@ func TestPool_MaxPerAgent_AllowsDifferentAgents(t *testing.T) { } } -func TestPool_ConsecutiveFailures_DrainAtTwo(t *testing.T) { +func TestPool_ConsecutiveFailures_DrainAtThree(t *testing.T) { store := testStore(t) runner := &mockRunner{err: fmt.Errorf("boom")} runners := map[string]Runner{"claude": runner} logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError})) - pool := NewPool(2, runners, store, logger) + pool := NewPool(3, runners, store, logger) - // Submit two failing tasks + // Two failures should NOT drain. for _, id := range []string{"cf-1", "cf-2"} { tk := makeTask(id) store.CreateTask(tk) pool.Submit(context.Background(), tk) - <-pool.Results() // drain + <-pool.Results() } + pool.mu.Lock() + draineEarly := pool.drained["claude"] + pool.mu.Unlock() + if draineEarly { + t.Error("expected claude NOT drained after only 2 failures") + } + + // Third failure should drain. + tk3 := makeTask("cf-3") + store.CreateTask(tk3) + pool.Submit(context.Background(), tk3) + <-pool.Results() pool.mu.Lock() drained := pool.drained["claude"] @@ -1564,18 +1576,18 @@ func TestPool_ConsecutiveFailures_DrainAtTwo(t *testing.T) { pool.mu.Unlock() if !drained { - t.Error("expected claude to be drained after 2 consecutive failures") + t.Error("expected claude to be drained after 3 consecutive failures") } - if failures < 2 { - t.Errorf("expected consecutiveFailures >= 2, got %d", failures) + if failures < 3 { + t.Errorf("expected consecutiveFailures >= 3, got %d", failures) } - // The second task should have a drain question set - tk2, err := store.GetTask("cf-2") + // The third task should have a drain question set. + tk3fetched, err := store.GetTask("cf-3") if err != nil { t.Fatalf("GetTask: %v", err) } - if tk2.QuestionJSON == "" { + if tk3fetched.QuestionJSON == "" { t.Error("expected drain question to be set on task after drain") } } -- cgit v1.2.3