diff --git a/internal/beads/beads_redirect.go b/internal/beads/beads_redirect.go index 5246a008..51112a7c 100644 --- a/internal/beads/beads_redirect.go +++ b/internal/beads/beads_redirect.go @@ -23,6 +23,9 @@ import ( // this indicates an errant redirect file that should be removed. The function logs a // warning and returns the original beads directory. func ResolveBeadsDir(workDir string) string { + if filepath.Base(workDir) == ".beads" { + workDir = filepath.Dir(workDir) + } beadsDir := filepath.Join(workDir, ".beads") redirectPath := filepath.Join(beadsDir, "redirect") diff --git a/internal/beads/beads_test.go b/internal/beads/beads_test.go index 32bcf74a..30cdfb03 100644 --- a/internal/beads/beads_test.go +++ b/internal/beads/beads_test.go @@ -1804,7 +1804,6 @@ func TestSetupRedirect(t *testing.T) { // TestAgentBeadTombstoneBug demonstrates the bd bug where `bd delete --hard --force` // creates tombstones instead of truly deleting records. // -// // This test documents the bug behavior: // 1. Create agent bead // 2. Delete with --hard --force (supposed to permanently delete) @@ -2134,7 +2133,7 @@ func TestCloseAndClearAgentBead_FieldClearing(t *testing.T) { for i, tc := range tests { t.Run(tc.name, func(t *testing.T) { // Create unique agent ID for each test case - agentID := fmt.Sprintf("test-testrig-%s-%d", tc.fields.RoleType, i) + agentID := fmt.Sprintf("test-testrig-%s-case-%c", tc.fields.RoleType, 'a'+i) // Step 1: Create agent bead with specified fields _, err := bd.CreateAgentBead(agentID, "Test agent", tc.fields) @@ -2371,7 +2370,7 @@ func TestCloseAndClearAgentBead_ReasonVariations(t *testing.T) { for i, tc := range tests { t.Run(tc.name, func(t *testing.T) { - agentID := fmt.Sprintf("test-testrig-polecat-reason%d", i) + agentID := fmt.Sprintf("test-testrig-polecat-reason-%c", 'a'+i) // Create agent bead _, err := bd.CreateAgentBead(agentID, "Test agent", &AgentFields{ diff --git a/internal/config/loader_test.go b/internal/config/loader_test.go index a9628bc6..06f86759 100644 --- a/internal/config/loader_test.go +++ b/internal/config/loader_test.go @@ -1212,11 +1212,18 @@ func TestBuildStartupCommand_UsesRigAgentWhenRigPathProvided(t *testing.T) { } func TestBuildStartupCommand_UsesRoleAgentsFromTownSettings(t *testing.T) { - skipIfAgentBinaryMissing(t, "gemini", "codex") - t.Parallel() townRoot := t.TempDir() rigPath := filepath.Join(townRoot, "testrig") + binDir := t.TempDir() + for _, name := range []string{"gemini", "codex"} { + path := filepath.Join(binDir, name) + if err := os.WriteFile(path, []byte("#!/bin/sh\nexit 0\n"), 0755); err != nil { + t.Fatalf("write %s stub: %v", name, err) + } + } + t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH")) + // Configure town settings with role_agents townSettings := NewTownSettings() townSettings.DefaultAgent = "claude" diff --git a/internal/config/test_main_test.go b/internal/config/test_main_test.go new file mode 100644 index 00000000..07161b9a --- /dev/null +++ b/internal/config/test_main_test.go @@ -0,0 +1,42 @@ +package config + +import ( + "fmt" + "os" + "path/filepath" + "testing" +) + +func TestMain(m *testing.M) { + stubDir, err := os.MkdirTemp("", "gt-agent-bin-*") + if err != nil { + fmt.Fprintf(os.Stderr, "create stub dir: %v\n", err) + os.Exit(1) + } + + stub := []byte("#!/bin/sh\nexit 0\n") + binaries := []string{ + "claude", + "gemini", + "codex", + "cursor-agent", + "auggie", + "amp", + } + for _, name := range binaries { + path := filepath.Join(stubDir, name) + if err := os.WriteFile(path, stub, 0755); err != nil { + fmt.Fprintf(os.Stderr, "write stub %s: %v\n", name, err) + os.Exit(1) + } + } + + originalPath := os.Getenv("PATH") + _ = os.Setenv("PATH", stubDir+string(os.PathListSeparator)+originalPath) + + code := m.Run() + + _ = os.Setenv("PATH", originalPath) + _ = os.RemoveAll(stubDir) + os.Exit(code) +}