fix(ax): resolve nested workspace discovery

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-03-30 20:12:39 +00:00
parent 4d278a5172
commit dc6f2e2073
6 changed files with 139 additions and 15 deletions

View file

@ -118,8 +118,8 @@ func (commands appCommandSet) check(_ core.Options) core.Result {
wsRoot := agentic.WorkspaceRoot()
if fs.IsDir(wsRoot) {
entries := core.PathGlob(core.JoinPath(wsRoot, "*"))
core.Print(nil, " workspace: %s (%d entries)", wsRoot, len(entries))
statusFiles := agentic.WorkspaceStatusPaths()
core.Print(nil, " workspace: %s (%d workspaces)", wsRoot, len(statusFiles))
} else {
core.Print(nil, " workspace: %s (MISSING)", wsRoot)
}

View file

@ -4,10 +4,12 @@ package main
import (
"bytes"
"io"
"os"
"testing"
agentpkg "dappco.re/go/agent"
"dappco.re/go/agent/pkg/agentic"
"dappco.re/go/core"
"github.com/stretchr/testify/assert"
)
@ -31,6 +33,35 @@ func withArgs(t *testing.T, args ...string) {
})
}
func captureStdout(t *testing.T, run func()) string {
t.Helper()
old := os.Stdout
reader, writer, err := os.Pipe()
if err != nil {
t.Fatalf("pipe stdout: %v", err)
}
os.Stdout = writer
defer func() {
os.Stdout = old
}()
run()
if err := writer.Close(); err != nil {
t.Fatalf("close writer: %v", err)
}
data, err := io.ReadAll(reader)
if err != nil {
t.Fatalf("read stdout: %v", err)
}
if err := reader.Close(); err != nil {
t.Fatalf("close reader: %v", err)
}
return string(data)
}
func TestCommands_ApplyLogLevel_Good(t *testing.T) {
defer core.SetLevel(core.LevelInfo)
@ -111,6 +142,26 @@ func TestCommands_Check_Good(t *testing.T) {
assert.True(t, r.OK)
}
func TestCommands_Check_Good_BranchWorkspaceCount(t *testing.T) {
c := newTestCore(t)
ws := core.JoinPath(agentic.WorkspaceRoot(), "core", "go-io", "feature", "new-ui")
assert.True(t, agentic.LocalFs().EnsureDir(agentic.WorkspaceRepoDir(ws)).OK)
assert.True(t, agentic.LocalFs().EnsureDir(agentic.WorkspaceMetaDir(ws)).OK)
assert.True(t, agentic.LocalFs().Write(core.JoinPath(ws, "status.json"), core.JSONMarshalString(agentic.WorkspaceStatus{
Status: "running",
Repo: "go-io",
Agent: "codex",
})).OK)
output := captureStdout(t, func() {
r := c.Cli().Run("check")
assert.True(t, r.OK)
})
assert.Contains(t, output, "1 workspaces")
}
func TestCommands_Env_Good(t *testing.T) {
c := newTestCore(t)

View file

@ -19,23 +19,23 @@ func registerMCPService(c *core.Core) core.Result {
return core.Result{Value: core.E("main.registerMCPService", "core is required", nil), OK: false}
}
var subsystems []mcp.Subsystem
var registeredSubsystems []mcp.Subsystem
if prep, ok := core.ServiceFor[*agentic.PrepSubsystem](c, "agentic"); ok {
subsystems = append(subsystems, prep)
if agenticSubsystem, ok := core.ServiceFor[*agentic.PrepSubsystem](c, "agentic"); ok {
registeredSubsystems = append(registeredSubsystems, agenticSubsystem)
}
if mon, ok := core.ServiceFor[*monitor.Subsystem](c, "monitor"); ok {
subsystems = append(subsystems, mon)
if monitorSubsystem, ok := core.ServiceFor[*monitor.Subsystem](c, "monitor"); ok {
registeredSubsystems = append(registeredSubsystems, monitorSubsystem)
}
if brn, ok := core.ServiceFor[*brain.DirectSubsystem](c, "brain"); ok {
subsystems = append(subsystems, brn)
if brainSubsystem, ok := core.ServiceFor[*brain.DirectSubsystem](c, "brain"); ok {
registeredSubsystems = append(registeredSubsystems, brainSubsystem)
}
svc, err := mcp.New(mcp.Options{
Subsystems: subsystems,
service, err := mcp.New(mcp.Options{
Subsystems: registeredSubsystems,
})
if err != nil {
return core.Result{Value: core.E("main.registerMCPService", "create mcp service", err), OK: false}
}
return core.Result{Value: svc, OK: true}
return core.Result{Value: service, OK: true}
}

View file

@ -614,6 +614,26 @@ func TestCommands_CmdStatus_Good_DeepWorkspace(t *testing.T) {
assert.Contains(t, output, "core/go-io/task-5")
}
func TestCommands_CmdStatus_Good_BranchWorkspace(t *testing.T) {
s, _ := testPrepWithCore(t, nil)
ws := core.JoinPath(WorkspaceRoot(), "core", "go-io", "feature", "new-ui")
fs.EnsureDir(WorkspaceRepoDir(ws))
fs.EnsureDir(WorkspaceMetaDir(ws))
fs.Write(core.JoinPath(ws, "status.json"), core.JSONMarshalString(WorkspaceStatus{
Status: "completed",
Repo: "go-io",
Agent: "codex",
}))
output := captureStdout(t, func() {
r := s.cmdStatus(core.NewOptions())
assert.True(t, r.OK)
})
assert.Contains(t, output, "core/go-io/feature/new-ui")
}
func TestCommands_CmdPrompt_Bad_MissingRepo(t *testing.T) {
s, _ := testPrepWithCore(t, nil)
r := s.cmdPrompt(core.NewOptions())

View file

@ -4,6 +4,8 @@ package agentic
import (
"context"
iofs "io/fs"
"sort"
"strconv"
core "dappco.re/go/core"
@ -82,9 +84,47 @@ func HomeDir() string {
}
func workspaceStatusPaths(wsRoot string) []string {
old := core.PathGlob(core.JoinPath(wsRoot, "*", "status.json"))
deep := core.PathGlob(core.JoinPath(wsRoot, "*", "*", "*", "status.json"))
return append(old, deep...)
if wsRoot == "" {
return nil
}
var paths []string
seen := make(map[string]bool)
var walk func(dir string, depth int)
walk = func(dir string, depth int) {
r := fs.List(dir)
if !r.OK {
return
}
entries, ok := r.Value.([]iofs.DirEntry)
if !ok {
return
}
statusPath := core.JoinPath(dir, "status.json")
if fs.IsFile(statusPath) {
if depth == 1 || depth == 3 || (fs.IsDir(core.JoinPath(dir, "repo")) && fs.IsDir(core.JoinPath(dir, ".meta"))) {
if !seen[statusPath] {
seen[statusPath] = true
paths = append(paths, statusPath)
}
return
}
}
for _, entry := range entries {
if !entry.IsDir() {
continue
}
walk(core.JoinPath(dir, entry.Name()), depth+1)
}
}
walk(wsRoot, 0)
sort.Strings(paths)
return paths
}
// WorkspaceRepoDir returns the checked-out repo directory for a workspace.

View file

@ -8,6 +8,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
core "dappco.re/go/core"
)
@ -65,6 +66,18 @@ func TestPaths_WorkspaceHelpers_Good(t *testing.T) {
assert.Contains(t, WorkspaceLogFiles(wsDir), core.JoinPath(metaDir, "agent-codex.log"))
}
func TestPaths_WorkspaceHelpers_Good_BranchNameWithSlash(t *testing.T) {
t.Setenv("CORE_WORKSPACE", "/tmp/test-core")
wsDir := core.JoinPath(WorkspaceRoot(), "core", "go-io", "feature", "new-ui")
require.True(t, fs.EnsureDir(WorkspaceRepoDir(wsDir)).OK)
require.True(t, fs.EnsureDir(WorkspaceMetaDir(wsDir)).OK)
require.True(t, fs.Write(WorkspaceStatusPath(wsDir), "{}").OK)
assert.Equal(t, "core/go-io/feature/new-ui", WorkspaceName(wsDir))
assert.Contains(t, WorkspaceStatusPaths(), WorkspaceStatusPath(wsDir))
}
func TestPaths_PlansRoot_Good(t *testing.T) {
t.Setenv("CORE_WORKSPACE", "/tmp/test-core")
assert.Equal(t, "/tmp/test-core/plans", PlansRoot())