feat(v0.5): include \$CTASK_ROOT/projects/ in SearchRoots by default

When CTASK_PROJECT_ROOT is unset, SearchRoots now appends
\$CTASK_ROOT/projects/ so that projects created under the default
category are discoverable from any shell without per-session env var
setup. Dedupe in scanAllRoots prevents double-counting workspaces that
are reachable both via the depth-2 scan under CTASK_ROOT and via the
new explicit search root. Adds a named regression test asserting no
duplicates appear in either ResolveQuery or ListWorkspaces results.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-22 19:51:07 -04:00
parent cdff7f32eb
commit 47430a1b1e
3 changed files with 126 additions and 10 deletions
+29
View File
@@ -211,6 +211,35 @@ func TestQueryFindsWorkspaceInProjectRoot(t *testing.T) {
}
}
// Workspace under $CTASK_ROOT/projects/<workspace> must appear exactly once
// in query results, even though SearchRoots includes both $CTASK_ROOT and
// $CTASK_ROOT/projects/ and the two-depth scan under $CTASK_ROOT already
// reaches the projects/ subdirectory.
func TestQueryNoDuplicateFromOverlappingRoots(t *testing.T) {
root := t.TempDir()
createTestWorkspace(t, root, "projects", "2026-04-22_only-once", "active")
// Simulate what v0.5 SearchRoots() produces when CTASK_PROJECT_ROOT is
// unset: the task root plus the default project subdirectory as a
// separate search root.
roots := []string{root, filepath.Join(root, "projects")}
results, err := ResolveQuery(roots, "only-once", false)
if err != nil {
t.Fatalf("ResolveQuery: %v", err)
}
if len(results) != 1 {
t.Fatalf("expected exactly 1 result (dedup), got %d: %+v", len(results), results)
}
listed, err := ListWorkspaces(roots, ListOpts{Limit: 20})
if err != nil {
t.Fatalf("ListWorkspaces: %v", err)
}
if len(listed) != 1 {
t.Fatalf("expected exactly 1 result from ListWorkspaces (dedup), got %d: %+v", len(listed), listed)
}
}
func TestQueryDedupesOverlappingRoots(t *testing.T) {
// If CTASK_PROJECT_ROOT equals CTASK_ROOT, the same workspace must not
// appear twice in ResolveQuery results.