fix: eliminate path/filepath from all test files
29 test files migrated: filepath.Join→core.JoinPath, filepath.Dir→core.PathDir, filepath.Base→core.PathBase, filepath.IsAbs→core.PathIsAbs. Test dogfooding complete for filepath. Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
aafa63818f
commit
23bb62a116
29 changed files with 447 additions and 471 deletions
|
|
@ -6,7 +6,6 @@ import (
|
|||
"encoding/json"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -30,14 +29,14 @@ func TestAutoPR_AutoCreatePR_Bad(t *testing.T) {
|
|||
}
|
||||
|
||||
// No status file → early return (no panic)
|
||||
wsNoStatus := filepath.Join(root, "ws-no-status")
|
||||
wsNoStatus := core.JoinPath(root, "ws-no-status")
|
||||
require.NoError(t, os.MkdirAll(wsNoStatus, 0o755))
|
||||
assert.NotPanics(t, func() {
|
||||
s.autoCreatePR(wsNoStatus)
|
||||
})
|
||||
|
||||
// Empty branch → early return
|
||||
wsNoBranch := filepath.Join(root, "ws-no-branch")
|
||||
wsNoBranch := core.JoinPath(root, "ws-no-branch")
|
||||
require.NoError(t, os.MkdirAll(wsNoBranch, 0o755))
|
||||
st := &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -47,13 +46,13 @@ func TestAutoPR_AutoCreatePR_Bad(t *testing.T) {
|
|||
}
|
||||
data, err := json.MarshalIndent(st, "", " ")
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, os.WriteFile(filepath.Join(wsNoBranch, "status.json"), data, 0o644))
|
||||
require.NoError(t, os.WriteFile(core.JoinPath(wsNoBranch, "status.json"), data, 0o644))
|
||||
assert.NotPanics(t, func() {
|
||||
s.autoCreatePR(wsNoBranch)
|
||||
})
|
||||
|
||||
// Empty repo → early return
|
||||
wsNoRepo := filepath.Join(root, "ws-no-repo")
|
||||
wsNoRepo := core.JoinPath(root, "ws-no-repo")
|
||||
require.NoError(t, os.MkdirAll(wsNoRepo, 0o755))
|
||||
st2 := &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -63,7 +62,7 @@ func TestAutoPR_AutoCreatePR_Bad(t *testing.T) {
|
|||
}
|
||||
data2, err := json.MarshalIndent(st2, "", " ")
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, os.WriteFile(filepath.Join(wsNoRepo, "status.json"), data2, 0o644))
|
||||
require.NoError(t, os.WriteFile(core.JoinPath(wsNoRepo, "status.json"), data2, 0o644))
|
||||
assert.NotPanics(t, func() {
|
||||
s.autoCreatePR(wsNoRepo)
|
||||
})
|
||||
|
|
@ -74,8 +73,8 @@ func TestAutoPR_AutoCreatePR_Ugly(t *testing.T) {
|
|||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
// Set up a real git repo with no commits ahead of origin/dev
|
||||
wsDir := filepath.Join(root, "ws-no-ahead")
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
wsDir := core.JoinPath(root, "ws-no-ahead")
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
require.NoError(t, os.MkdirAll(repoDir, 0o755))
|
||||
|
||||
// Init the repo
|
||||
|
|
@ -86,7 +85,7 @@ func TestAutoPR_AutoCreatePR_Ugly(t *testing.T) {
|
|||
cmd = exec.Command("git", "-C", repoDir, "config", "user.email", "test@test.com")
|
||||
require.NoError(t, cmd.Run())
|
||||
|
||||
require.NoError(t, os.WriteFile(filepath.Join(repoDir, "README.md"), []byte("# test"), 0o644))
|
||||
require.NoError(t, os.WriteFile(core.JoinPath(repoDir, "README.md"), []byte("# test"), 0o644))
|
||||
cmd = exec.Command("git", "-C", repoDir, "add", ".")
|
||||
require.NoError(t, cmd.Run())
|
||||
cmd = exec.Command("git", "-C", repoDir, "commit", "-m", "init")
|
||||
|
|
@ -102,7 +101,7 @@ func TestAutoPR_AutoCreatePR_Ugly(t *testing.T) {
|
|||
}
|
||||
data, err := json.MarshalIndent(st, "", " ")
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, os.WriteFile(filepath.Join(wsDir, "status.json"), data, 0o644))
|
||||
require.NoError(t, os.WriteFile(core.JoinPath(wsDir, "status.json"), data, 0o644))
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -460,10 +459,10 @@ func TestCommandsWorkspace_CmdWorkspaceList_Good_WithEntries(t *testing.T) {
|
|||
s, _ := testPrepWithCore(t, nil)
|
||||
|
||||
wsRoot := WorkspaceRoot()
|
||||
ws := filepath.Join(wsRoot, "ws-1")
|
||||
ws := core.JoinPath(wsRoot, "ws-1")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
data, _ := json.Marshal(WorkspaceStatus{Status: "running", Repo: "go-io", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
r := s.cmdWorkspaceList(core.NewOptions())
|
||||
assert.True(t, r.OK)
|
||||
|
|
@ -479,10 +478,10 @@ func TestCommandsWorkspace_CmdWorkspaceClean_Good_RemovesCompleted(t *testing.T)
|
|||
s, _ := testPrepWithCore(t, nil)
|
||||
|
||||
wsRoot := WorkspaceRoot()
|
||||
ws := filepath.Join(wsRoot, "ws-done")
|
||||
ws := core.JoinPath(wsRoot, "ws-done")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
data, _ := json.Marshal(WorkspaceStatus{Status: "completed", Repo: "go-io", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
r := s.cmdWorkspaceClean(core.NewOptions())
|
||||
assert.True(t, r.OK)
|
||||
|
|
@ -499,18 +498,18 @@ func TestCommandsWorkspace_CmdWorkspaceClean_Good_FilterFailed(t *testing.T) {
|
|||
{"ws-ok", "completed"},
|
||||
{"ws-bad", "failed"},
|
||||
} {
|
||||
d := filepath.Join(wsRoot, ws.name)
|
||||
d := core.JoinPath(wsRoot, ws.name)
|
||||
os.MkdirAll(d, 0o755)
|
||||
data, _ := json.Marshal(WorkspaceStatus{Status: ws.status, Repo: "test", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(d, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(d, "status.json"), data, 0o644)
|
||||
}
|
||||
|
||||
r := s.cmdWorkspaceClean(core.NewOptions(core.Option{Key: "_arg", Value: "failed"}))
|
||||
assert.True(t, r.OK)
|
||||
|
||||
_, err1 := os.Stat(filepath.Join(wsRoot, "ws-bad"))
|
||||
_, err1 := os.Stat(core.JoinPath(wsRoot, "ws-bad"))
|
||||
assert.True(t, os.IsNotExist(err1))
|
||||
_, err2 := os.Stat(filepath.Join(wsRoot, "ws-ok"))
|
||||
_, err2 := os.Stat(core.JoinPath(wsRoot, "ws-ok"))
|
||||
assert.NoError(t, err2)
|
||||
}
|
||||
|
||||
|
|
@ -518,10 +517,10 @@ func TestCommandsWorkspace_CmdWorkspaceClean_Good_FilterBlocked(t *testing.T) {
|
|||
s, _ := testPrepWithCore(t, nil)
|
||||
|
||||
wsRoot := WorkspaceRoot()
|
||||
d := filepath.Join(wsRoot, "ws-stuck")
|
||||
d := core.JoinPath(wsRoot, "ws-stuck")
|
||||
os.MkdirAll(d, 0o755)
|
||||
data, _ := json.Marshal(WorkspaceStatus{Status: "blocked", Repo: "test", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(d, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(d, "status.json"), data, 0o644)
|
||||
|
||||
r := s.cmdWorkspaceClean(core.NewOptions(core.Option{Key: "_arg", Value: "blocked"}))
|
||||
assert.True(t, r.OK)
|
||||
|
|
@ -567,10 +566,10 @@ func TestCommands_CmdStatus_Good_WithWorkspaces(t *testing.T) {
|
|||
s, _ := testPrepWithCore(t, nil)
|
||||
|
||||
wsRoot := WorkspaceRoot()
|
||||
ws := filepath.Join(wsRoot, "ws-1")
|
||||
ws := core.JoinPath(wsRoot, "ws-1")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
data, _ := json.Marshal(WorkspaceStatus{Status: "completed", Repo: "test", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
r := s.cmdStatus(core.NewOptions())
|
||||
assert.True(t, r.OK)
|
||||
|
|
@ -590,7 +589,7 @@ func TestCommands_CmdPrompt_Good_DefaultTask(t *testing.T) {
|
|||
|
||||
func TestCommands_CmdExtract_Good(t *testing.T) {
|
||||
s, _ := testPrepWithCore(t, nil)
|
||||
target := filepath.Join(t.TempDir(), "extract-test")
|
||||
target := core.JoinPath(t.TempDir(), "extract-test")
|
||||
r := s.cmdExtract(core.NewOptions(
|
||||
core.Option{Key: "_arg", Value: "default"},
|
||||
core.Option{Key: "target", Value: target},
|
||||
|
|
@ -651,9 +650,9 @@ func TestCommands_RegisterCommands_Good_AllRegistered(t *testing.T) {
|
|||
|
||||
func TestCommands_CmdExtract_Bad_TargetDirAlreadyHasFiles(t *testing.T) {
|
||||
s, _ := testPrepWithCore(t, nil)
|
||||
target := filepath.Join(t.TempDir(), "extract-existing")
|
||||
target := core.JoinPath(t.TempDir(), "extract-existing")
|
||||
os.MkdirAll(target, 0o755)
|
||||
os.WriteFile(filepath.Join(target, "existing.txt"), []byte("data"), 0o644)
|
||||
os.WriteFile(core.JoinPath(target, "existing.txt"), []byte("data"), 0o644)
|
||||
|
||||
// Missing template arg uses "default", target already has files — still succeeds (overwrites)
|
||||
r := s.cmdExtract(core.NewOptions(
|
||||
|
|
@ -664,7 +663,7 @@ func TestCommands_CmdExtract_Bad_TargetDirAlreadyHasFiles(t *testing.T) {
|
|||
|
||||
func TestCommands_CmdExtract_Ugly_TargetIsFile(t *testing.T) {
|
||||
s, _ := testPrepWithCore(t, nil)
|
||||
target := filepath.Join(t.TempDir(), "not-a-dir")
|
||||
target := core.JoinPath(t.TempDir(), "not-a-dir")
|
||||
os.WriteFile(target, []byte("I am a file"), 0o644)
|
||||
|
||||
r := s.cmdExtract(core.NewOptions(
|
||||
|
|
@ -840,13 +839,13 @@ func TestCommands_CmdStatus_Ugly_NonDirEntries(t *testing.T) {
|
|||
os.MkdirAll(wsRoot, 0o755)
|
||||
|
||||
// Create a file (not a dir) inside workspace root
|
||||
os.WriteFile(filepath.Join(wsRoot, "not-a-workspace.txt"), []byte("junk"), 0o644)
|
||||
os.WriteFile(core.JoinPath(wsRoot, "not-a-workspace.txt"), []byte("junk"), 0o644)
|
||||
|
||||
// Also create a proper workspace
|
||||
ws := filepath.Join(wsRoot, "ws-valid")
|
||||
ws := core.JoinPath(wsRoot, "ws-valid")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
data, _ := json.Marshal(WorkspaceStatus{Status: "running", Repo: "test", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
r := s.cmdStatus(core.NewOptions())
|
||||
assert.True(t, r.OK)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ package agentic
|
|||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -89,22 +88,22 @@ func TestCommandsWorkspace_CmdWorkspaceList_Bad_NoWorkspaceRootDir(t *testing.T)
|
|||
func TestCommandsWorkspace_CmdWorkspaceList_Ugly_NonDirAndCorruptStatus(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
os.MkdirAll(wsRoot, 0o755)
|
||||
|
||||
// Non-directory entry in workspace root
|
||||
os.WriteFile(filepath.Join(wsRoot, "stray-file.txt"), []byte("not a workspace"), 0o644)
|
||||
os.WriteFile(core.JoinPath(wsRoot, "stray-file.txt"), []byte("not a workspace"), 0o644)
|
||||
|
||||
// Workspace with corrupt status.json
|
||||
wsCorrupt := filepath.Join(wsRoot, "ws-corrupt")
|
||||
wsCorrupt := core.JoinPath(wsRoot, "ws-corrupt")
|
||||
os.MkdirAll(wsCorrupt, 0o755)
|
||||
os.WriteFile(filepath.Join(wsCorrupt, "status.json"), []byte("{broken json!!!"), 0o644)
|
||||
os.WriteFile(core.JoinPath(wsCorrupt, "status.json"), []byte("{broken json!!!"), 0o644)
|
||||
|
||||
// Valid workspace
|
||||
wsGood := filepath.Join(wsRoot, "ws-good")
|
||||
wsGood := core.JoinPath(wsRoot, "ws-good")
|
||||
os.MkdirAll(wsGood, 0o755)
|
||||
data, _ := json.Marshal(WorkspaceStatus{Status: "running", Repo: "go-io", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(wsGood, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(wsGood, "status.json"), data, 0o644)
|
||||
|
||||
c := core.New()
|
||||
s := &PrepSubsystem{
|
||||
|
|
@ -122,7 +121,7 @@ func TestCommandsWorkspace_CmdWorkspaceList_Ugly_NonDirAndCorruptStatus(t *testi
|
|||
func TestCommandsWorkspace_CmdWorkspaceClean_Bad_UnknownFilterLeavesEverything(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create workspaces with various statuses
|
||||
for _, ws := range []struct{ name, status string }{
|
||||
|
|
@ -130,10 +129,10 @@ func TestCommandsWorkspace_CmdWorkspaceClean_Bad_UnknownFilterLeavesEverything(t
|
|||
{"ws-fail", "failed"},
|
||||
{"ws-run", "running"},
|
||||
} {
|
||||
d := filepath.Join(wsRoot, ws.name)
|
||||
d := core.JoinPath(wsRoot, ws.name)
|
||||
os.MkdirAll(d, 0o755)
|
||||
data, _ := json.Marshal(WorkspaceStatus{Status: ws.status, Repo: "test", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(d, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(d, "status.json"), data, 0o644)
|
||||
}
|
||||
|
||||
c := core.New()
|
||||
|
|
@ -149,7 +148,7 @@ func TestCommandsWorkspace_CmdWorkspaceClean_Bad_UnknownFilterLeavesEverything(t
|
|||
|
||||
// All workspaces should still exist
|
||||
for _, name := range []string{"ws-done", "ws-fail", "ws-run"} {
|
||||
_, err := os.Stat(filepath.Join(wsRoot, name))
|
||||
_, err := os.Stat(core.JoinPath(wsRoot, name))
|
||||
assert.NoError(t, err, "workspace %s should still exist", name)
|
||||
}
|
||||
}
|
||||
|
|
@ -157,7 +156,7 @@ func TestCommandsWorkspace_CmdWorkspaceClean_Bad_UnknownFilterLeavesEverything(t
|
|||
func TestCommandsWorkspace_CmdWorkspaceClean_Ugly_MixedStatuses(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create workspaces with statuses including merged and ready-for-review
|
||||
for _, ws := range []struct{ name, status string }{
|
||||
|
|
@ -167,10 +166,10 @@ func TestCommandsWorkspace_CmdWorkspaceClean_Ugly_MixedStatuses(t *testing.T) {
|
|||
{"ws-queued", "queued"},
|
||||
{"ws-blocked", "blocked"},
|
||||
} {
|
||||
d := filepath.Join(wsRoot, ws.name)
|
||||
d := core.JoinPath(wsRoot, ws.name)
|
||||
os.MkdirAll(d, 0o755)
|
||||
data, _ := json.Marshal(WorkspaceStatus{Status: ws.status, Repo: "test", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(d, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(d, "status.json"), data, 0o644)
|
||||
}
|
||||
|
||||
c := core.New()
|
||||
|
|
@ -186,12 +185,12 @@ func TestCommandsWorkspace_CmdWorkspaceClean_Ugly_MixedStatuses(t *testing.T) {
|
|||
|
||||
// merged, ready-for-review, blocked should be removed
|
||||
for _, name := range []string{"ws-merged", "ws-review", "ws-blocked"} {
|
||||
_, err := os.Stat(filepath.Join(wsRoot, name))
|
||||
_, err := os.Stat(core.JoinPath(wsRoot, name))
|
||||
assert.True(t, os.IsNotExist(err), "workspace %s should be removed", name)
|
||||
}
|
||||
// running and queued should remain
|
||||
for _, name := range []string{"ws-running", "ws-queued"} {
|
||||
_, err := os.Stat(filepath.Join(wsRoot, name))
|
||||
_, err := os.Stat(core.JoinPath(wsRoot, name))
|
||||
assert.NoError(t, err, "workspace %s should still exist", name)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -81,12 +80,12 @@ func TestDispatch_DetectFinalStatus_Ugly(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
|
||||
// BLOCKED.md exists but is whitespace only — NOT blocked
|
||||
os.WriteFile(filepath.Join(dir, "BLOCKED.md"), []byte(" \n "), 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "BLOCKED.md"), []byte(" \n "), 0o644)
|
||||
status, _ := detectFinalStatus(dir, 0, "completed")
|
||||
assert.Equal(t, "completed", status)
|
||||
|
||||
// BLOCKED.md takes precedence over non-zero exit
|
||||
os.WriteFile(filepath.Join(dir, "BLOCKED.md"), []byte("Need credentials"), 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "BLOCKED.md"), []byte("Need credentials"), 0o644)
|
||||
status2, question2 := detectFinalStatus(dir, 1, "failed")
|
||||
assert.Equal(t, "blocked", status2)
|
||||
assert.Equal(t, "Need credentials", question2)
|
||||
|
|
@ -136,7 +135,7 @@ func TestDispatch_StartIssueTracking_Good(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
st := &WorkspaceStatus{Status: "running", Repo: "go-io", Org: "core", Issue: 15}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(dir, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}), forge: forge.NewForge(srv.URL, "tok"), backoff: make(map[string]time.Time), failCount: make(map[string]int)}
|
||||
s.startIssueTracking(dir)
|
||||
|
|
@ -157,7 +156,7 @@ func TestDispatch_StartIssueTracking_Ugly(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
st := &WorkspaceStatus{Status: "running", Repo: "test"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(dir, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}), forge: forge.NewForge("http://invalid", "tok"), backoff: make(map[string]time.Time), failCount: make(map[string]int)}
|
||||
s.startIssueTracking(dir) // no issue → skips API call
|
||||
|
|
@ -174,7 +173,7 @@ func TestDispatch_StopIssueTracking_Good(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
st := &WorkspaceStatus{Status: "completed", Repo: "go-io", Issue: 10}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(dir, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}), forge: forge.NewForge(srv.URL, "tok"), backoff: make(map[string]time.Time), failCount: make(map[string]int)}
|
||||
s.stopIssueTracking(dir)
|
||||
|
|
@ -190,7 +189,7 @@ func TestDispatch_StopIssueTracking_Ugly(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
st := &WorkspaceStatus{Status: "completed", Repo: "test"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(dir, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}), forge: forge.NewForge("http://invalid", "tok"), backoff: make(map[string]time.Time), failCount: make(map[string]int)}
|
||||
s.stopIssueTracking(dir)
|
||||
|
|
@ -202,10 +201,10 @@ func TestDispatch_BroadcastStart_Good(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "workspace", "ws-test")
|
||||
wsDir := core.JoinPath(root, "workspace", "ws-test")
|
||||
os.MkdirAll(wsDir, 0o755)
|
||||
data, _ := json.Marshal(WorkspaceStatus{Repo: "go-io", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(wsDir, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(wsDir, "status.json"), data, 0o644)
|
||||
|
||||
c := core.New()
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(c, AgentOptions{}), backoff: make(map[string]time.Time), failCount: make(map[string]int)}
|
||||
|
|
@ -231,10 +230,10 @@ func TestDispatch_BroadcastComplete_Good(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "workspace", "ws-test")
|
||||
wsDir := core.JoinPath(root, "workspace", "ws-test")
|
||||
os.MkdirAll(wsDir, 0o755)
|
||||
data, _ := json.Marshal(WorkspaceStatus{Repo: "go-io", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(wsDir, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(wsDir, "status.json"), data, 0o644)
|
||||
|
||||
c := core.New()
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(c, AgentOptions{}), backoff: make(map[string]time.Time), failCount: make(map[string]int)}
|
||||
|
|
@ -259,18 +258,18 @@ func TestDispatch_OnAgentComplete_Good(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "ws-test")
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
metaDir := filepath.Join(wsDir, ".meta")
|
||||
wsDir := core.JoinPath(root, "ws-test")
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
metaDir := core.JoinPath(wsDir, ".meta")
|
||||
os.MkdirAll(repoDir, 0o755)
|
||||
os.MkdirAll(metaDir, 0o755)
|
||||
|
||||
st := &WorkspaceStatus{Status: "running", Repo: "go-io", Agent: "codex", StartedAt: time.Now()}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(wsDir, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(wsDir, "status.json"), data, 0o644)
|
||||
|
||||
s := newPrepWithProcess()
|
||||
outputFile := filepath.Join(metaDir, "agent-codex.log")
|
||||
outputFile := core.JoinPath(metaDir, "agent-codex.log")
|
||||
s.onAgentComplete("codex", wsDir, outputFile, 0, "completed", "test output")
|
||||
|
||||
updated, err := ReadStatus(wsDir)
|
||||
|
|
@ -286,18 +285,18 @@ func TestDispatch_OnAgentComplete_Bad(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "ws-fail")
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
metaDir := filepath.Join(wsDir, ".meta")
|
||||
wsDir := core.JoinPath(root, "ws-fail")
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
metaDir := core.JoinPath(wsDir, ".meta")
|
||||
os.MkdirAll(repoDir, 0o755)
|
||||
os.MkdirAll(metaDir, 0o755)
|
||||
|
||||
st := &WorkspaceStatus{Status: "running", Repo: "go-io", Agent: "codex", StartedAt: time.Now()}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(wsDir, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(wsDir, "status.json"), data, 0o644)
|
||||
|
||||
s := newPrepWithProcess()
|
||||
s.onAgentComplete("codex", wsDir, filepath.Join(metaDir, "agent-codex.log"), 1, "failed", "error")
|
||||
s.onAgentComplete("codex", wsDir, core.JoinPath(metaDir, "agent-codex.log"), 1, "failed", "error")
|
||||
|
||||
updated, _ := ReadStatus(wsDir)
|
||||
assert.Equal(t, "failed", updated.Status)
|
||||
|
|
@ -308,26 +307,26 @@ func TestDispatch_OnAgentComplete_Ugly(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "ws-blocked")
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
metaDir := filepath.Join(wsDir, ".meta")
|
||||
wsDir := core.JoinPath(root, "ws-blocked")
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
metaDir := core.JoinPath(wsDir, ".meta")
|
||||
os.MkdirAll(repoDir, 0o755)
|
||||
os.MkdirAll(metaDir, 0o755)
|
||||
|
||||
os.WriteFile(filepath.Join(repoDir, "BLOCKED.md"), []byte("Need credentials"), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "BLOCKED.md"), []byte("Need credentials"), 0o644)
|
||||
st := &WorkspaceStatus{Status: "running", Repo: "go-io", Agent: "codex", StartedAt: time.Now()}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(wsDir, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(wsDir, "status.json"), data, 0o644)
|
||||
|
||||
s := newPrepWithProcess()
|
||||
s.onAgentComplete("codex", wsDir, filepath.Join(metaDir, "agent-codex.log"), 0, "completed", "")
|
||||
s.onAgentComplete("codex", wsDir, core.JoinPath(metaDir, "agent-codex.log"), 0, "completed", "")
|
||||
|
||||
updated, _ := ReadStatus(wsDir)
|
||||
assert.Equal(t, "blocked", updated.Status)
|
||||
assert.Equal(t, "Need credentials", updated.Question)
|
||||
|
||||
// Empty output should NOT create log file
|
||||
_, err := os.Stat(filepath.Join(metaDir, "agent-codex.log"))
|
||||
_, err := os.Stat(core.JoinPath(metaDir, "agent-codex.log"))
|
||||
assert.True(t, os.IsNotExist(err))
|
||||
}
|
||||
|
||||
|
|
@ -335,10 +334,10 @@ func TestDispatch_OnAgentComplete_Ugly(t *testing.T) {
|
|||
|
||||
func TestDispatch_RunQA_Good(t *testing.T) {
|
||||
wsDir := t.TempDir()
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
os.MkdirAll(repoDir, 0o755)
|
||||
os.WriteFile(filepath.Join(repoDir, "go.mod"), []byte("module testmod\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(filepath.Join(repoDir, "main.go"), []byte("package main\nfunc main() {}\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "go.mod"), []byte("module testmod\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "main.go"), []byte("package main\nfunc main() {}\n"), 0o644)
|
||||
|
||||
s := newPrepWithProcess()
|
||||
assert.True(t, s.runQA(wsDir))
|
||||
|
|
@ -346,21 +345,21 @@ func TestDispatch_RunQA_Good(t *testing.T) {
|
|||
|
||||
func TestDispatch_RunQA_Bad(t *testing.T) {
|
||||
wsDir := t.TempDir()
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
os.MkdirAll(repoDir, 0o755)
|
||||
|
||||
// Broken Go code
|
||||
os.WriteFile(filepath.Join(repoDir, "go.mod"), []byte("module testmod\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(filepath.Join(repoDir, "main.go"), []byte("package main\nfunc main( {\n}\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "go.mod"), []byte("module testmod\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "main.go"), []byte("package main\nfunc main( {\n}\n"), 0o644)
|
||||
|
||||
s := newPrepWithProcess()
|
||||
assert.False(t, s.runQA(wsDir))
|
||||
|
||||
// PHP project — composer not available
|
||||
wsDir2 := t.TempDir()
|
||||
repoDir2 := filepath.Join(wsDir2, "repo")
|
||||
repoDir2 := core.JoinPath(wsDir2, "repo")
|
||||
os.MkdirAll(repoDir2, 0o755)
|
||||
os.WriteFile(filepath.Join(repoDir2, "composer.json"), []byte(`{"name":"test"}`), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir2, "composer.json"), []byte(`{"name":"test"}`), 0o644)
|
||||
|
||||
assert.False(t, s.runQA(wsDir2))
|
||||
}
|
||||
|
|
@ -368,24 +367,24 @@ func TestDispatch_RunQA_Bad(t *testing.T) {
|
|||
func TestDispatch_RunQA_Ugly(t *testing.T) {
|
||||
// Unknown language — passes QA (no checks)
|
||||
wsDir := t.TempDir()
|
||||
os.MkdirAll(filepath.Join(wsDir, "repo"), 0o755)
|
||||
os.MkdirAll(core.JoinPath(wsDir, "repo"), 0o755)
|
||||
|
||||
s := newPrepWithProcess()
|
||||
assert.True(t, s.runQA(wsDir))
|
||||
|
||||
// Go vet failure (compiles but bad printf)
|
||||
wsDir2 := t.TempDir()
|
||||
repoDir2 := filepath.Join(wsDir2, "repo")
|
||||
repoDir2 := core.JoinPath(wsDir2, "repo")
|
||||
os.MkdirAll(repoDir2, 0o755)
|
||||
os.WriteFile(filepath.Join(repoDir2, "go.mod"), []byte("module testmod\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(filepath.Join(repoDir2, "main.go"), []byte("package main\nimport \"fmt\"\nfunc main() { fmt.Printf(\"%d\", \"x\") }\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir2, "go.mod"), []byte("module testmod\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir2, "main.go"), []byte("package main\nimport \"fmt\"\nfunc main() { fmt.Printf(\"%d\", \"x\") }\n"), 0o644)
|
||||
assert.False(t, s.runQA(wsDir2))
|
||||
|
||||
// Node project — npm install likely fails
|
||||
wsDir3 := t.TempDir()
|
||||
repoDir3 := filepath.Join(wsDir3, "repo")
|
||||
repoDir3 := core.JoinPath(wsDir3, "repo")
|
||||
os.MkdirAll(repoDir3, 0o755)
|
||||
os.WriteFile(filepath.Join(repoDir3, "package.json"), []byte(`{"name":"test","scripts":{"test":"echo ok"}}`), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir3, "package.json"), []byte(`{"name":"test","scripts":{"test":"echo ok"}}`), 0o644)
|
||||
_ = s.runQA(wsDir3) // exercises the node path
|
||||
}
|
||||
|
||||
|
|
@ -400,17 +399,17 @@ func TestDispatch_Dispatch_Good(t *testing.T) {
|
|||
}))
|
||||
t.Cleanup(forgeSrv.Close)
|
||||
|
||||
srcRepo := filepath.Join(t.TempDir(), "core", "go-io")
|
||||
srcRepo := core.JoinPath(t.TempDir(), "core", "go-io")
|
||||
exec.Command("git", "init", "-b", "main", srcRepo).Run()
|
||||
exec.Command("git", "-C", srcRepo, "config", "user.name", "T").Run()
|
||||
exec.Command("git", "-C", srcRepo, "config", "user.email", "t@t.com").Run()
|
||||
os.WriteFile(filepath.Join(srcRepo, "go.mod"), []byte("module test\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(srcRepo, "go.mod"), []byte("module test\ngo 1.22\n"), 0o644)
|
||||
exec.Command("git", "-C", srcRepo, "add", ".").Run()
|
||||
exec.Command("git", "-C", srcRepo, "commit", "-m", "init").Run()
|
||||
|
||||
s := newPrepWithProcess()
|
||||
s.forge = forge.NewForge(forgeSrv.URL, "tok")
|
||||
s.codePath = filepath.Dir(filepath.Dir(srcRepo))
|
||||
s.codePath = core.PathDir(core.PathDir(srcRepo))
|
||||
|
||||
_, out, err := s.dispatch(context.Background(), nil, DispatchInput{
|
||||
Repo: "go-io", Task: "Fix stuff", Issue: 42, DryRun: true,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ package agentic
|
|||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -72,13 +71,13 @@ func TestHandlers_RegisterHandlers_Good_QAFailsUpdatesStatus(t *testing.T) {
|
|||
|
||||
root := WorkspaceRoot()
|
||||
wsName := "core/test/task-1"
|
||||
wsDir := filepath.Join(root, wsName)
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
wsDir := core.JoinPath(root, wsName)
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
os.MkdirAll(repoDir, 0o755)
|
||||
|
||||
// Create a Go project that will fail vet/build
|
||||
os.WriteFile(filepath.Join(repoDir, "go.mod"), []byte("module test\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(filepath.Join(repoDir, "main.go"), []byte("package main\nimport \"fmt\"\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "go.mod"), []byte("module test\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "main.go"), []byte("package main\nimport \"fmt\"\n"), 0o644)
|
||||
|
||||
st := &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -108,8 +107,8 @@ func TestHandlers_RegisterHandlers_Good_IngestOnCompletion(t *testing.T) {
|
|||
|
||||
root := WorkspaceRoot()
|
||||
wsName := "core/test/task-2"
|
||||
wsDir := filepath.Join(root, wsName)
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
wsDir := core.JoinPath(root, wsName)
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
os.MkdirAll(repoDir, 0o755)
|
||||
|
||||
st := &WorkspaceStatus{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import (
|
|||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -47,13 +46,13 @@ func TestIngest_IngestFindings_Good_WithFindings(t *testing.T) {
|
|||
"- `pkg/core/service.go:100` has a missing error check\n" +
|
||||
"- `pkg/core/config.go:25` needs documentation\n" +
|
||||
"This is padding to get past the 100 char minimum length requirement for the log file content parsing."
|
||||
require.True(t, fs.Write(filepath.Join(wsDir, "agent-codex.log"), logContent).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(wsDir, "agent-codex.log"), logContent).OK)
|
||||
|
||||
// Set up HOME for the agent-api.key read
|
||||
home := t.TempDir()
|
||||
t.Setenv("DIR_HOME", home)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(home, ".claude")).OK)
|
||||
require.True(t, fs.Write(filepath.Join(home, ".claude", "agent-api.key"), "test-api-key").OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(home, ".claude")).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(home, ".claude", "agent-api.key"), "test-api-key").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -114,7 +113,7 @@ func TestIngest_IngestFindings_Bad_TooFewFindings(t *testing.T) {
|
|||
|
||||
// Only 1 finding (need >= 2 to ingest)
|
||||
logContent := "Found: `main.go:1` has an issue. This padding makes the content long enough to pass the 100 char minimum check."
|
||||
require.True(t, fs.Write(filepath.Join(wsDir, "agent-codex.log"), logContent).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(wsDir, "agent-codex.log"), logContent).OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -136,7 +135,7 @@ func TestIngest_IngestFindings_Bad_QuotaExhausted(t *testing.T) {
|
|||
|
||||
// Log contains quota error — should skip
|
||||
logContent := "QUOTA_EXHAUSTED: Rate limit exceeded. `main.go:1` `other.go:2` padding to ensure we pass length check and get past the threshold."
|
||||
require.True(t, fs.Write(filepath.Join(wsDir, "agent-codex.log"), logContent).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(wsDir, "agent-codex.log"), logContent).OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -171,7 +170,7 @@ func TestIngest_IngestFindings_Bad_ShortLogFile(t *testing.T) {
|
|||
}))
|
||||
|
||||
// Log content is less than 100 bytes — should skip
|
||||
require.True(t, fs.Write(filepath.Join(wsDir, "agent-codex.log"), "short").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(wsDir, "agent-codex.log"), "short").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -258,8 +257,8 @@ func TestIngest_CreateIssueViaAPI_Bad_ServerError(t *testing.T) {
|
|||
|
||||
home := t.TempDir()
|
||||
t.Setenv("DIR_HOME", home)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(home, ".claude")).OK)
|
||||
require.True(t, fs.Write(filepath.Join(home, ".claude", "agent-api.key"), "test-key").OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(home, ".claude")).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(home, ".claude", "agent-api.key"), "test-key").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -326,8 +325,8 @@ func TestIngest_CreateIssueViaAPI_Ugly(t *testing.T) {
|
|||
|
||||
home := t.TempDir()
|
||||
t.Setenv("DIR_HOME", home)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(home, ".claude")).OK)
|
||||
require.True(t, fs.Write(filepath.Join(home, ".claude", "agent-api.key"), "test-key").OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(home, ".claude")).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(home, ".claude", "agent-api.key"), "test-key").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import (
|
|||
"bufio"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
|
@ -268,11 +267,11 @@ func TestAutoPr_BuildAutoPRBody_Ugly_ZeroCommits(t *testing.T) {
|
|||
func TestEvents_EmitEvent_Good_WritesJSONL(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
emitEvent("agent_completed", "codex", "core/go-io/task-5", "completed")
|
||||
|
||||
eventsFile := filepath.Join(root, "workspace", "events.jsonl")
|
||||
eventsFile := core.JoinPath(root, "workspace", "events.jsonl")
|
||||
r := fs.Read(eventsFile)
|
||||
require.True(t, r.OK, "events.jsonl should exist after emitEvent")
|
||||
|
||||
|
|
@ -286,11 +285,11 @@ func TestEvents_EmitEvent_Good_WritesJSONL(t *testing.T) {
|
|||
func TestEvents_EmitEvent_Good_ValidJSON(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
emitEvent("agent_started", "claude", "core/agent/task-1", "running")
|
||||
|
||||
eventsFile := filepath.Join(root, "workspace", "events.jsonl")
|
||||
eventsFile := core.JoinPath(root, "workspace", "events.jsonl")
|
||||
f, err := os.Open(eventsFile)
|
||||
require.NoError(t, err)
|
||||
defer f.Close()
|
||||
|
|
@ -310,12 +309,12 @@ func TestEvents_EmitEvent_Good_ValidJSON(t *testing.T) {
|
|||
func TestEvents_EmitEvent_Good_Appends(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
emitEvent("agent_started", "codex", "core/go-io/task-1", "running")
|
||||
emitEvent("agent_completed", "codex", "core/go-io/task-1", "completed")
|
||||
|
||||
eventsFile := filepath.Join(root, "workspace", "events.jsonl")
|
||||
eventsFile := core.JoinPath(root, "workspace", "events.jsonl")
|
||||
r := fs.Read(eventsFile)
|
||||
require.True(t, r.OK)
|
||||
|
||||
|
|
@ -331,11 +330,11 @@ func TestEvents_EmitEvent_Good_Appends(t *testing.T) {
|
|||
func TestEvents_EmitEvent_Good_StartHelper(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
emitStartEvent("gemini", "core/go-log/task-3")
|
||||
|
||||
eventsFile := filepath.Join(root, "workspace", "events.jsonl")
|
||||
eventsFile := core.JoinPath(root, "workspace", "events.jsonl")
|
||||
r := fs.Read(eventsFile)
|
||||
require.True(t, r.OK)
|
||||
assert.Contains(t, r.Value.(string), "agent_started")
|
||||
|
|
@ -345,11 +344,11 @@ func TestEvents_EmitEvent_Good_StartHelper(t *testing.T) {
|
|||
func TestEvents_EmitEvent_Good_CompletionHelper(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
emitCompletionEvent("claude", "core/agent/task-7", "failed")
|
||||
|
||||
eventsFile := filepath.Join(root, "workspace", "events.jsonl")
|
||||
eventsFile := core.JoinPath(root, "workspace", "events.jsonl")
|
||||
r := fs.Read(eventsFile)
|
||||
require.True(t, r.OK)
|
||||
assert.Contains(t, r.Value.(string), "agent_completed")
|
||||
|
|
@ -370,7 +369,7 @@ func TestEvents_EmitEvent_Bad_NoWorkspaceDir(t *testing.T) {
|
|||
func TestEvents_EmitEvent_Ugly_EmptyFields(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
// Should not panic with all empty fields
|
||||
assert.NotPanics(t, func() {
|
||||
|
|
@ -383,11 +382,11 @@ func TestEvents_EmitEvent_Ugly_EmptyFields(t *testing.T) {
|
|||
func TestEvents_EmitStartEvent_Good(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
emitStartEvent("codex", "core/go-io/task-10")
|
||||
|
||||
eventsFile := filepath.Join(root, "workspace", "events.jsonl")
|
||||
eventsFile := core.JoinPath(root, "workspace", "events.jsonl")
|
||||
r := fs.Read(eventsFile)
|
||||
require.True(t, r.OK)
|
||||
content := r.Value.(string)
|
||||
|
|
@ -400,13 +399,13 @@ func TestEvents_EmitStartEvent_Bad(t *testing.T) {
|
|||
// Empty agent name
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
emitStartEvent("", "core/go-io/task-10")
|
||||
})
|
||||
|
||||
eventsFile := filepath.Join(root, "workspace", "events.jsonl")
|
||||
eventsFile := core.JoinPath(root, "workspace", "events.jsonl")
|
||||
r := fs.Read(eventsFile)
|
||||
require.True(t, r.OK)
|
||||
content := r.Value.(string)
|
||||
|
|
@ -417,14 +416,14 @@ func TestEvents_EmitStartEvent_Ugly(t *testing.T) {
|
|||
// Very long workspace name
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
longName := strings.Repeat("very-long-workspace-name-", 50)
|
||||
assert.NotPanics(t, func() {
|
||||
emitStartEvent("claude", longName)
|
||||
})
|
||||
|
||||
eventsFile := filepath.Join(root, "workspace", "events.jsonl")
|
||||
eventsFile := core.JoinPath(root, "workspace", "events.jsonl")
|
||||
r := fs.Read(eventsFile)
|
||||
require.True(t, r.OK)
|
||||
assert.Contains(t, r.Value.(string), "agent_started")
|
||||
|
|
@ -433,11 +432,11 @@ func TestEvents_EmitStartEvent_Ugly(t *testing.T) {
|
|||
func TestEvents_EmitCompletionEvent_Good(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
emitCompletionEvent("gemini", "core/go-log/task-5", "completed")
|
||||
|
||||
eventsFile := filepath.Join(root, "workspace", "events.jsonl")
|
||||
eventsFile := core.JoinPath(root, "workspace", "events.jsonl")
|
||||
r := fs.Read(eventsFile)
|
||||
require.True(t, r.OK)
|
||||
content := r.Value.(string)
|
||||
|
|
@ -450,13 +449,13 @@ func TestEvents_EmitCompletionEvent_Bad(t *testing.T) {
|
|||
// Empty status
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
emitCompletionEvent("claude", "core/agent/task-1", "")
|
||||
})
|
||||
|
||||
eventsFile := filepath.Join(root, "workspace", "events.jsonl")
|
||||
eventsFile := core.JoinPath(root, "workspace", "events.jsonl")
|
||||
r := fs.Read(eventsFile)
|
||||
require.True(t, r.OK)
|
||||
assert.Contains(t, r.Value.(string), "agent_completed")
|
||||
|
|
@ -466,13 +465,13 @@ func TestEvents_EmitCompletionEvent_Ugly(t *testing.T) {
|
|||
// Unicode in agent name
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
emitCompletionEvent("\u00e9nchantr\u00efx-\u2603", "core/agent/task-1", "completed")
|
||||
})
|
||||
|
||||
eventsFile := filepath.Join(root, "workspace", "events.jsonl")
|
||||
eventsFile := core.JoinPath(root, "workspace", "events.jsonl")
|
||||
r := fs.Read(eventsFile)
|
||||
require.True(t, r.OK)
|
||||
assert.Contains(t, r.Value.(string), "\u00e9nchantr\u00efx")
|
||||
|
|
@ -597,7 +596,7 @@ func TestHandlers_ResolveWorkspace_Good_ExistingDir(t *testing.T) {
|
|||
|
||||
// Create the workspace directory structure
|
||||
wsName := "core/go-io/task-5"
|
||||
wsDir := filepath.Join(root, "workspace", wsName)
|
||||
wsDir := core.JoinPath(root, "workspace", wsName)
|
||||
require.True(t, fs.EnsureDir(wsDir).OK)
|
||||
|
||||
result := resolveWorkspace(wsName)
|
||||
|
|
@ -609,7 +608,7 @@ func TestHandlers_ResolveWorkspace_Good_NestedPath(t *testing.T) {
|
|||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsName := "core/agent/pr-42"
|
||||
wsDir := filepath.Join(root, "workspace", wsName)
|
||||
wsDir := core.JoinPath(root, "workspace", wsName)
|
||||
require.True(t, fs.EnsureDir(wsDir).OK)
|
||||
|
||||
result := resolveWorkspace(wsName)
|
||||
|
|
@ -651,7 +650,7 @@ func TestHandlers_FindWorkspaceByPR_Good_MatchesFlatLayout(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "workspace", "task-10")
|
||||
wsDir := core.JoinPath(root, "workspace", "task-10")
|
||||
require.True(t, fs.EnsureDir(wsDir).OK)
|
||||
require.NoError(t, writeStatus(wsDir, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -667,7 +666,7 @@ func TestHandlers_FindWorkspaceByPR_Good_MatchesDeepLayout(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "workspace", "core", "go-io", "task-15")
|
||||
wsDir := core.JoinPath(root, "workspace", "core", "go-io", "task-15")
|
||||
require.True(t, fs.EnsureDir(wsDir).OK)
|
||||
require.NoError(t, writeStatus(wsDir, &WorkspaceStatus{
|
||||
Status: "running",
|
||||
|
|
@ -683,7 +682,7 @@ func TestHandlers_FindWorkspaceByPR_Bad_NoMatch(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "workspace", "task-99")
|
||||
wsDir := core.JoinPath(root, "workspace", "task-99")
|
||||
require.True(t, fs.EnsureDir(wsDir).OK)
|
||||
require.NoError(t, writeStatus(wsDir, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -707,7 +706,7 @@ func TestHandlers_FindWorkspaceByPR_Bad_RepoDiffers(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "workspace", "task-5")
|
||||
wsDir := core.JoinPath(root, "workspace", "task-5")
|
||||
require.True(t, fs.EnsureDir(wsDir).OK)
|
||||
require.NoError(t, writeStatus(wsDir, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -724,9 +723,9 @@ func TestHandlers_FindWorkspaceByPR_Ugly_CorruptStatusFile(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "workspace", "corrupt-ws")
|
||||
wsDir := core.JoinPath(root, "workspace", "corrupt-ws")
|
||||
require.True(t, fs.EnsureDir(wsDir).OK)
|
||||
require.True(t, fs.Write(filepath.Join(wsDir, "status.json"), "not-valid-json{").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(wsDir, "status.json"), "not-valid-json{").OK)
|
||||
|
||||
// Should skip corrupt entries, not panic
|
||||
result := findWorkspaceByPR("go-io", "agent/any")
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ package agentic
|
|||
|
||||
import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
core "dappco.re/go/core"
|
||||
|
|
@ -34,7 +33,7 @@ func initBareRepo(t *testing.T) string {
|
|||
run("git", "config", "user.email", "test@test.com")
|
||||
|
||||
// Create a file and commit
|
||||
require.True(t, fs.Write(filepath.Join(dir, "README.md"), "# Test").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "README.md"), "# Test").OK)
|
||||
run("git", "add", "README.md")
|
||||
run("git", "commit", "-m", "initial commit")
|
||||
return dir
|
||||
|
|
@ -102,7 +101,7 @@ func TestMirror_CommitsAhead_Good_OneAhead(t *testing.T) {
|
|||
run("git", "branch", "base")
|
||||
|
||||
// Add a commit on main
|
||||
require.True(t, fs.Write(filepath.Join(dir, "new.txt"), "data").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "new.txt"), "data").OK)
|
||||
run("git", "add", "new.txt")
|
||||
run("git", "commit", "-m", "second commit")
|
||||
|
||||
|
|
@ -129,7 +128,7 @@ func TestMirror_CommitsAhead_Good_ThreeAhead(t *testing.T) {
|
|||
run("git", "branch", "base")
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
name := filepath.Join(dir, "file"+string(rune('a'+i))+".txt")
|
||||
name := core.JoinPath(dir, "file"+string(rune('a'+i))+".txt")
|
||||
require.True(t, fs.Write(name, "content").OK)
|
||||
run("git", "add", ".")
|
||||
run("git", "commit", "-m", "commit "+string(rune('0'+i)))
|
||||
|
|
@ -182,7 +181,7 @@ func TestMirror_FilesChanged_Good_OneFile(t *testing.T) {
|
|||
|
||||
run("git", "branch", "base")
|
||||
|
||||
require.True(t, fs.Write(filepath.Join(dir, "changed.txt"), "new").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "changed.txt"), "new").OK)
|
||||
run("git", "add", "changed.txt")
|
||||
run("git", "commit", "-m", "add file")
|
||||
|
||||
|
|
@ -209,7 +208,7 @@ func TestMirror_FilesChanged_Good_MultipleFiles(t *testing.T) {
|
|||
run("git", "branch", "base")
|
||||
|
||||
for _, name := range []string{"a.go", "b.go", "c.go"} {
|
||||
require.True(t, fs.Write(filepath.Join(dir, name), "package main").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, name), "package main").OK)
|
||||
}
|
||||
run("git", "add", ".")
|
||||
run("git", "commit", "-m", "add three files")
|
||||
|
|
@ -317,13 +316,13 @@ func TestMirror_ListLocalRepos_Good_FindsRepos(t *testing.T) {
|
|||
|
||||
// Create two git repos under base
|
||||
for _, name := range []string{"repo-a", "repo-b"} {
|
||||
repoDir := filepath.Join(base, name)
|
||||
repoDir := core.JoinPath(base, name)
|
||||
cmd := exec.Command("git", "init", repoDir)
|
||||
require.NoError(t, cmd.Run())
|
||||
}
|
||||
|
||||
// Create a non-repo directory
|
||||
require.True(t, fs.EnsureDir(filepath.Join(base, "not-a-repo")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(base, "not-a-repo")).OK)
|
||||
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{})}
|
||||
repos := s.listLocalRepos(base)
|
||||
|
|
@ -364,18 +363,18 @@ func TestMirror_ListLocalRepos_Ugly(t *testing.T) {
|
|||
|
||||
// Create two git repos
|
||||
for _, name := range []string{"real-repo-a", "real-repo-b"} {
|
||||
repoDir := filepath.Join(base, name)
|
||||
repoDir := core.JoinPath(base, name)
|
||||
cmd := exec.Command("git", "init", repoDir)
|
||||
require.NoError(t, cmd.Run())
|
||||
}
|
||||
|
||||
// Create non-git directories (no .git inside)
|
||||
for _, name := range []string{"plain-dir", "another-dir"} {
|
||||
require.True(t, fs.EnsureDir(filepath.Join(base, name)).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(base, name)).OK)
|
||||
}
|
||||
|
||||
// Create a regular file (not a directory)
|
||||
require.True(t, fs.Write(filepath.Join(base, "some-file.txt"), "hello").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(base, "some-file.txt"), "hello").OK)
|
||||
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{})}
|
||||
repos := s.listLocalRepos(base)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
package agentic
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
core "dappco.re/go/core"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -68,7 +68,7 @@ func TestReadWritePlan_Good_BasicRoundtrip(t *testing.T) {
|
|||
|
||||
path, err := writePlan(dir, plan)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, filepath.Join(dir, "basic-plan-abc.json"), path)
|
||||
assert.Equal(t, core.JoinPath(dir, "basic-plan-abc.json"), path)
|
||||
|
||||
read, err := readPlan(dir, "basic-plan-abc")
|
||||
require.NoError(t, err)
|
||||
|
|
@ -120,7 +120,7 @@ func TestPlan_ReadPlan_Bad_MissingFile(t *testing.T) {
|
|||
|
||||
func TestPlan_ReadPlan_Bad_CorruptJSON(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "bad.json"), `{broken`).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "bad.json"), `{broken`).OK)
|
||||
|
||||
_, err := readPlan(dir, "bad")
|
||||
assert.Error(t, err)
|
||||
|
|
@ -128,7 +128,7 @@ func TestPlan_ReadPlan_Bad_CorruptJSON(t *testing.T) {
|
|||
|
||||
func TestPlan_WritePlan_Good_CreatesNestedDir(t *testing.T) {
|
||||
base := t.TempDir()
|
||||
nested := filepath.Join(base, "deep", "nested", "plans")
|
||||
nested := core.JoinPath(base, "deep", "nested", "plans")
|
||||
|
||||
plan := &Plan{
|
||||
ID: "deep-plan-xyz",
|
||||
|
|
@ -139,7 +139,7 @@ func TestPlan_WritePlan_Good_CreatesNestedDir(t *testing.T) {
|
|||
|
||||
path, err := writePlan(nested, plan)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, filepath.Join(nested, "deep-plan-xyz.json"), path)
|
||||
assert.Equal(t, core.JoinPath(nested, "deep-plan-xyz.json"), path)
|
||||
assert.True(t, fs.IsFile(path))
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ func TestPlan_WritePlan_Good_OverwriteExistingLogic(t *testing.T) {
|
|||
|
||||
func TestPlan_ReadPlan_Ugly_EmptyFileLogic(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "empty.json"), "").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "empty.json"), "").OK)
|
||||
|
||||
_, err := readPlan(dir, "empty")
|
||||
assert.Error(t, err)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
package agentic
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
core "dappco.re/go/core"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -27,7 +27,7 @@ func TestPlan_WritePlan_Good(t *testing.T) {
|
|||
|
||||
path, err := writePlan(dir, plan)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, filepath.Join(dir, "test-plan-abc123.json"), path)
|
||||
assert.Equal(t, core.JoinPath(dir, "test-plan-abc123.json"), path)
|
||||
|
||||
// Verify file exists
|
||||
assert.True(t, fs.IsFile(path))
|
||||
|
|
@ -35,7 +35,7 @@ func TestPlan_WritePlan_Good(t *testing.T) {
|
|||
|
||||
func TestPlan_WritePlan_Good_CreatesDirectory(t *testing.T) {
|
||||
base := t.TempDir()
|
||||
dir := filepath.Join(base, "nested", "plans")
|
||||
dir := core.JoinPath(base, "nested", "plans")
|
||||
|
||||
plan := &Plan{
|
||||
ID: "nested-plan-abc123",
|
||||
|
|
@ -95,7 +95,7 @@ func TestPlan_ReadPlan_Bad_NotFound(t *testing.T) {
|
|||
|
||||
func TestPlan_ReadPlan_Bad_InvalidJSON(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "bad-json.json"), "{broken").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "bad-json.json"), "{broken").OK)
|
||||
|
||||
_, err := readPlan(dir, "bad-json")
|
||||
assert.Error(t, err)
|
||||
|
|
@ -204,7 +204,7 @@ func TestPlan_WritePlan_Good_OverwriteExisting(t *testing.T) {
|
|||
|
||||
func TestPlan_ReadPlan_Ugly_EmptyFile(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "empty.json"), "").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "empty.json"), "").OK)
|
||||
|
||||
_, err := readPlan(dir, "empty")
|
||||
assert.Error(t, err)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
|
@ -162,8 +161,8 @@ func TestPr_CreatePR_Good_DryRun(t *testing.T) {
|
|||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
// Create workspace with repo/.git
|
||||
wsDir := filepath.Join(root, "workspace", "test-ws")
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
wsDir := core.JoinPath(root, "workspace", "test-ws")
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
require.NoError(t, exec.Command("git", "init", "-b", "main", repoDir).Run())
|
||||
gitCmd := exec.Command("git", "config", "user.name", "Test")
|
||||
gitCmd.Dir = repoDir
|
||||
|
|
@ -201,8 +200,8 @@ func TestPr_CreatePR_Good_CustomTitle(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "workspace", "test-ws-2")
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
wsDir := core.JoinPath(root, "workspace", "test-ws-2")
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
require.NoError(t, exec.Command("git", "init", "-b", "main", repoDir).Run())
|
||||
gitCmd := exec.Command("git", "config", "user.name", "Test")
|
||||
gitCmd.Dir = repoDir
|
||||
|
|
@ -375,8 +374,8 @@ func TestPr_CreatePR_Ugly(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsDir := filepath.Join(root, "workspace", "test-ws-ugly")
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
wsDir := core.JoinPath(root, "workspace", "test-ws-ugly")
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
require.NoError(t, exec.Command("git", "init", "-b", "main", repoDir).Run())
|
||||
gitCmd := exec.Command("git", "config", "user.name", "Test")
|
||||
gitCmd.Dir = repoDir
|
||||
|
|
@ -386,7 +385,7 @@ func TestPr_CreatePR_Ugly(t *testing.T) {
|
|||
gitCmd.Run()
|
||||
|
||||
// Need an initial commit so HEAD exists for branch detection
|
||||
require.NoError(t, os.WriteFile(filepath.Join(repoDir, "README.md"), []byte("# Test"), 0o644))
|
||||
require.NoError(t, os.WriteFile(core.JoinPath(repoDir, "README.md"), []byte("# Test"), 0o644))
|
||||
addCmd := exec.Command("git", "add", ".")
|
||||
addCmd.Dir = repoDir
|
||||
require.NoError(t, addCmd.Run())
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -50,7 +49,7 @@ use (
|
|||
./core/agent
|
||||
./core/mcp
|
||||
)`
|
||||
os.WriteFile(filepath.Join(dir, "go.work"), []byte(goWork), 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "go.work"), []byte(goWork), 0o644)
|
||||
|
||||
// Create module dirs with go.mod
|
||||
for _, mod := range []struct {
|
||||
|
|
@ -61,9 +60,9 @@ use (
|
|||
{"core/agent", "module forge.lthn.ai/core/agent\n\nrequire forge.lthn.ai/core/go v0.7.0\n"},
|
||||
{"core/mcp", "module forge.lthn.ai/core/mcp\n\nrequire forge.lthn.ai/core/go v0.7.0\n"},
|
||||
} {
|
||||
modDir := filepath.Join(dir, mod.path)
|
||||
modDir := core.JoinPath(dir, mod.path)
|
||||
os.MkdirAll(modDir, 0o755)
|
||||
os.WriteFile(filepath.Join(modDir, "go.mod"), []byte(mod.content), 0o644)
|
||||
os.WriteFile(core.JoinPath(modDir, "go.mod"), []byte(mod.content), 0o644)
|
||||
}
|
||||
|
||||
s := &PrepSubsystem{
|
||||
|
|
@ -88,11 +87,11 @@ func TestPrep_FindConsumersList_Good_NoConsumers(t *testing.T) {
|
|||
use (
|
||||
./core/go
|
||||
)`
|
||||
os.WriteFile(filepath.Join(dir, "go.work"), []byte(goWork), 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "go.work"), []byte(goWork), 0o644)
|
||||
|
||||
modDir := filepath.Join(dir, "core", "go")
|
||||
modDir := core.JoinPath(dir, "core", "go")
|
||||
os.MkdirAll(modDir, 0o755)
|
||||
os.WriteFile(filepath.Join(modDir, "go.mod"), []byte("module forge.lthn.ai/core/go\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(modDir, "go.mod"), []byte("module forge.lthn.ai/core/go\n"), 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -222,7 +221,7 @@ func TestPrep_GetIssueBody_Bad_NotFound(t *testing.T) {
|
|||
func TestPrep_BuildPrompt_Good_BasicFields(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
// Create go.mod to detect language
|
||||
os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module test\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "go.mod"), []byte("module test\n\ngo 1.22\n"), 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -282,7 +281,7 @@ func TestPrep_BuildPrompt_Good_WithIssue(t *testing.T) {
|
|||
func TestPrep_BuildPrompt_Good(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
// Create go.mod to detect language as "go"
|
||||
os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module test\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "go.mod"), []byte("module test\n\ngo 1.22\n"), 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -330,7 +329,7 @@ func TestPrep_BuildPrompt_Bad(t *testing.T) {
|
|||
|
||||
func TestPrep_BuildPrompt_Ugly(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module test\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "go.mod"), []byte("module test\n\ngo 1.22\n"), 0o644)
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(map[string]any{
|
||||
|
|
@ -368,7 +367,7 @@ func TestPrep_BuildPrompt_Ugly(t *testing.T) {
|
|||
|
||||
func TestPrep_BuildPrompt_Ugly_WithGitLog(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module test\n\ngo 1.22\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "go.mod"), []byte("module test\n\ngo 1.22\n"), 0o644)
|
||||
|
||||
// Init a real git repo with commits so git log path is covered
|
||||
exec.Command("git", "init", "-b", "main", dir).Run()
|
||||
|
|
@ -396,10 +395,10 @@ func TestPrep_BuildPrompt_Ugly_WithGitLog(t *testing.T) {
|
|||
|
||||
func TestDispatch_RunQA_Good_PHPNoComposer(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
repoDir := filepath.Join(dir, "repo")
|
||||
repoDir := core.JoinPath(dir, "repo")
|
||||
os.MkdirAll(repoDir, 0o755)
|
||||
// composer.json present but no composer binary
|
||||
os.WriteFile(filepath.Join(repoDir, "composer.json"), []byte(`{"name":"test"}`), 0o644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "composer.json"), []byte(`{"name":"test"}`), 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -546,15 +545,15 @@ func TestPrep_FindConsumersList_Ugly(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
|
||||
goWork := "go 1.22\n\nuse (\n\t./core/go\n\t./core/missing\n)"
|
||||
os.WriteFile(filepath.Join(dir, "go.work"), []byte(goWork), 0o644)
|
||||
os.WriteFile(core.JoinPath(dir, "go.work"), []byte(goWork), 0o644)
|
||||
|
||||
// Create only the first module dir with go.mod
|
||||
modDir := filepath.Join(dir, "core", "go")
|
||||
modDir := core.JoinPath(dir, "core", "go")
|
||||
os.MkdirAll(modDir, 0o755)
|
||||
os.WriteFile(filepath.Join(modDir, "go.mod"), []byte("module forge.lthn.ai/core/go\n"), 0o644)
|
||||
os.WriteFile(core.JoinPath(modDir, "go.mod"), []byte("module forge.lthn.ai/core/go\n"), 0o644)
|
||||
|
||||
// core/missing has no go.mod
|
||||
os.MkdirAll(filepath.Join(dir, "core", "missing"), 0o755)
|
||||
os.MkdirAll(core.JoinPath(dir, "core", "missing"), 0o755)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
|
@ -36,43 +35,43 @@ func TestPrep_EnvOr_Good_UnsetUsesFallback(t *testing.T) {
|
|||
|
||||
func TestPrep_DetectLanguage_Good_Go(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "go.mod"), "module test").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "go.mod"), "module test").OK)
|
||||
assert.Equal(t, "go", detectLanguage(dir))
|
||||
}
|
||||
|
||||
func TestPrep_DetectLanguage_Good_PHP(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "composer.json"), "{}").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "composer.json"), "{}").OK)
|
||||
assert.Equal(t, "php", detectLanguage(dir))
|
||||
}
|
||||
|
||||
func TestPrep_DetectLanguage_Good_TypeScript(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "package.json"), "{}").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "package.json"), "{}").OK)
|
||||
assert.Equal(t, "ts", detectLanguage(dir))
|
||||
}
|
||||
|
||||
func TestPrep_DetectLanguage_Good_Rust(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "Cargo.toml"), "[package]").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "Cargo.toml"), "[package]").OK)
|
||||
assert.Equal(t, "rust", detectLanguage(dir))
|
||||
}
|
||||
|
||||
func TestPrep_DetectLanguage_Good_Python(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "requirements.txt"), "flask").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "requirements.txt"), "flask").OK)
|
||||
assert.Equal(t, "py", detectLanguage(dir))
|
||||
}
|
||||
|
||||
func TestPrep_DetectLanguage_Good_Cpp(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "CMakeLists.txt"), "cmake_minimum_required").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "CMakeLists.txt"), "cmake_minimum_required").OK)
|
||||
assert.Equal(t, "cpp", detectLanguage(dir))
|
||||
}
|
||||
|
||||
func TestPrep_DetectLanguage_Good_Docker(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "Dockerfile"), "FROM alpine").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "Dockerfile"), "FROM alpine").OK)
|
||||
assert.Equal(t, "docker", detectLanguage(dir))
|
||||
}
|
||||
|
||||
|
|
@ -98,7 +97,7 @@ func TestPrep_DetectBuildCmd_Good(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
t.Run(tt.file, func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, tt.file), tt.content).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, tt.file), tt.content).OK)
|
||||
assert.Equal(t, tt.expected, detectBuildCmd(dir))
|
||||
})
|
||||
}
|
||||
|
|
@ -126,7 +125,7 @@ func TestPrep_DetectTestCmd_Good(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
t.Run(tt.file, func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, tt.file), tt.content).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, tt.file), tt.content).OK)
|
||||
assert.Equal(t, tt.expected, detectTestCmd(dir))
|
||||
})
|
||||
}
|
||||
|
|
@ -500,8 +499,8 @@ func TestPrep_DetectLanguage_Bad(t *testing.T) {
|
|||
func TestPrep_DetectLanguage_Ugly(t *testing.T) {
|
||||
// Dir with multiple project files (go.mod + package.json) — go wins (first match)
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "go.mod"), "module test").OK)
|
||||
require.True(t, fs.Write(filepath.Join(dir, "package.json"), "{}").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "go.mod"), "module test").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "package.json"), "{}").OK)
|
||||
assert.Equal(t, "go", detectLanguage(dir), "go.mod checked first, so go wins")
|
||||
}
|
||||
|
||||
|
|
@ -580,7 +579,7 @@ func TestPrep_TestPrepWorkspace_Ugly(t *testing.T) {
|
|||
|
||||
func TestPrep_TestBuildPrompt_Good(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "go.mod"), "module test").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "go.mod"), "module test").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -689,7 +688,7 @@ func TestPrep_GetGitLog_Good(t *testing.T) {
|
|||
run("git", "init", "-b", "main")
|
||||
run("git", "config", "user.name", "Test")
|
||||
run("git", "config", "user.email", "test@test.com")
|
||||
require.True(t, fs.Write(filepath.Join(dir, "README.md"), "# Test").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "README.md"), "# Test").OK)
|
||||
run("git", "add", "README.md")
|
||||
run("git", "commit", "-m", "initial commit")
|
||||
|
||||
|
|
@ -748,7 +747,7 @@ func TestPrep_PrepWorkspace_Good(t *testing.T) {
|
|||
t.Cleanup(srv.Close)
|
||||
|
||||
// Create a source repo to clone from
|
||||
srcRepo := filepath.Join(root, "src", "core", "test-repo")
|
||||
srcRepo := core.JoinPath(root, "src", "core", "test-repo")
|
||||
run := func(dir string, args ...string) {
|
||||
t.Helper()
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
|
|
@ -766,14 +765,14 @@ func TestPrep_PrepWorkspace_Good(t *testing.T) {
|
|||
run(srcRepo, "git", "init", "-b", "main")
|
||||
run(srcRepo, "git", "config", "user.name", "Test")
|
||||
run(srcRepo, "git", "config", "user.email", "test@test.com")
|
||||
require.True(t, fs.Write(filepath.Join(srcRepo, "README.md"), "# Test").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(srcRepo, "README.md"), "# Test").OK)
|
||||
run(srcRepo, "git", "add", "README.md")
|
||||
run(srcRepo, "git", "commit", "-m", "initial commit")
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
forge: forge.NewForge(srv.URL, "test-token"),
|
||||
codePath: filepath.Join(root, "src"),
|
||||
codePath: core.JoinPath(root, "src"),
|
||||
backoff: make(map[string]time.Time),
|
||||
failCount: make(map[string]int),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ package agentic
|
|||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -91,7 +90,7 @@ rates:
|
|||
sustained_delay: 120
|
||||
burst_window: 2
|
||||
burst_delay: 15`
|
||||
os.WriteFile(filepath.Join(root, "agents.yaml"), []byte(cfg), 0o644)
|
||||
os.WriteFile(core.JoinPath(root, "agents.yaml"), []byte(cfg), 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -110,7 +109,7 @@ rates:
|
|||
func TestQueue_CountRunningByModel_Good_NoWorkspaces(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
os.MkdirAll(filepath.Join(root, "workspace"), 0o755)
|
||||
os.MkdirAll(core.JoinPath(root, "workspace"), 0o755)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -125,7 +124,7 @@ func TestQueue_CountRunningByModel_Good_NoWorkspaces(t *testing.T) {
|
|||
func TestQueue_DrainQueue_Good_NoCoreFallsBackToMutex(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
os.MkdirAll(filepath.Join(root, "workspace"), 0o755)
|
||||
os.MkdirAll(core.JoinPath(root, "workspace"), 0o755)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: nil,
|
||||
|
|
@ -139,7 +138,7 @@ func TestQueue_DrainQueue_Good_NoCoreFallsBackToMutex(t *testing.T) {
|
|||
func TestQueue_DrainOne_Good_NoWorkspaces(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
os.MkdirAll(filepath.Join(root, "workspace"), 0o755)
|
||||
os.MkdirAll(core.JoinPath(root, "workspace"), 0o755)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -153,13 +152,13 @@ func TestQueue_DrainOne_Good_NoWorkspaces(t *testing.T) {
|
|||
func TestQueue_DrainOne_Good_SkipsNonQueued(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
ws := filepath.Join(wsRoot, "ws-done")
|
||||
ws := core.JoinPath(wsRoot, "ws-done")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
st := &WorkspaceStatus{Status: "completed", Agent: "codex", Repo: "test"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -173,13 +172,13 @@ func TestQueue_DrainOne_Good_SkipsNonQueued(t *testing.T) {
|
|||
func TestQueue_DrainOne_Good_SkipsBackedOffPool(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
ws := filepath.Join(wsRoot, "ws-queued")
|
||||
ws := core.JoinPath(wsRoot, "ws-queued")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
st := &WorkspaceStatus{Status: "queued", Agent: "codex", Repo: "test", Task: "do it"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -197,7 +196,7 @@ func TestQueue_DrainOne_Good_SkipsBackedOffPool(t *testing.T) {
|
|||
func TestQueue_CanDispatchAgent_Ugly(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
os.MkdirAll(filepath.Join(root, "workspace"), 0o755)
|
||||
os.MkdirAll(core.JoinPath(root, "workspace"), 0o755)
|
||||
|
||||
c := core.New()
|
||||
// Set concurrency on Core.Config() — same path that Register() uses
|
||||
|
|
@ -224,7 +223,7 @@ func TestQueue_CanDispatchAgent_Ugly(t *testing.T) {
|
|||
func TestQueue_DrainQueue_Ugly(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
os.MkdirAll(filepath.Join(root, "workspace"), 0o755)
|
||||
os.MkdirAll(core.JoinPath(root, "workspace"), 0o755)
|
||||
|
||||
c := core.New()
|
||||
s := &PrepSubsystem{
|
||||
|
|
@ -243,10 +242,10 @@ func TestQueue_DrainQueue_Ugly(t *testing.T) {
|
|||
func TestQueue_CanDispatchAgent_Bad_AgentAtLimit(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create a running workspace with a valid-looking PID (use our own PID)
|
||||
ws := filepath.Join(wsRoot, "ws-running")
|
||||
ws := core.JoinPath(wsRoot, "ws-running")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
st := &WorkspaceStatus{
|
||||
Status: "running",
|
||||
|
|
@ -255,7 +254,7 @@ func TestQueue_CanDispatchAgent_Bad_AgentAtLimit(t *testing.T) {
|
|||
PID: os.Getpid(), // Our own PID so Kill(pid, 0) succeeds
|
||||
}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
c := core.New()
|
||||
c.Config().Set("agents.concurrency", map[string]ConcurrencyLimit{
|
||||
|
|
@ -277,10 +276,10 @@ func TestQueue_CanDispatchAgent_Bad_AgentAtLimit(t *testing.T) {
|
|||
func TestQueue_CountRunningByAgent_Bad_WrongAgentType(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create a running workspace for a different agent type
|
||||
ws := filepath.Join(wsRoot, "ws-gemini")
|
||||
ws := core.JoinPath(wsRoot, "ws-gemini")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
st := &WorkspaceStatus{
|
||||
Status: "running",
|
||||
|
|
@ -289,7 +288,7 @@ func TestQueue_CountRunningByAgent_Bad_WrongAgentType(t *testing.T) {
|
|||
PID: os.Getpid(),
|
||||
}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -304,12 +303,12 @@ func TestQueue_CountRunningByAgent_Bad_WrongAgentType(t *testing.T) {
|
|||
func TestQueue_CountRunningByAgent_Ugly_CorruptStatusJSON(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create a workspace with corrupt status.json
|
||||
ws := filepath.Join(wsRoot, "ws-corrupt")
|
||||
ws := core.JoinPath(wsRoot, "ws-corrupt")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), []byte("{not valid json!!!"), 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), []byte("{not valid json!!!"), 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -326,9 +325,9 @@ func TestQueue_CountRunningByAgent_Ugly_CorruptStatusJSON(t *testing.T) {
|
|||
func TestQueue_CountRunningByModel_Bad_NoMatchingModel(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
ws := filepath.Join(wsRoot, "ws-1")
|
||||
ws := core.JoinPath(wsRoot, "ws-1")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
st := &WorkspaceStatus{
|
||||
Status: "running",
|
||||
|
|
@ -337,7 +336,7 @@ func TestQueue_CountRunningByModel_Bad_NoMatchingModel(t *testing.T) {
|
|||
PID: os.Getpid(),
|
||||
}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -352,7 +351,7 @@ func TestQueue_CountRunningByModel_Bad_NoMatchingModel(t *testing.T) {
|
|||
func TestQueue_CountRunningByModel_Ugly_ModelMismatch(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Two workspaces, different models of same agent
|
||||
for _, ws := range []struct {
|
||||
|
|
@ -361,11 +360,11 @@ func TestQueue_CountRunningByModel_Ugly_ModelMismatch(t *testing.T) {
|
|||
{"ws-a", "codex:gpt-5.4"},
|
||||
{"ws-b", "codex:gpt-5.3-codex-spark"},
|
||||
} {
|
||||
d := filepath.Join(wsRoot, ws.name)
|
||||
d := core.JoinPath(wsRoot, ws.name)
|
||||
os.MkdirAll(d, 0o755)
|
||||
st := &WorkspaceStatus{Status: "running", Agent: ws.agent, Repo: "test", PID: os.Getpid()}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(d, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(d, "status.json"), data, 0o644)
|
||||
}
|
||||
|
||||
s := &PrepSubsystem{
|
||||
|
|
@ -393,7 +392,7 @@ rates:
|
|||
sustained_delay: 0
|
||||
burst_window: 0
|
||||
burst_delay: 0`
|
||||
os.WriteFile(filepath.Join(root, "agents.yaml"), []byte(cfg), 0o644)
|
||||
os.WriteFile(core.JoinPath(root, "agents.yaml"), []byte(cfg), 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -418,7 +417,7 @@ rates:
|
|||
sustained_delay: 60
|
||||
burst_window: 2
|
||||
burst_delay: 10`
|
||||
os.WriteFile(filepath.Join(root, "agents.yaml"), []byte(cfg), 0o644)
|
||||
os.WriteFile(core.JoinPath(root, "agents.yaml"), []byte(cfg), 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -439,10 +438,10 @@ rates:
|
|||
func TestQueue_DrainOne_Bad_QueuedButAtConcurrencyLimit(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create a running workspace that uses our PID
|
||||
wsRunning := filepath.Join(wsRoot, "ws-running")
|
||||
wsRunning := core.JoinPath(wsRoot, "ws-running")
|
||||
os.MkdirAll(wsRunning, 0o755)
|
||||
stRunning := &WorkspaceStatus{
|
||||
Status: "running",
|
||||
|
|
@ -451,14 +450,14 @@ func TestQueue_DrainOne_Bad_QueuedButAtConcurrencyLimit(t *testing.T) {
|
|||
PID: os.Getpid(),
|
||||
}
|
||||
dataRunning, _ := json.Marshal(stRunning)
|
||||
os.WriteFile(filepath.Join(wsRunning, "status.json"), dataRunning, 0o644)
|
||||
os.WriteFile(core.JoinPath(wsRunning, "status.json"), dataRunning, 0o644)
|
||||
|
||||
// Create a queued workspace
|
||||
wsQueued := filepath.Join(wsRoot, "ws-queued")
|
||||
wsQueued := core.JoinPath(wsRoot, "ws-queued")
|
||||
os.MkdirAll(wsQueued, 0o755)
|
||||
stQueued := &WorkspaceStatus{Status: "queued", Agent: "claude", Repo: "go-log", Task: "do it"}
|
||||
dataQueued, _ := json.Marshal(stQueued)
|
||||
os.WriteFile(filepath.Join(wsQueued, "status.json"), dataQueued, 0o644)
|
||||
os.WriteFile(core.JoinPath(wsQueued, "status.json"), dataQueued, 0o644)
|
||||
|
||||
c := core.New()
|
||||
c.Config().Set("agents.concurrency", map[string]ConcurrencyLimit{
|
||||
|
|
@ -479,14 +478,14 @@ func TestQueue_DrainOne_Bad_QueuedButAtConcurrencyLimit(t *testing.T) {
|
|||
func TestQueue_DrainOne_Ugly_QueuedButInBackoffWindow(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create a queued workspace
|
||||
ws := filepath.Join(wsRoot, "ws-queued")
|
||||
ws := core.JoinPath(wsRoot, "ws-queued")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
st := &WorkspaceStatus{Status: "queued", Agent: "codex", Repo: "go-io", Task: "fix it"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -609,14 +608,14 @@ func TestQueue_LoadAgentsConfig_Ugly(t *testing.T) {
|
|||
func TestQueue_DrainQueue_Bad_FrozenQueueDoesNothing(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create a queued workspace that would normally be drained
|
||||
ws := filepath.Join(wsRoot, "ws-queued")
|
||||
ws := core.JoinPath(wsRoot, "ws-queued")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
st := &WorkspaceStatus{Status: "queued", Agent: "codex", Repo: "go-io", Task: "fix it"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ package agentic
|
|||
|
||||
import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -28,7 +27,7 @@ func TestQueue_CountRunningByModel_Good_SkipsNonRunning(t *testing.T) {
|
|||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
// Completed workspace — must not be counted
|
||||
ws := filepath.Join(root, "workspace", "test-ws")
|
||||
ws := core.JoinPath(root, "workspace", "test-ws")
|
||||
require.True(t, fs.EnsureDir(ws).OK)
|
||||
require.NoError(t, writeStatus(ws, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -44,7 +43,7 @@ func TestQueue_CountRunningByModel_Good_SkipsMismatchedModel(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
ws := filepath.Join(root, "workspace", "model-ws")
|
||||
ws := core.JoinPath(root, "workspace", "model-ws")
|
||||
require.True(t, fs.EnsureDir(ws).OK)
|
||||
require.NoError(t, writeStatus(ws, &WorkspaceStatus{
|
||||
Status: "running",
|
||||
|
|
@ -62,7 +61,7 @@ func TestQueue_CountRunningByModel_Good_DeepLayout(t *testing.T) {
|
|||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
// Deep layout: workspace/org/repo/task-N/status.json
|
||||
ws := filepath.Join(root, "workspace", "core", "go-io", "task-1")
|
||||
ws := core.JoinPath(root, "workspace", "core", "go-io", "task-1")
|
||||
require.True(t, fs.EnsureDir(ws).OK)
|
||||
require.NoError(t, writeStatus(ws, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -242,7 +241,7 @@ func TestPaths_LocalFs_Good_NonNil(t *testing.T) {
|
|||
|
||||
func TestPaths_LocalFs_Good_CanRead(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "hello.txt")
|
||||
path := core.JoinPath(dir, "hello.txt")
|
||||
require.True(t, fs.Write(path, "hello").OK)
|
||||
|
||||
f := LocalFs()
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import (
|
|||
core "dappco.re/go/core"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
@ -35,7 +34,7 @@ func TestQueue_CanDispatchAgent_Good_NoConfig(t *testing.T) {
|
|||
// With no running workspaces and default config, should be able to dispatch
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}), codePath: t.TempDir()}
|
||||
assert.True(t, s.canDispatchAgent("gemini"))
|
||||
|
|
@ -45,7 +44,7 @@ func TestQueue_CanDispatchAgent_Good_UnknownAgent(t *testing.T) {
|
|||
// Unknown agent has no limit, so always allowed
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}), codePath: t.TempDir()}
|
||||
assert.True(t, s.canDispatchAgent("unknown-agent"))
|
||||
|
|
@ -54,7 +53,7 @@ func TestQueue_CanDispatchAgent_Good_UnknownAgent(t *testing.T) {
|
|||
func TestQueue_CountRunningByAgent_Good_EmptyWorkspace(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{})}
|
||||
assert.Equal(t, 0, s.countRunningByAgent("gemini"))
|
||||
|
|
@ -66,7 +65,7 @@ func TestQueue_CountRunningByAgent_Good_NoRunning(t *testing.T) {
|
|||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
// Create a workspace with completed status under workspace/
|
||||
ws := filepath.Join(root, "workspace", "test-ws")
|
||||
ws := core.JoinPath(root, "workspace", "test-ws")
|
||||
require.True(t, fs.EnsureDir(ws).OK)
|
||||
require.NoError(t, writeStatus(ws, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"encoding/json"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -23,14 +22,14 @@ func TestResume_Resume_Good(t *testing.T) {
|
|||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsRoot := WorkspaceRoot()
|
||||
ws := filepath.Join(wsRoot, "ws-blocked")
|
||||
repoDir := filepath.Join(ws, "repo")
|
||||
ws := core.JoinPath(wsRoot, "ws-blocked")
|
||||
repoDir := core.JoinPath(ws, "repo")
|
||||
os.MkdirAll(repoDir, 0o755)
|
||||
exec.Command("git", "init", repoDir).Run()
|
||||
|
||||
st := &WorkspaceStatus{Status: "blocked", Repo: "go-io", Agent: "codex", Task: "Fix the tests"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}), backoff: make(map[string]time.Time), failCount: make(map[string]int)}
|
||||
_, out, err := s.resume(context.Background(), nil, ResumeInput{
|
||||
|
|
@ -43,7 +42,7 @@ func TestResume_Resume_Good(t *testing.T) {
|
|||
assert.Contains(t, out.Prompt, "Fix the tests")
|
||||
assert.Contains(t, out.Prompt, "Use the new Core API")
|
||||
|
||||
answerContent, _ := os.ReadFile(filepath.Join(repoDir, "ANSWER.md"))
|
||||
answerContent, _ := os.ReadFile(core.JoinPath(repoDir, "ANSWER.md"))
|
||||
assert.Contains(t, string(answerContent), "Use the new Core API")
|
||||
|
||||
// Agent override
|
||||
|
|
@ -53,12 +52,12 @@ func TestResume_Resume_Good(t *testing.T) {
|
|||
assert.Equal(t, "claude:opus", out2.Agent)
|
||||
|
||||
// Completed workspace is resumable too
|
||||
ws2 := filepath.Join(wsRoot, "ws-done")
|
||||
os.MkdirAll(filepath.Join(ws2, "repo"), 0o755)
|
||||
exec.Command("git", "init", filepath.Join(ws2, "repo")).Run()
|
||||
ws2 := core.JoinPath(wsRoot, "ws-done")
|
||||
os.MkdirAll(core.JoinPath(ws2, "repo"), 0o755)
|
||||
exec.Command("git", "init", core.JoinPath(ws2, "repo")).Run()
|
||||
st2 := &WorkspaceStatus{Status: "completed", Repo: "go-io", Agent: "codex", Task: "Review code"}
|
||||
data2, _ := json.Marshal(st2)
|
||||
os.WriteFile(filepath.Join(ws2, "status.json"), data2, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws2, "status.json"), data2, 0o644)
|
||||
|
||||
_, out3, err3 := s.resume(context.Background(), nil, ResumeInput{Workspace: "ws-done", DryRun: true})
|
||||
require.NoError(t, err3)
|
||||
|
|
@ -82,12 +81,12 @@ func TestResume_Resume_Bad(t *testing.T) {
|
|||
assert.Contains(t, err.Error(), "workspace not found")
|
||||
|
||||
// Not resumable (running)
|
||||
ws := filepath.Join(WorkspaceRoot(), "ws-running")
|
||||
os.MkdirAll(filepath.Join(ws, "repo"), 0o755)
|
||||
exec.Command("git", "init", filepath.Join(ws, "repo")).Run()
|
||||
ws := core.JoinPath(WorkspaceRoot(), "ws-running")
|
||||
os.MkdirAll(core.JoinPath(ws, "repo"), 0o755)
|
||||
exec.Command("git", "init", core.JoinPath(ws, "repo")).Run()
|
||||
st := &WorkspaceStatus{Status: "running", Repo: "test", Agent: "codex"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
_, _, err = s.resume(context.Background(), nil, ResumeInput{Workspace: "ws-running"})
|
||||
assert.Error(t, err)
|
||||
|
|
@ -99,9 +98,9 @@ func TestResume_Resume_Ugly(t *testing.T) {
|
|||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
// Workspace exists but no status.json
|
||||
ws := filepath.Join(WorkspaceRoot(), "ws-nostatus")
|
||||
os.MkdirAll(filepath.Join(ws, "repo"), 0o755)
|
||||
exec.Command("git", "init", filepath.Join(ws, "repo")).Run()
|
||||
ws := core.JoinPath(WorkspaceRoot(), "ws-nostatus")
|
||||
os.MkdirAll(core.JoinPath(ws, "repo"), 0o755)
|
||||
exec.Command("git", "init", core.JoinPath(ws, "repo")).Run()
|
||||
|
||||
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}), backoff: make(map[string]time.Time), failCount: make(map[string]int)}
|
||||
_, _, err := s.resume(context.Background(), nil, ResumeInput{Workspace: "ws-nostatus"})
|
||||
|
|
@ -109,12 +108,12 @@ func TestResume_Resume_Ugly(t *testing.T) {
|
|||
assert.Contains(t, err.Error(), "no status.json")
|
||||
|
||||
// No answer provided — prompt has no ANSWER section
|
||||
ws2 := filepath.Join(WorkspaceRoot(), "ws-noanswer")
|
||||
os.MkdirAll(filepath.Join(ws2, "repo"), 0o755)
|
||||
exec.Command("git", "init", filepath.Join(ws2, "repo")).Run()
|
||||
ws2 := core.JoinPath(WorkspaceRoot(), "ws-noanswer")
|
||||
os.MkdirAll(core.JoinPath(ws2, "repo"), 0o755)
|
||||
exec.Command("git", "init", core.JoinPath(ws2, "repo")).Run()
|
||||
st := &WorkspaceStatus{Status: "blocked", Repo: "test", Agent: "codex", Task: "Fix"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws2, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws2, "status.json"), data, 0o644)
|
||||
|
||||
_, out, err := s.resume(context.Background(), nil, ResumeInput{Workspace: "ws-noanswer", DryRun: true})
|
||||
require.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
|
@ -49,7 +48,7 @@ func TestSaveLoadRateLimitState_Good_Roundtrip(t *testing.T) {
|
|||
t.Setenv("CORE_WORKSPACE", dir)
|
||||
|
||||
// Ensure .core dir exists
|
||||
os.MkdirAll(filepath.Join(dir, ".core"), 0o755)
|
||||
os.MkdirAll(core.JoinPath(dir, ".core"), 0o755)
|
||||
|
||||
// Note: saveRateLimitState uses core.Env("DIR_HOME") which is pre-populated.
|
||||
// We need to work around this by using CORE_WORKSPACE for the load,
|
||||
|
|
@ -97,7 +96,7 @@ func TestReviewQueue_Good_NoCandidates(t *testing.T) {
|
|||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
// Create an empty core dir (no repos)
|
||||
coreDir := filepath.Join(root, "core")
|
||||
coreDir := core.JoinPath(root, "core")
|
||||
os.MkdirAll(coreDir, 0o755)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
|
|
@ -118,7 +117,7 @@ func TestReviewQueue_Good_NoCandidates(t *testing.T) {
|
|||
func TestStatus_Good_FilteredByStatus(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create workspaces with different statuses
|
||||
for _, ws := range []struct {
|
||||
|
|
@ -130,11 +129,11 @@ func TestStatus_Good_FilteredByStatus(t *testing.T) {
|
|||
{"ws-3", "completed"},
|
||||
{"ws-4", "queued"},
|
||||
} {
|
||||
wsDir := filepath.Join(wsRoot, ws.name)
|
||||
wsDir := core.JoinPath(wsRoot, ws.name)
|
||||
os.MkdirAll(wsDir, 0o755)
|
||||
st := &WorkspaceStatus{Status: ws.status, Repo: "test", Agent: "codex"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(wsDir, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(wsDir, "status.json"), data, 0o644)
|
||||
}
|
||||
|
||||
s := &PrepSubsystem{
|
||||
|
|
@ -156,10 +155,10 @@ func TestStatus_Good_FilteredByStatus(t *testing.T) {
|
|||
func TestHandlers_ResolveWorkspace_Good_Exists(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create workspace dir
|
||||
ws := filepath.Join(wsRoot, "core", "go-io", "task-15")
|
||||
ws := core.JoinPath(wsRoot, "core", "go-io", "task-15")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
|
||||
result := resolveWorkspace("core/go-io/task-15")
|
||||
|
|
@ -177,13 +176,13 @@ func TestHandlers_ResolveWorkspace_Bad_NotExists(t *testing.T) {
|
|||
func TestHandlers_FindWorkspaceByPR_Good_Match(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
ws := filepath.Join(wsRoot, "ws-test")
|
||||
ws := core.JoinPath(wsRoot, "ws-test")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
st := &WorkspaceStatus{Repo: "go-io", Branch: "agent/fix", Status: "completed"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
result := findWorkspaceByPR("go-io", "agent/fix")
|
||||
assert.Equal(t, ws, result)
|
||||
|
|
@ -192,14 +191,14 @@ func TestHandlers_FindWorkspaceByPR_Good_Match(t *testing.T) {
|
|||
func TestHandlers_FindWorkspaceByPR_Good_DeepLayout(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Deep layout: org/repo/task
|
||||
ws := filepath.Join(wsRoot, "core", "agent", "task-5")
|
||||
ws := core.JoinPath(wsRoot, "core", "agent", "task-5")
|
||||
os.MkdirAll(ws, 0o755)
|
||||
st := &WorkspaceStatus{Repo: "agent", Branch: "agent/tests", Status: "completed"}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(ws, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws, "status.json"), data, 0o644)
|
||||
|
||||
result := findWorkspaceByPR("agent", "agent/tests")
|
||||
assert.Equal(t, ws, result)
|
||||
|
|
@ -210,14 +209,14 @@ func TestHandlers_FindWorkspaceByPR_Good_DeepLayout(t *testing.T) {
|
|||
func TestReviewQueue_LoadRateLimitState_Ugly(t *testing.T) {
|
||||
// core.Env("DIR_HOME") is cached at init, so we must write to the real path.
|
||||
// Save original content, write corrupt JSON, test, then restore.
|
||||
ratePath := filepath.Join(core.Env("DIR_HOME"), ".core", "coderabbit-ratelimit.json")
|
||||
ratePath := core.JoinPath(core.Env("DIR_HOME"), ".core", "coderabbit-ratelimit.json")
|
||||
|
||||
// Save original content (may or may not exist)
|
||||
original, readErr := os.ReadFile(ratePath)
|
||||
hadFile := readErr == nil
|
||||
|
||||
// Ensure parent dir exists
|
||||
os.MkdirAll(filepath.Dir(ratePath), 0o755)
|
||||
os.MkdirAll(core.PathDir(ratePath), 0o755)
|
||||
|
||||
// Write corrupt JSON
|
||||
require.NoError(t, os.WriteFile(ratePath, []byte("not-valid-json{{{"), 0o644))
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -22,7 +21,7 @@ import (
|
|||
func TestStatus_Good_EmptyWorkspace(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -40,10 +39,10 @@ func TestStatus_Good_EmptyWorkspace(t *testing.T) {
|
|||
func TestStatus_Good_MixedWorkspaces(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create completed workspace (old layout)
|
||||
ws1 := filepath.Join(wsRoot, "task-1")
|
||||
ws1 := core.JoinPath(wsRoot, "task-1")
|
||||
require.True(t, fs.EnsureDir(ws1).OK)
|
||||
require.NoError(t, writeStatus(ws1, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -52,7 +51,7 @@ func TestStatus_Good_MixedWorkspaces(t *testing.T) {
|
|||
}))
|
||||
|
||||
// Create failed workspace (old layout)
|
||||
ws2 := filepath.Join(wsRoot, "task-2")
|
||||
ws2 := core.JoinPath(wsRoot, "task-2")
|
||||
require.True(t, fs.EnsureDir(ws2).OK)
|
||||
require.NoError(t, writeStatus(ws2, &WorkspaceStatus{
|
||||
Status: "failed",
|
||||
|
|
@ -61,7 +60,7 @@ func TestStatus_Good_MixedWorkspaces(t *testing.T) {
|
|||
}))
|
||||
|
||||
// Create blocked workspace (old layout)
|
||||
ws3 := filepath.Join(wsRoot, "task-3")
|
||||
ws3 := core.JoinPath(wsRoot, "task-3")
|
||||
require.True(t, fs.EnsureDir(ws3).OK)
|
||||
require.NoError(t, writeStatus(ws3, &WorkspaceStatus{
|
||||
Status: "blocked",
|
||||
|
|
@ -71,7 +70,7 @@ func TestStatus_Good_MixedWorkspaces(t *testing.T) {
|
|||
}))
|
||||
|
||||
// Create queued workspace (old layout)
|
||||
ws4 := filepath.Join(wsRoot, "task-4")
|
||||
ws4 := core.JoinPath(wsRoot, "task-4")
|
||||
require.True(t, fs.EnsureDir(ws4).OK)
|
||||
require.NoError(t, writeStatus(ws4, &WorkspaceStatus{
|
||||
Status: "queued",
|
||||
|
|
@ -99,10 +98,10 @@ func TestStatus_Good_MixedWorkspaces(t *testing.T) {
|
|||
func TestStatus_Good_DeepLayout(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create workspace in deep layout (org/repo/task)
|
||||
ws := filepath.Join(wsRoot, "core", "go-io", "task-15")
|
||||
ws := core.JoinPath(wsRoot, "core", "go-io", "task-15")
|
||||
require.True(t, fs.EnsureDir(ws).OK)
|
||||
require.NoError(t, writeStatus(ws, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -125,11 +124,11 @@ func TestStatus_Good_DeepLayout(t *testing.T) {
|
|||
func TestStatus_Good_CorruptStatusFile(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
ws := filepath.Join(wsRoot, "corrupt-ws")
|
||||
ws := core.JoinPath(wsRoot, "corrupt-ws")
|
||||
require.True(t, fs.EnsureDir(ws).OK)
|
||||
require.True(t, fs.Write(filepath.Join(ws, "status.json"), "invalid-json{{{").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(ws, "status.json"), "invalid-json{{{").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -182,7 +181,7 @@ func TestShutdown_ShutdownGraceful_Good(t *testing.T) {
|
|||
func TestShutdown_ShutdownNow_Good_EmptyWorkspace(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
require.True(t, fs.EnsureDir(filepath.Join(root, "workspace")).OK)
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(root, "workspace")).OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -201,11 +200,11 @@ func TestShutdown_ShutdownNow_Good_EmptyWorkspace(t *testing.T) {
|
|||
func TestShutdown_ShutdownNow_Good_ClearsQueued(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create queued workspaces
|
||||
for i := 1; i <= 3; i++ {
|
||||
ws := filepath.Join(wsRoot, "task-"+itoa(i))
|
||||
ws := core.JoinPath(wsRoot, "task-"+itoa(i))
|
||||
require.True(t, fs.EnsureDir(ws).OK)
|
||||
require.NoError(t, writeStatus(ws, &WorkspaceStatus{
|
||||
Status: "queued",
|
||||
|
|
@ -226,7 +225,7 @@ func TestShutdown_ShutdownNow_Good_ClearsQueued(t *testing.T) {
|
|||
|
||||
// Verify queued workspaces are now failed
|
||||
for i := 1; i <= 3; i++ {
|
||||
ws := filepath.Join(wsRoot, "task-"+itoa(i))
|
||||
ws := core.JoinPath(wsRoot, "task-"+itoa(i))
|
||||
st, err := ReadStatus(ws)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "failed", st.Status)
|
||||
|
|
@ -557,10 +556,10 @@ func TestQueue_DrainQueue_Good_FrozenDoesNothing(t *testing.T) {
|
|||
func TestPrep_Shutdown_ShutdownNow_Ugly(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create workspace in deep layout (org/repo/task)
|
||||
ws := filepath.Join(wsRoot, "core", "go-io", "task-5")
|
||||
ws := core.JoinPath(wsRoot, "core", "go-io", "task-5")
|
||||
require.True(t, fs.EnsureDir(ws).OK)
|
||||
require.NoError(t, writeStatus(ws, &WorkspaceStatus{
|
||||
Status: "queued",
|
||||
|
|
@ -646,11 +645,11 @@ func TestShutdown_ShutdownGraceful_Bad_AlreadyFrozen(t *testing.T) {
|
|||
func TestShutdown_ShutdownGraceful_Ugly_WithWorkspaces(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create workspaces with various statuses
|
||||
for _, name := range []string{"ws-completed", "ws-failed", "ws-blocked"} {
|
||||
ws := filepath.Join(wsRoot, name)
|
||||
ws := core.JoinPath(wsRoot, name)
|
||||
require.True(t, fs.EnsureDir(ws).OK)
|
||||
require.NoError(t, writeStatus(ws, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -679,11 +678,11 @@ func TestShutdown_ShutdownGraceful_Ugly_WithWorkspaces(t *testing.T) {
|
|||
func TestShutdown_ShutdownNow_Bad_NoRunningPIDs(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create completed workspaces only (no running PIDs to kill)
|
||||
for i := 1; i <= 2; i++ {
|
||||
ws := filepath.Join(wsRoot, "task-"+itoa(i))
|
||||
ws := core.JoinPath(wsRoot, "task-"+itoa(i))
|
||||
require.True(t, fs.EnsureDir(ws).OK)
|
||||
require.NoError(t, writeStatus(ws, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ package agentic
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
core "dappco.re/go/core"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -35,7 +35,7 @@ func TestStatus_ReadStatus_Good_AllFields(t *testing.T) {
|
|||
}
|
||||
data, err := json.MarshalIndent(original, "", " ")
|
||||
require.NoError(t, err)
|
||||
require.True(t, fs.Write(filepath.Join(dir, "status.json"), string(data)).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "status.json"), string(data)).OK)
|
||||
|
||||
st, err := ReadStatus(dir)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -59,7 +59,7 @@ func TestStatus_ReadStatus_Bad_MissingFile(t *testing.T) {
|
|||
|
||||
func TestStatus_ReadStatus_Bad_CorruptJSON(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "status.json"), `{"status": "running", broken`).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "status.json"), `{"status": "running", broken`).OK)
|
||||
|
||||
_, err := ReadStatus(dir)
|
||||
assert.Error(t, err, "corrupt JSON must return an error")
|
||||
|
|
@ -67,7 +67,7 @@ func TestStatus_ReadStatus_Bad_CorruptJSON(t *testing.T) {
|
|||
|
||||
func TestStatus_ReadStatus_Bad_NullJSON(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "status.json"), "null").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "status.json"), "null").OK)
|
||||
|
||||
// null is valid JSON — ReadStatus returns a zero-value struct, not an error
|
||||
st, err := ReadStatus(dir)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ package agentic
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -30,7 +29,7 @@ func TestStatus_WriteStatus_Good(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Verify file was written via core.Fs
|
||||
r := fs.Read(filepath.Join(dir, "status.json"))
|
||||
r := fs.Read(core.JoinPath(dir, "status.json"))
|
||||
require.True(t, r.OK)
|
||||
|
||||
var read WorkspaceStatus
|
||||
|
|
@ -78,7 +77,7 @@ func TestStatus_ReadStatus_Good(t *testing.T) {
|
|||
|
||||
data, err := json.MarshalIndent(status, "", " ")
|
||||
require.NoError(t, err)
|
||||
require.True(t, fs.Write(filepath.Join(dir, "status.json"), string(data)).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "status.json"), string(data)).OK)
|
||||
|
||||
read, err := ReadStatus(dir)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -100,7 +99,7 @@ func TestStatus_ReadStatus_Bad_NoFile(t *testing.T) {
|
|||
|
||||
func TestStatus_ReadStatus_Bad_InvalidJSON(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "status.json"), "not json{").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "status.json"), "not json{").OK)
|
||||
|
||||
_, err := ReadStatus(dir)
|
||||
assert.Error(t, err)
|
||||
|
|
@ -118,7 +117,7 @@ func TestStatus_ReadStatus_Good_BlockedWithQuestion(t *testing.T) {
|
|||
|
||||
data, err := json.MarshalIndent(status, "", " ")
|
||||
require.NoError(t, err)
|
||||
require.True(t, fs.Write(filepath.Join(dir, "status.json"), string(data)).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "status.json"), string(data)).OK)
|
||||
|
||||
read, err := ReadStatus(dir)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -178,7 +177,7 @@ func TestStatus_WriteStatus_Good_OverwriteExisting(t *testing.T) {
|
|||
|
||||
func TestStatus_ReadStatus_Ugly_EmptyFile(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "status.json"), "").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "status.json"), "").OK)
|
||||
|
||||
_, err := ReadStatus(dir)
|
||||
assert.Error(t, err)
|
||||
|
|
@ -189,33 +188,33 @@ func TestStatus_ReadStatus_Ugly_EmptyFile(t *testing.T) {
|
|||
func TestStatus_Status_Ugly(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Case 1: running + dead PID + BLOCKED.md → should detect as blocked
|
||||
ws1 := filepath.Join(wsRoot, "dead-blocked")
|
||||
require.True(t, fs.EnsureDir(filepath.Join(ws1, "repo")).OK)
|
||||
ws1 := core.JoinPath(wsRoot, "dead-blocked")
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(ws1, "repo")).OK)
|
||||
require.NoError(t, writeStatus(ws1, &WorkspaceStatus{
|
||||
Status: "running",
|
||||
Repo: "go-io",
|
||||
Agent: "codex",
|
||||
PID: 999999,
|
||||
}))
|
||||
require.True(t, fs.Write(filepath.Join(ws1, "repo", "BLOCKED.md"), "Need API credentials").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(ws1, "repo", "BLOCKED.md"), "Need API credentials").OK)
|
||||
|
||||
// Case 2: running + dead PID + agent log → completed
|
||||
ws2 := filepath.Join(wsRoot, "dead-completed")
|
||||
require.True(t, fs.EnsureDir(filepath.Join(ws2, "repo")).OK)
|
||||
ws2 := core.JoinPath(wsRoot, "dead-completed")
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(ws2, "repo")).OK)
|
||||
require.NoError(t, writeStatus(ws2, &WorkspaceStatus{
|
||||
Status: "running",
|
||||
Repo: "go-log",
|
||||
Agent: "claude",
|
||||
PID: 999999,
|
||||
}))
|
||||
require.True(t, fs.Write(filepath.Join(ws2, "agent-claude.log"), "agent finished ok").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(ws2, "agent-claude.log"), "agent finished ok").OK)
|
||||
|
||||
// Case 3: running + dead PID + no log + no BLOCKED.md → failed
|
||||
ws3 := filepath.Join(wsRoot, "dead-failed")
|
||||
require.True(t, fs.EnsureDir(filepath.Join(ws3, "repo")).OK)
|
||||
ws3 := core.JoinPath(wsRoot, "dead-failed")
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(ws3, "repo")).OK)
|
||||
require.NoError(t, writeStatus(ws3, &WorkspaceStatus{
|
||||
Status: "running",
|
||||
Repo: "agent",
|
||||
|
|
@ -318,11 +317,11 @@ func TestStatus_WriteStatus_Bad_ReadOnlyPath(t *testing.T) {
|
|||
func TestStatus_Status_Good_PopulatedWorkspaces(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create a running workspace with a live PID (our own PID)
|
||||
ws1 := filepath.Join(wsRoot, "task-running")
|
||||
require.True(t, fs.EnsureDir(filepath.Join(ws1, "repo")).OK)
|
||||
ws1 := core.JoinPath(wsRoot, "task-running")
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(ws1, "repo")).OK)
|
||||
require.NoError(t, writeStatus(ws1, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
Repo: "go-io",
|
||||
|
|
@ -331,8 +330,8 @@ func TestStatus_Status_Good_PopulatedWorkspaces(t *testing.T) {
|
|||
}))
|
||||
|
||||
// Create a blocked workspace
|
||||
ws2 := filepath.Join(wsRoot, "task-blocked")
|
||||
require.True(t, fs.EnsureDir(filepath.Join(ws2, "repo")).OK)
|
||||
ws2 := core.JoinPath(wsRoot, "task-blocked")
|
||||
require.True(t, fs.EnsureDir(core.JoinPath(ws2, "repo")).OK)
|
||||
require.NoError(t, writeStatus(ws2, &WorkspaceStatus{
|
||||
Status: "blocked",
|
||||
Repo: "go-log",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -66,8 +65,8 @@ func TestVerify_AutoVerifyAndMerge_Good_FullPipeline(t *testing.T) {
|
|||
t.Cleanup(srv.Close)
|
||||
|
||||
dir := t.TempDir()
|
||||
wsDir := filepath.Join(dir, "ws")
|
||||
repoDir := filepath.Join(wsDir, "repo")
|
||||
wsDir := core.JoinPath(dir, "ws")
|
||||
repoDir := core.JoinPath(wsDir, "repo")
|
||||
os.MkdirAll(repoDir, 0o755)
|
||||
|
||||
// No go.mod, composer.json, or package.json = no test runner = passes
|
||||
|
|
@ -79,7 +78,7 @@ func TestVerify_AutoVerifyAndMerge_Good_FullPipeline(t *testing.T) {
|
|||
PRURL: "https://forge.lthn.ai/core/test-repo/pulls/5",
|
||||
}
|
||||
data, _ := json.Marshal(st)
|
||||
os.WriteFile(filepath.Join(wsDir, "status.json"), data, 0o644)
|
||||
os.WriteFile(core.JoinPath(wsDir, "status.json"), data, 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -269,7 +268,7 @@ func TestVerify_RunVerification_Good_NoProjectFile(t *testing.T) {
|
|||
|
||||
func TestVerify_RunVerification_Good_GoProject(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "go.mod"), "module test").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "go.mod"), "module test").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -284,7 +283,7 @@ func TestVerify_RunVerification_Good_GoProject(t *testing.T) {
|
|||
|
||||
func TestVerify_RunVerification_Good_PHPProject(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "composer.json"), `{"require":{}}`).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "composer.json"), `{"require":{}}`).OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -299,7 +298,7 @@ func TestVerify_RunVerification_Good_PHPProject(t *testing.T) {
|
|||
|
||||
func TestVerify_RunVerification_Good_NodeProject(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "package.json"), `{"scripts":{"test":"echo ok"}}`).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "package.json"), `{"scripts":{"test":"echo ok"}}`).OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -313,7 +312,7 @@ func TestVerify_RunVerification_Good_NodeProject(t *testing.T) {
|
|||
|
||||
func TestVerify_RunVerification_Good_NodeNoTestScript(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "package.json"), `{"scripts":{}}`).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "package.json"), `{"scripts":{}}`).OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -330,7 +329,7 @@ func TestVerify_RunVerification_Good_NodeNoTestScript(t *testing.T) {
|
|||
|
||||
func TestVerify_FileExists_Good_Exists(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "test.txt")
|
||||
path := core.JoinPath(dir, "test.txt")
|
||||
require.True(t, fs.Write(path, "hello").OK)
|
||||
|
||||
assert.True(t, fileExists(path))
|
||||
|
|
@ -566,9 +565,9 @@ func TestVerify_AttemptVerifyAndMerge_Ugly(t *testing.T) {
|
|||
|
||||
dir := t.TempDir()
|
||||
// Write a go.mod so runVerification detects Go and runs "go test ./..."
|
||||
require.True(t, fs.Write(filepath.Join(dir, "go.mod"), "module broken-test\n\ngo 1.22").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "go.mod"), "module broken-test\n\ngo 1.22").OK)
|
||||
// Write invalid Go code to force test failure
|
||||
require.True(t, fs.Write(filepath.Join(dir, "broken.go"), "package broken\n\nfunc Bad() { undeclared() }").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "broken.go"), "package broken\n\nfunc Bad() { undeclared() }").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -666,7 +665,7 @@ func TestVerify_ForgeMergePR_Ugly_EmptyBody200(t *testing.T) {
|
|||
|
||||
func TestVerify_FileExists_Ugly_PathIsDirectory(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
sub := filepath.Join(dir, "subdir")
|
||||
sub := core.JoinPath(dir, "subdir")
|
||||
require.NoError(t, os.MkdirAll(sub, 0o755))
|
||||
|
||||
// A directory is not a file — fileExists should return false
|
||||
|
|
@ -728,7 +727,7 @@ func TestVerify_FlagForReview_Ugly_LabelNotFoundZeroID(t *testing.T) {
|
|||
|
||||
func TestVerify_RunVerification_Bad_GoModButNoGoFiles(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "go.mod"), "module test\n\ngo 1.22").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "go.mod"), "module test\n\ngo 1.22").OK)
|
||||
// go.mod exists but no .go files — go test should fail
|
||||
|
||||
s := &PrepSubsystem{
|
||||
|
|
@ -746,8 +745,8 @@ func TestVerify_RunVerification_Bad_GoModButNoGoFiles(t *testing.T) {
|
|||
func TestVerify_RunVerification_Ugly_MultipleProjectFiles(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
// Both go.mod and package.json exist — Go takes priority
|
||||
require.True(t, fs.Write(filepath.Join(dir, "go.mod"), "module test\n\ngo 1.22").OK)
|
||||
require.True(t, fs.Write(filepath.Join(dir, "package.json"), `{"scripts":{"test":"echo ok"}}`).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "go.mod"), "module test\n\ngo 1.22").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "package.json"), `{"scripts":{"test":"echo ok"}}`).OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -764,8 +763,8 @@ func TestVerify_RunVerification_Ugly_MultipleProjectFiles(t *testing.T) {
|
|||
|
||||
func TestVerify_RunVerification_Ugly_GoAndPHPProjectFiles(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.Write(filepath.Join(dir, "go.mod"), "module test\n\ngo 1.22").OK)
|
||||
require.True(t, fs.Write(filepath.Join(dir, "composer.json"), `{"require":{}}`).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "go.mod"), "module test\n\ngo 1.22").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "composer.json"), `{"require":{}}`).OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -782,9 +781,9 @@ func TestVerify_RunVerification_Ugly_GoAndPHPProjectFiles(t *testing.T) {
|
|||
func TestVerify_RunGoTests_Good(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
// Create a valid Go project with a passing test
|
||||
require.True(t, fs.Write(filepath.Join(dir, "go.mod"), "module testproj\n\ngo 1.22\n").OK)
|
||||
require.True(t, fs.Write(filepath.Join(dir, "main.go"), "package testproj\n\nfunc Add(a, b int) int { return a + b }\n").OK)
|
||||
require.True(t, fs.Write(filepath.Join(dir, "main_test.go"), `package testproj
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "go.mod"), "module testproj\n\ngo 1.22\n").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "main.go"), "package testproj\n\nfunc Add(a, b int) int { return a + b }\n").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "main_test.go"), `package testproj
|
||||
|
||||
import "testing"
|
||||
|
||||
|
|
@ -810,8 +809,8 @@ func TestAdd(t *testing.T) {
|
|||
func TestVerify_RunGoTests_Bad(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
// Create a broken Go project — compilation error
|
||||
require.True(t, fs.Write(filepath.Join(dir, "go.mod"), "module broken\n\ngo 1.22\n").OK)
|
||||
require.True(t, fs.Write(filepath.Join(dir, "broken.go"), "package broken\n\nfunc Bad() { undeclared() }\n").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "go.mod"), "module broken\n\ngo 1.22\n").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "broken.go"), "package broken\n\nfunc Bad() { undeclared() }\n").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -828,8 +827,8 @@ func TestVerify_RunGoTests_Bad(t *testing.T) {
|
|||
func TestVerify_RunGoTests_Ugly(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
// go.mod but no test files — Go considers this a pass
|
||||
require.True(t, fs.Write(filepath.Join(dir, "go.mod"), "module empty\n\ngo 1.22\n").OK)
|
||||
require.True(t, fs.Write(filepath.Join(dir, "main.go"), "package empty\n").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "go.mod"), "module empty\n\ngo 1.22\n").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(dir, "main.go"), "package empty\n").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ package agentic
|
|||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -23,7 +22,7 @@ func TestWatch_ResolveWorkspaceDir_Good_RelativeName(t *testing.T) {
|
|||
}
|
||||
dir := s.resolveWorkspaceDir("go-io-abc123")
|
||||
assert.Contains(t, dir, "go-io-abc123")
|
||||
assert.True(t, filepath.IsAbs(dir))
|
||||
assert.True(t, core.PathIsAbs(dir))
|
||||
}
|
||||
|
||||
func TestWatch_ResolveWorkspaceDir_Good_AbsolutePath(t *testing.T) {
|
||||
|
|
@ -42,25 +41,25 @@ func TestWatch_FindActiveWorkspaces_Good_WithActive(t *testing.T) {
|
|||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create running workspace
|
||||
ws1 := filepath.Join(wsRoot, "ws-running")
|
||||
ws1 := core.JoinPath(wsRoot, "ws-running")
|
||||
os.MkdirAll(ws1, 0o755)
|
||||
st1, _ := json.Marshal(WorkspaceStatus{Status: "running", Repo: "go-io", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(ws1, "status.json"), st1, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws1, "status.json"), st1, 0o644)
|
||||
|
||||
// Create completed workspace (should not be in active list)
|
||||
ws2 := filepath.Join(wsRoot, "ws-done")
|
||||
ws2 := core.JoinPath(wsRoot, "ws-done")
|
||||
os.MkdirAll(ws2, 0o755)
|
||||
st2, _ := json.Marshal(WorkspaceStatus{Status: "completed", Repo: "go-crypt", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(ws2, "status.json"), st2, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws2, "status.json"), st2, 0o644)
|
||||
|
||||
// Create queued workspace
|
||||
ws3 := filepath.Join(wsRoot, "ws-queued")
|
||||
ws3 := core.JoinPath(wsRoot, "ws-queued")
|
||||
os.MkdirAll(ws3, 0o755)
|
||||
st3, _ := json.Marshal(WorkspaceStatus{Status: "queued", Repo: "go-log", Agent: "gemini"})
|
||||
os.WriteFile(filepath.Join(ws3, "status.json"), st3, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws3, "status.json"), st3, 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -78,7 +77,7 @@ func TestWatch_FindActiveWorkspaces_Good_Empty(t *testing.T) {
|
|||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
// Ensure workspace dir exists but is empty
|
||||
os.MkdirAll(filepath.Join(root, "workspace"), 0o755)
|
||||
os.MkdirAll(core.JoinPath(root, "workspace"), 0o755)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -94,7 +93,7 @@ func TestWatch_FindActiveWorkspaces_Good_Empty(t *testing.T) {
|
|||
func TestWatch_FindActiveWorkspaces_Bad(t *testing.T) {
|
||||
// Workspace dir doesn't exist
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", filepath.Join(root, "nonexistent"))
|
||||
t.Setenv("CORE_WORKSPACE", core.JoinPath(root, "nonexistent"))
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -111,18 +110,18 @@ func TestWatch_FindActiveWorkspaces_Ugly(t *testing.T) {
|
|||
// Workspaces with corrupt status.json
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
wsRoot := filepath.Join(root, "workspace")
|
||||
wsRoot := core.JoinPath(root, "workspace")
|
||||
|
||||
// Create workspace with corrupt status.json
|
||||
ws1 := filepath.Join(wsRoot, "ws-corrupt")
|
||||
ws1 := core.JoinPath(wsRoot, "ws-corrupt")
|
||||
os.MkdirAll(ws1, 0o755)
|
||||
os.WriteFile(filepath.Join(ws1, "status.json"), []byte("not-valid-json{{{"), 0o644)
|
||||
os.WriteFile(core.JoinPath(ws1, "status.json"), []byte("not-valid-json{{{"), 0o644)
|
||||
|
||||
// Create valid running workspace
|
||||
ws2 := filepath.Join(wsRoot, "ws-valid")
|
||||
ws2 := core.JoinPath(wsRoot, "ws-valid")
|
||||
os.MkdirAll(ws2, 0o755)
|
||||
st, _ := json.Marshal(WorkspaceStatus{Status: "running", Repo: "go-io", Agent: "codex"})
|
||||
os.WriteFile(filepath.Join(ws2, "status.json"), st, 0o644)
|
||||
os.WriteFile(core.JoinPath(ws2, "status.json"), st, 0o644)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
|
|
@ -147,7 +146,7 @@ func TestWatch_ResolveWorkspaceDir_Bad(t *testing.T) {
|
|||
}
|
||||
dir := s.resolveWorkspaceDir("")
|
||||
assert.NotEmpty(t, dir, "empty name should still resolve to workspace root")
|
||||
assert.True(t, filepath.IsAbs(dir))
|
||||
assert.True(t, core.PathIsAbs(dir))
|
||||
}
|
||||
|
||||
func TestWatch_ResolveWorkspaceDir_Ugly(t *testing.T) {
|
||||
|
|
@ -160,6 +159,6 @@ func TestWatch_ResolveWorkspaceDir_Ugly(t *testing.T) {
|
|||
assert.NotPanics(t, func() {
|
||||
dir := s.resolveWorkspaceDir("../..")
|
||||
// JoinPath handles traversal; result should be absolute
|
||||
assert.True(t, filepath.IsAbs(dir))
|
||||
assert.True(t, core.PathIsAbs(dir))
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ package brain
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
core "dappco.re/go/core"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// newTestDirect returns a DirectSubsystem wired to the given test server.
|
||||
|
|
@ -60,9 +61,9 @@ func TestNewDirect_Good_KeyFromFile(t *testing.T) {
|
|||
|
||||
tmpHome := t.TempDir()
|
||||
t.Setenv("CORE_HOME", tmpHome)
|
||||
keyDir := filepath.Join(tmpHome, ".claude")
|
||||
keyDir := core.JoinPath(tmpHome, ".claude")
|
||||
require.True(t, fs.EnsureDir(keyDir).OK)
|
||||
require.True(t, fs.Write(filepath.Join(keyDir, "brain.key"), " file-key-456 \n").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(keyDir, "brain.key"), " file-key-456 \n").OK)
|
||||
|
||||
sub := NewDirect()
|
||||
assert.Equal(t, "file-key-456", sub.apiKey)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"encoding/json"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"dappco.re/go/agent/pkg/messages"
|
||||
|
|
@ -22,23 +21,23 @@ func initTestRepo(t *testing.T) (sourceDir, wsDir string) {
|
|||
t.Helper()
|
||||
|
||||
// Create bare "source" repo
|
||||
sourceDir = filepath.Join(t.TempDir(), "source")
|
||||
sourceDir = core.JoinPath(t.TempDir(), "source")
|
||||
require.NoError(t, os.MkdirAll(sourceDir, 0755))
|
||||
run(t, sourceDir, "git", "init")
|
||||
run(t, sourceDir, "git", "checkout", "-b", "main")
|
||||
os.WriteFile(filepath.Join(sourceDir, "README.md"), []byte("# test"), 0644)
|
||||
os.WriteFile(core.JoinPath(sourceDir, "README.md"), []byte("# test"), 0644)
|
||||
run(t, sourceDir, "git", "add", ".")
|
||||
run(t, sourceDir, "git", "commit", "-m", "init")
|
||||
|
||||
// Create workspace dir with src/ clone
|
||||
wsDir = filepath.Join(t.TempDir(), "workspace")
|
||||
srcDir := filepath.Join(wsDir, "src")
|
||||
wsDir = core.JoinPath(t.TempDir(), "workspace")
|
||||
srcDir := core.JoinPath(wsDir, "src")
|
||||
require.NoError(t, os.MkdirAll(wsDir, 0755))
|
||||
run(t, wsDir, "git", "clone", sourceDir, "src")
|
||||
|
||||
// Create agent branch with a commit
|
||||
run(t, srcDir, "git", "checkout", "-b", "agent/test-task")
|
||||
os.WriteFile(filepath.Join(srcDir, "new.go"), []byte("package main\n"), 0644)
|
||||
os.WriteFile(core.JoinPath(srcDir, "new.go"), []byte("package main\n"), 0644)
|
||||
run(t, srcDir, "git", "add", ".")
|
||||
run(t, srcDir, "git", "commit", "-m", "agent work")
|
||||
|
||||
|
|
@ -62,14 +61,14 @@ func writeStatus(t *testing.T, wsDir, status, repo, branch string) {
|
|||
"branch": branch,
|
||||
}
|
||||
data, _ := json.MarshalIndent(st, "", " ")
|
||||
require.NoError(t, os.WriteFile(filepath.Join(wsDir, "status.json"), data, 0644))
|
||||
require.NoError(t, os.WriteFile(core.JoinPath(wsDir, "status.json"), data, 0644))
|
||||
}
|
||||
|
||||
// --- Tests ---
|
||||
|
||||
func TestHarvest_DetectBranch_Good(t *testing.T) {
|
||||
_, wsDir := initTestRepo(t)
|
||||
srcDir := filepath.Join(wsDir, "src")
|
||||
srcDir := core.JoinPath(wsDir, "src")
|
||||
|
||||
branch := testMon.detectBranch(srcDir)
|
||||
assert.Equal(t, "agent/test-task", branch)
|
||||
|
|
@ -82,7 +81,7 @@ func TestHarvest_DetectBranch_Bad_NoRepo(t *testing.T) {
|
|||
|
||||
func TestHarvest_CountUnpushed_Good(t *testing.T) {
|
||||
_, wsDir := initTestRepo(t)
|
||||
srcDir := filepath.Join(wsDir, "src")
|
||||
srcDir := core.JoinPath(wsDir, "src")
|
||||
|
||||
count := testMon.countUnpushed(srcDir, "agent/test-task")
|
||||
assert.Equal(t, 1, count)
|
||||
|
|
@ -90,7 +89,7 @@ func TestHarvest_CountUnpushed_Good(t *testing.T) {
|
|||
|
||||
func TestHarvest_CountChangedFiles_Good(t *testing.T) {
|
||||
_, wsDir := initTestRepo(t)
|
||||
srcDir := filepath.Join(wsDir, "src")
|
||||
srcDir := core.JoinPath(wsDir, "src")
|
||||
|
||||
count := testMon.countChangedFiles(srcDir)
|
||||
assert.Equal(t, 1, count)
|
||||
|
|
@ -98,7 +97,7 @@ func TestHarvest_CountChangedFiles_Good(t *testing.T) {
|
|||
|
||||
func TestHarvest_CheckSafety_Good_CleanWorkspace(t *testing.T) {
|
||||
_, wsDir := initTestRepo(t)
|
||||
srcDir := filepath.Join(wsDir, "src")
|
||||
srcDir := core.JoinPath(wsDir, "src")
|
||||
|
||||
reason := testMon.checkSafety(srcDir)
|
||||
assert.Equal(t, "", reason)
|
||||
|
|
@ -106,10 +105,10 @@ func TestHarvest_CheckSafety_Good_CleanWorkspace(t *testing.T) {
|
|||
|
||||
func TestHarvest_CheckSafety_Bad_BinaryFile(t *testing.T) {
|
||||
_, wsDir := initTestRepo(t)
|
||||
srcDir := filepath.Join(wsDir, "src")
|
||||
srcDir := core.JoinPath(wsDir, "src")
|
||||
|
||||
// Add a binary file
|
||||
os.WriteFile(filepath.Join(srcDir, "app.exe"), []byte("binary"), 0644)
|
||||
os.WriteFile(core.JoinPath(srcDir, "app.exe"), []byte("binary"), 0644)
|
||||
run(t, srcDir, "git", "add", ".")
|
||||
run(t, srcDir, "git", "commit", "-m", "add binary")
|
||||
|
||||
|
|
@ -120,11 +119,11 @@ func TestHarvest_CheckSafety_Bad_BinaryFile(t *testing.T) {
|
|||
|
||||
func TestHarvest_CheckSafety_Bad_LargeFile(t *testing.T) {
|
||||
_, wsDir := initTestRepo(t)
|
||||
srcDir := filepath.Join(wsDir, "src")
|
||||
srcDir := core.JoinPath(wsDir, "src")
|
||||
|
||||
// Add a file > 1MB
|
||||
bigData := make([]byte, 1024*1024+1)
|
||||
os.WriteFile(filepath.Join(srcDir, "huge.txt"), bigData, 0644)
|
||||
os.WriteFile(core.JoinPath(srcDir, "huge.txt"), bigData, 0644)
|
||||
run(t, srcDir, "git", "add", ".")
|
||||
run(t, srcDir, "git", "commit", "-m", "add large file")
|
||||
|
||||
|
|
@ -148,7 +147,7 @@ func TestHarvest_HarvestWorkspace_Good(t *testing.T) {
|
|||
assert.Equal(t, "", result.rejected)
|
||||
|
||||
// Verify status updated
|
||||
data, err := os.ReadFile(filepath.Join(wsDir, "status.json"))
|
||||
data, err := os.ReadFile(core.JoinPath(wsDir, "status.json"))
|
||||
require.NoError(t, err)
|
||||
var st map[string]any
|
||||
json.Unmarshal(data, &st)
|
||||
|
|
@ -169,7 +168,7 @@ func TestHarvest_HarvestWorkspace_Bad_MainBranch(t *testing.T) {
|
|||
_, wsDir := initTestRepo(t)
|
||||
|
||||
// Switch back to main
|
||||
srcDir := filepath.Join(wsDir, "src")
|
||||
srcDir := core.JoinPath(wsDir, "src")
|
||||
run(t, srcDir, "git", "checkout", "main")
|
||||
|
||||
writeStatus(t, wsDir, "completed", "test-repo", "main")
|
||||
|
|
@ -182,10 +181,10 @@ func TestHarvest_HarvestWorkspace_Bad_MainBranch(t *testing.T) {
|
|||
|
||||
func TestHarvest_HarvestWorkspace_Bad_BinaryRejected(t *testing.T) {
|
||||
_, wsDir := initTestRepo(t)
|
||||
srcDir := filepath.Join(wsDir, "src")
|
||||
srcDir := core.JoinPath(wsDir, "src")
|
||||
|
||||
// Add binary
|
||||
os.WriteFile(filepath.Join(srcDir, "build.so"), []byte("elf"), 0644)
|
||||
os.WriteFile(core.JoinPath(srcDir, "build.so"), []byte("elf"), 0644)
|
||||
run(t, srcDir, "git", "add", ".")
|
||||
run(t, srcDir, "git", "commit", "-m", "add binary")
|
||||
|
||||
|
|
@ -199,7 +198,7 @@ func TestHarvest_HarvestWorkspace_Bad_BinaryRejected(t *testing.T) {
|
|||
assert.Contains(t, result.rejected, "binary file added")
|
||||
|
||||
// Verify status set to rejected
|
||||
data, _ := os.ReadFile(filepath.Join(wsDir, "status.json"))
|
||||
data, _ := os.ReadFile(core.JoinPath(wsDir, "status.json"))
|
||||
var st map[string]any
|
||||
json.Unmarshal(data, &st)
|
||||
assert.Equal(t, "rejected", st["status"])
|
||||
|
|
@ -241,11 +240,11 @@ func TestHarvest_UpdateStatus_Good(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
initial := map[string]any{"status": "completed", "repo": "test"}
|
||||
data, _ := json.MarshalIndent(initial, "", " ")
|
||||
os.WriteFile(filepath.Join(dir, "status.json"), data, 0644)
|
||||
os.WriteFile(core.JoinPath(dir, "status.json"), data, 0644)
|
||||
|
||||
updateStatus(dir, "ready-for-review", "")
|
||||
|
||||
out, _ := os.ReadFile(filepath.Join(dir, "status.json"))
|
||||
out, _ := os.ReadFile(core.JoinPath(dir, "status.json"))
|
||||
var st map[string]any
|
||||
json.Unmarshal(out, &st)
|
||||
assert.Equal(t, "ready-for-review", st["status"])
|
||||
|
|
@ -255,11 +254,11 @@ func TestHarvest_UpdateStatus_Good_WithQuestion(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
initial := map[string]any{"status": "completed", "repo": "test"}
|
||||
data, _ := json.MarshalIndent(initial, "", " ")
|
||||
os.WriteFile(filepath.Join(dir, "status.json"), data, 0644)
|
||||
os.WriteFile(core.JoinPath(dir, "status.json"), data, 0644)
|
||||
|
||||
updateStatus(dir, "rejected", "binary file: app.exe")
|
||||
|
||||
out, _ := os.ReadFile(filepath.Join(dir, "status.json"))
|
||||
out, _ := os.ReadFile(core.JoinPath(dir, "status.json"))
|
||||
var st map[string]any
|
||||
json.Unmarshal(out, &st)
|
||||
assert.Equal(t, "rejected", st["status"])
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ package monitor
|
|||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -43,7 +42,7 @@ func TestLogic_HandleAgentStarted_Bad_EmptyWorkspace(t *testing.T) {
|
|||
func TestLogic_HandleAgentCompleted_Good_NilRuntime(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
mon := New()
|
||||
// ServiceRuntime is nil — must not panic, must record completion and poke.
|
||||
|
|
@ -58,7 +57,7 @@ func TestLogic_HandleAgentCompleted_Good_NilRuntime(t *testing.T) {
|
|||
func TestLogic_HandleAgentCompleted_Good_WithCore(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
// Use Register so IPC handlers are wired
|
||||
c := core.New(core.WithService(Register))
|
||||
|
|
@ -76,7 +75,7 @@ func TestLogic_HandleAgentCompleted_Good_WithCore(t *testing.T) {
|
|||
func TestLogic_HandleAgentCompleted_Bad_EmptyFields(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
mon := New()
|
||||
|
||||
|
|
@ -94,7 +93,7 @@ func TestLogic_HandleAgentCompleted_Bad_EmptyFields(t *testing.T) {
|
|||
func TestLogic_CheckIdleAfterDelay_Bad_NilRuntime(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
mon := New() // ServiceRuntime is nil
|
||||
|
||||
|
|
@ -120,7 +119,7 @@ func TestLogic_CheckIdleAfterDelay_Bad_NilRuntime(t *testing.T) {
|
|||
func TestLogic_CheckIdleAfterDelay_Good_EmptyWorkspace(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
// Create a Core with an IPC handler to capture QueueDrained messages
|
||||
var captured []messages.QueueDrained
|
||||
|
|
@ -153,7 +152,7 @@ func TestLogic_CheckIdleAfterDelay_Good_EmptyWorkspace(t *testing.T) {
|
|||
func TestLogic_CountLiveWorkspaces_Good_EmptyWorkspace(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
mon := New()
|
||||
running, queued := mon.countLiveWorkspaces()
|
||||
|
|
@ -256,7 +255,7 @@ func TestLogic_SetCore_Good_RegistersIPCHandler(t *testing.T) {
|
|||
func TestLogic_SetCore_Good_IPCHandlerFires(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
// IPC handlers are registered via Register, not SetCore
|
||||
c := core.New(core.WithService(Register))
|
||||
|
|
@ -275,7 +274,7 @@ func TestLogic_SetCore_Good_IPCHandlerFires(t *testing.T) {
|
|||
func TestLogic_SetCore_Good_CompletedIPCHandler(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
// IPC handlers are registered via Register, not SetCore
|
||||
c := core.New(core.WithService(Register))
|
||||
|
|
@ -296,7 +295,7 @@ func TestLogic_SetCore_Good_CompletedIPCHandler(t *testing.T) {
|
|||
func TestLogic_OnStartup_Good_StartsLoop(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
home := t.TempDir()
|
||||
t.Setenv("HOME", home)
|
||||
|
|
@ -316,7 +315,7 @@ func TestLogic_OnStartup_Good_StartsLoop(t *testing.T) {
|
|||
func TestLogic_OnStartup_Good_NoError(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
mon := New(Options{Interval: 1 * time.Hour})
|
||||
assert.True(t, mon.OnStartup(context.Background()).OK)
|
||||
|
|
@ -331,7 +330,7 @@ func TestLogic_OnShutdown_Good_NoError(t *testing.T) {
|
|||
func TestLogic_OnShutdown_Good_StopsLoop(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
home := t.TempDir()
|
||||
t.Setenv("HOME", home)
|
||||
|
|
@ -394,7 +393,7 @@ func TestLogic_Register_Good_CoreWired(t *testing.T) {
|
|||
func TestLogic_Register_Good_IPCHandlerActive(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
c := core.New(core.WithService(Register))
|
||||
require.NotNil(t, c)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -26,9 +25,9 @@ func setupBrainKey(t *testing.T, key string) {
|
|||
t.Helper()
|
||||
home := t.TempDir()
|
||||
t.Setenv("HOME", home)
|
||||
claudeDir := filepath.Join(home, ".claude")
|
||||
claudeDir := core.JoinPath(home, ".claude")
|
||||
require.NoError(t, os.MkdirAll(claudeDir, 0755))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(claudeDir, "brain.key"), []byte(key), 0644))
|
||||
require.NoError(t, os.WriteFile(core.JoinPath(claudeDir, "brain.key"), []byte(key), 0644))
|
||||
}
|
||||
|
||||
// setupAPIEnv sets up brain key, CORE_API_URL, and AGENT_NAME for API tests.
|
||||
|
|
@ -43,10 +42,10 @@ func setupAPIEnv(t *testing.T, apiURL string) {
|
|||
// under the given root. Returns the workspace directory path.
|
||||
func writeWorkspaceStatus(t *testing.T, wsRoot, name string, fields map[string]any) string {
|
||||
t.Helper()
|
||||
dir := filepath.Join(wsRoot, "workspace", name)
|
||||
dir := core.JoinPath(wsRoot, "workspace", name)
|
||||
require.NoError(t, os.MkdirAll(dir, 0755))
|
||||
data, _ := json.Marshal(fields)
|
||||
require.NoError(t, os.WriteFile(filepath.Join(dir, "status.json"), data, 0644))
|
||||
require.NoError(t, os.WriteFile(core.JoinPath(dir, "status.json"), data, 0644))
|
||||
return dir
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +129,7 @@ func TestMonitor_CheckCompletions_Good_NewCompletions(t *testing.T) {
|
|||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
// Create Core with IPC handler to capture QueueDrained messages
|
||||
var drainEvents []messages.QueueDrained
|
||||
|
|
@ -166,7 +165,7 @@ func TestMonitor_CheckCompletions_Good_MixedStatuses(t *testing.T) {
|
|||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
mon := New()
|
||||
assert.Equal(t, "", mon.checkCompletions())
|
||||
|
|
@ -203,7 +202,7 @@ func TestMonitor_CheckCompletions_Good_NoNewCompletions(t *testing.T) {
|
|||
func TestMonitor_CheckCompletions_Good_EmptyWorkspace(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
mon := New()
|
||||
msg := mon.checkCompletions()
|
||||
|
|
@ -214,9 +213,9 @@ func TestMonitor_CheckCompletions_Bad_InvalidJSON(t *testing.T) {
|
|||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
|
||||
dir := filepath.Join(wsRoot, "workspace", "ws-bad")
|
||||
dir := core.JoinPath(wsRoot, "workspace", "ws-bad")
|
||||
require.NoError(t, os.MkdirAll(dir, 0755))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(dir, "status.json"), []byte("not json"), 0644))
|
||||
require.NoError(t, os.WriteFile(core.JoinPath(dir, "status.json"), []byte("not json"), 0644))
|
||||
|
||||
mon := New()
|
||||
msg := mon.checkCompletions()
|
||||
|
|
@ -227,7 +226,7 @@ func TestMonitor_CheckCompletions_Good_NilRuntime(t *testing.T) {
|
|||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
mon := New()
|
||||
assert.Equal(t, "", mon.checkCompletions())
|
||||
|
|
@ -424,7 +423,7 @@ func TestMonitor_Check_Good_CombinesMessages(t *testing.T) {
|
|||
func TestMonitor_Check_Good_NoMessages(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
home := t.TempDir()
|
||||
t.Setenv("HOME", home)
|
||||
|
|
@ -445,7 +444,7 @@ func TestMonitor_Notify_Good_NilServer(t *testing.T) {
|
|||
func TestMonitor_Loop_Good_ImmediateCancel(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
home := t.TempDir()
|
||||
t.Setenv("HOME", home)
|
||||
|
|
@ -470,7 +469,7 @@ func TestMonitor_Loop_Good_ImmediateCancel(t *testing.T) {
|
|||
func TestMonitor_Loop_Good_PokeTriggersCheck(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
home := t.TempDir()
|
||||
t.Setenv("HOME", home)
|
||||
|
|
@ -613,7 +612,7 @@ func TestMonitor_AgentStatusResource_Good(t *testing.T) {
|
|||
func TestMonitor_AgentStatusResource_Good_Empty(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
mon := New()
|
||||
result, err := mon.agentStatusResource(context.Background(), &mcp.ReadResourceRequest{})
|
||||
|
|
@ -626,9 +625,9 @@ func TestMonitor_AgentStatusResource_Bad_InvalidJSON(t *testing.T) {
|
|||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
|
||||
dir := filepath.Join(wsRoot, "workspace", "ws-bad")
|
||||
dir := core.JoinPath(wsRoot, "workspace", "ws-bad")
|
||||
require.NoError(t, os.MkdirAll(dir, 0755))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(dir, "status.json"), []byte("bad"), 0644))
|
||||
require.NoError(t, os.WriteFile(core.JoinPath(dir, "status.json"), []byte("bad"), 0644))
|
||||
|
||||
mon := New()
|
||||
result, err := mon.agentStatusResource(context.Background(), &mcp.ReadResourceRequest{})
|
||||
|
|
@ -639,25 +638,25 @@ func TestMonitor_AgentStatusResource_Bad_InvalidJSON(t *testing.T) {
|
|||
// --- syncRepos (git pull path) ---
|
||||
|
||||
func TestMonitor_SyncRepos_Good_PullsChangedRepo(t *testing.T) {
|
||||
remoteDir := filepath.Join(t.TempDir(), "remote")
|
||||
remoteDir := core.JoinPath(t.TempDir(), "remote")
|
||||
require.NoError(t, os.MkdirAll(remoteDir, 0755))
|
||||
run(t, remoteDir, "git", "init", "--bare")
|
||||
|
||||
codeDir := t.TempDir()
|
||||
repoDir := filepath.Join(codeDir, "test-repo")
|
||||
repoDir := core.JoinPath(codeDir, "test-repo")
|
||||
run(t, codeDir, "git", "clone", remoteDir, "test-repo")
|
||||
run(t, repoDir, "git", "checkout", "-b", "main")
|
||||
os.WriteFile(filepath.Join(repoDir, "README.md"), []byte("# test"), 0644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "README.md"), []byte("# test"), 0644)
|
||||
run(t, repoDir, "git", "add", ".")
|
||||
run(t, repoDir, "git", "commit", "-m", "init")
|
||||
run(t, repoDir, "git", "push", "-u", "origin", "main")
|
||||
|
||||
// Simulate another agent pushing work via a second clone
|
||||
clone2Parent := t.TempDir()
|
||||
tmpClone := filepath.Join(clone2Parent, "clone2")
|
||||
tmpClone := core.JoinPath(clone2Parent, "clone2")
|
||||
run(t, clone2Parent, "git", "clone", remoteDir, "clone2")
|
||||
run(t, tmpClone, "git", "checkout", "main")
|
||||
os.WriteFile(filepath.Join(tmpClone, "new.go"), []byte("package main\n"), 0644)
|
||||
os.WriteFile(core.JoinPath(tmpClone, "new.go"), []byte("package main\n"), 0644)
|
||||
run(t, tmpClone, "git", "add", ".")
|
||||
run(t, tmpClone, "git", "commit", "-m", "agent work")
|
||||
run(t, tmpClone, "git", "push", "origin", "main")
|
||||
|
|
@ -683,21 +682,21 @@ func TestMonitor_SyncRepos_Good_PullsChangedRepo(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMonitor_SyncRepos_Good_SkipsDirtyRepo(t *testing.T) {
|
||||
remoteDir := filepath.Join(t.TempDir(), "remote")
|
||||
remoteDir := core.JoinPath(t.TempDir(), "remote")
|
||||
require.NoError(t, os.MkdirAll(remoteDir, 0755))
|
||||
run(t, remoteDir, "git", "init", "--bare")
|
||||
|
||||
codeDir := t.TempDir()
|
||||
repoDir := filepath.Join(codeDir, "dirty-repo")
|
||||
repoDir := core.JoinPath(codeDir, "dirty-repo")
|
||||
run(t, codeDir, "git", "clone", remoteDir, "dirty-repo")
|
||||
run(t, repoDir, "git", "checkout", "-b", "main")
|
||||
os.WriteFile(filepath.Join(repoDir, "README.md"), []byte("# test"), 0644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "README.md"), []byte("# test"), 0644)
|
||||
run(t, repoDir, "git", "add", ".")
|
||||
run(t, repoDir, "git", "commit", "-m", "init")
|
||||
run(t, repoDir, "git", "push", "-u", "origin", "main")
|
||||
|
||||
// Make the repo dirty
|
||||
os.WriteFile(filepath.Join(repoDir, "dirty.txt"), []byte("uncommitted"), 0644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "dirty.txt"), []byte("uncommitted"), 0644)
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
resp := CheckinResponse{
|
||||
|
|
@ -719,15 +718,15 @@ func TestMonitor_SyncRepos_Good_SkipsDirtyRepo(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMonitor_SyncRepos_Good_SkipsNonMainBranch(t *testing.T) {
|
||||
remoteDir := filepath.Join(t.TempDir(), "remote")
|
||||
remoteDir := core.JoinPath(t.TempDir(), "remote")
|
||||
require.NoError(t, os.MkdirAll(remoteDir, 0755))
|
||||
run(t, remoteDir, "git", "init", "--bare")
|
||||
|
||||
codeDir := t.TempDir()
|
||||
repoDir := filepath.Join(codeDir, "feature-repo")
|
||||
repoDir := core.JoinPath(codeDir, "feature-repo")
|
||||
run(t, codeDir, "git", "clone", remoteDir, "feature-repo")
|
||||
run(t, repoDir, "git", "checkout", "-b", "main")
|
||||
os.WriteFile(filepath.Join(repoDir, "README.md"), []byte("# test"), 0644)
|
||||
os.WriteFile(core.JoinPath(repoDir, "README.md"), []byte("# test"), 0644)
|
||||
run(t, repoDir, "git", "add", ".")
|
||||
run(t, repoDir, "git", "commit", "-m", "init")
|
||||
run(t, repoDir, "git", "push", "-u", "origin", "main")
|
||||
|
|
@ -800,21 +799,21 @@ func TestMonitor_HarvestCompleted_Good_MultipleWorkspaces(t *testing.T) {
|
|||
|
||||
for i := 0; i < 2; i++ {
|
||||
name := fmt.Sprintf("ws-%d", i)
|
||||
wsDir := filepath.Join(wsRoot, "workspace", name)
|
||||
wsDir := core.JoinPath(wsRoot, "workspace", name)
|
||||
|
||||
sourceDir := filepath.Join(wsRoot, fmt.Sprintf("source-%d", i))
|
||||
sourceDir := core.JoinPath(wsRoot, fmt.Sprintf("source-%d", i))
|
||||
require.NoError(t, os.MkdirAll(sourceDir, 0755))
|
||||
run(t, sourceDir, "git", "init")
|
||||
run(t, sourceDir, "git", "checkout", "-b", "main")
|
||||
os.WriteFile(filepath.Join(sourceDir, "README.md"), []byte("# test"), 0644)
|
||||
os.WriteFile(core.JoinPath(sourceDir, "README.md"), []byte("# test"), 0644)
|
||||
run(t, sourceDir, "git", "add", ".")
|
||||
run(t, sourceDir, "git", "commit", "-m", "init")
|
||||
|
||||
require.NoError(t, os.MkdirAll(wsDir, 0755))
|
||||
run(t, wsDir, "git", "clone", sourceDir, "src")
|
||||
srcDir := filepath.Join(wsDir, "src")
|
||||
srcDir := core.JoinPath(wsDir, "src")
|
||||
run(t, srcDir, "git", "checkout", "-b", "agent/test-task")
|
||||
os.WriteFile(filepath.Join(srcDir, "new.go"), []byte("package main\n"), 0644)
|
||||
os.WriteFile(core.JoinPath(srcDir, "new.go"), []byte("package main\n"), 0644)
|
||||
run(t, srcDir, "git", "add", ".")
|
||||
run(t, srcDir, "git", "commit", "-m", "agent work")
|
||||
|
||||
|
|
@ -846,7 +845,7 @@ func TestMonitor_HarvestCompleted_Good_MultipleWorkspaces(t *testing.T) {
|
|||
func TestMonitor_HarvestCompleted_Good_Empty(t *testing.T) {
|
||||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(wsRoot, "workspace"), 0755))
|
||||
require.NoError(t, os.MkdirAll(core.JoinPath(wsRoot, "workspace"), 0755))
|
||||
|
||||
mon := New()
|
||||
mon.ServiceRuntime = testMon.ServiceRuntime
|
||||
|
|
@ -858,25 +857,25 @@ func TestMonitor_HarvestCompleted_Good_RejectedWorkspace(t *testing.T) {
|
|||
wsRoot := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", wsRoot)
|
||||
|
||||
sourceDir := filepath.Join(wsRoot, "source-rej")
|
||||
sourceDir := core.JoinPath(wsRoot, "source-rej")
|
||||
require.NoError(t, os.MkdirAll(sourceDir, 0755))
|
||||
run(t, sourceDir, "git", "init")
|
||||
run(t, sourceDir, "git", "checkout", "-b", "main")
|
||||
os.WriteFile(filepath.Join(sourceDir, "README.md"), []byte("# test"), 0644)
|
||||
os.WriteFile(core.JoinPath(sourceDir, "README.md"), []byte("# test"), 0644)
|
||||
run(t, sourceDir, "git", "add", ".")
|
||||
run(t, sourceDir, "git", "commit", "-m", "init")
|
||||
|
||||
wsDir := filepath.Join(wsRoot, "workspace", "ws-rej")
|
||||
wsDir := core.JoinPath(wsRoot, "workspace", "ws-rej")
|
||||
require.NoError(t, os.MkdirAll(wsDir, 0755))
|
||||
run(t, wsDir, "git", "clone", sourceDir, "src")
|
||||
srcDir := filepath.Join(wsDir, "src")
|
||||
srcDir := core.JoinPath(wsDir, "src")
|
||||
run(t, srcDir, "git", "checkout", "-b", "agent/test-task")
|
||||
os.WriteFile(filepath.Join(srcDir, "new.go"), []byte("package main\n"), 0644)
|
||||
os.WriteFile(core.JoinPath(srcDir, "new.go"), []byte("package main\n"), 0644)
|
||||
run(t, srcDir, "git", "add", ".")
|
||||
run(t, srcDir, "git", "commit", "-m", "agent work")
|
||||
|
||||
// Add binary to trigger rejection
|
||||
os.WriteFile(filepath.Join(srcDir, "app.exe"), []byte("binary"), 0644)
|
||||
os.WriteFile(core.JoinPath(srcDir, "app.exe"), []byte("binary"), 0644)
|
||||
run(t, srcDir, "git", "add", ".")
|
||||
run(t, srcDir, "git", "commit", "-m", "add binary")
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
package setup
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
core "dappco.re/go/core"
|
||||
|
|
@ -19,7 +18,7 @@ func testSvc() *Service {
|
|||
|
||||
func TestDetect_Good(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.WriteMode(filepath.Join(dir, "go.mod"), "module example.com/test\n", 0644).OK)
|
||||
require.True(t, fs.WriteMode(core.JoinPath(dir, "go.mod"), "module example.com/test\n", 0644).OK)
|
||||
|
||||
assert.Equal(t, TypeGo, Detect(dir))
|
||||
assert.Equal(t, []ProjectType{TypeGo}, DetectAll(dir))
|
||||
|
|
@ -59,28 +58,28 @@ func TestParseGitRemote_Bad(t *testing.T) {
|
|||
|
||||
func TestRun_Good(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.WriteMode(filepath.Join(dir, "go.mod"), "module example.com/test\n", 0644).OK)
|
||||
require.True(t, fs.WriteMode(core.JoinPath(dir, "go.mod"), "module example.com/test\n", 0644).OK)
|
||||
|
||||
err := testSvc().Run(Options{Path: dir})
|
||||
require.NoError(t, err)
|
||||
|
||||
build := fs.Read(filepath.Join(dir, ".core", "build.yaml"))
|
||||
build := fs.Read(core.JoinPath(dir, ".core", "build.yaml"))
|
||||
require.True(t, build.OK)
|
||||
assert.Contains(t, build.Value.(string), "type: go")
|
||||
|
||||
test := fs.Read(filepath.Join(dir, ".core", "test.yaml"))
|
||||
test := fs.Read(core.JoinPath(dir, ".core", "test.yaml"))
|
||||
require.True(t, test.OK)
|
||||
assert.Contains(t, test.Value.(string), "go test ./...")
|
||||
}
|
||||
|
||||
func TestRun_TemplateAlias_Good(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.True(t, fs.WriteMode(filepath.Join(dir, "go.mod"), "module example.com/test\n", 0644).OK)
|
||||
require.True(t, fs.WriteMode(core.JoinPath(dir, "go.mod"), "module example.com/test\n", 0644).OK)
|
||||
|
||||
err := testSvc().Run(Options{Path: dir, Template: "agent"})
|
||||
require.NoError(t, err)
|
||||
|
||||
prompt := fs.Read(filepath.Join(dir, "PROMPT.md"))
|
||||
prompt := fs.Read(core.JoinPath(dir, "PROMPT.md"))
|
||||
require.True(t, prompt.OK)
|
||||
assert.Contains(t, prompt.Value.(string), "This workspace was scaffolded by pkg/setup.")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue