fix(v0.4.1): route all workspace commands through SearchRoots
Every resolver, lister, and most-recent caller now passes config.SearchRoots() so CTASK_PROJECT_ROOT is searched alongside CTASK_ROOT. Commands use ws.Root when rendering relative paths or session env vars so displays and CTASK_ROOT exports are correct for workspaces living under CTASK_PROJECT_ROOT. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+3
-3
@@ -23,8 +23,8 @@ func init() {
|
||||
}
|
||||
|
||||
func runArchive(cmd *cobra.Command, args []string) error {
|
||||
root := config.ResolveRoot()
|
||||
ws := resolveOne(root, args[0], false)
|
||||
roots := config.SearchRoots()
|
||||
ws := resolveOne(roots, args[0], false)
|
||||
|
||||
now := time.Now().UTC().Truncate(time.Second)
|
||||
ws.Meta.Status = "archived"
|
||||
@@ -36,7 +36,7 @@ func runArchive(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("updating metadata: %w", err)
|
||||
}
|
||||
|
||||
relPath := workspace.RelativePath(root, ws.Path)
|
||||
relPath := workspace.RelativePath(ws.Root, ws.Path)
|
||||
fmt.Printf("[ctask] archived: %s\n", relPath)
|
||||
|
||||
return nil
|
||||
|
||||
+4
-4
@@ -32,8 +32,8 @@ func init() {
|
||||
}
|
||||
|
||||
func runDelete(cmd *cobra.Command, args []string) error {
|
||||
root := config.ResolveRoot()
|
||||
ws := resolveOne(root, args[0], deleteAll)
|
||||
roots := config.SearchRoots()
|
||||
ws := resolveOne(roots, args[0], deleteAll)
|
||||
|
||||
// Active workspace protection — two checks, BOTH run before any mutation.
|
||||
//
|
||||
@@ -61,7 +61,7 @@ func runDelete(cmd *cobra.Command, args []string) error {
|
||||
|
||||
// --- Past this point, we are confident no session is active. ---
|
||||
|
||||
relPath := workspace.RelativePath(root, ws.Path)
|
||||
relPath := workspace.RelativePath(ws.Root, ws.Path)
|
||||
|
||||
// Gather contents summary (best-effort, read-only)
|
||||
fileCount, totalSize := summarizeContents(ws.Path)
|
||||
@@ -72,7 +72,7 @@ func runDelete(cmd *cobra.Command, args []string) error {
|
||||
|
||||
// Check if this is the most recently updated workspace across both
|
||||
// tasks and projects.
|
||||
if best, _ := workspace.MostRecentActive(root); best != nil {
|
||||
if best, _ := workspace.MostRecentActive(roots); best != nil {
|
||||
absBest, _ := filepath.Abs(best.Path)
|
||||
if strings.EqualFold(absTarget, absBest) {
|
||||
fmt.Println()
|
||||
|
||||
+1
-1
@@ -152,7 +152,7 @@ func runDoctor(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// Check 5: Workspace root has workspaces
|
||||
results, err := workspace.ListWorkspaces(root, workspace.ListOpts{
|
||||
results, err := workspace.ListWorkspaces(config.SearchRoots(), workspace.ListOpts{
|
||||
IncludeArchived: true,
|
||||
Limit: 0, // no limit
|
||||
})
|
||||
|
||||
+6
-4
@@ -7,9 +7,11 @@ import (
|
||||
"github.com/warrenronsiek/ctask/internal/workspace"
|
||||
)
|
||||
|
||||
// resolveOne resolves a query to exactly one workspace. Prints errors and exits on 0 or >1 matches.
|
||||
func resolveOne(root, query string, includeArchived bool) *workspace.QueryResult {
|
||||
results, err := workspace.ResolveQuery(root, query, includeArchived)
|
||||
// resolveOne resolves a query to exactly one workspace across the given roots.
|
||||
// Prints errors and exits on 0 or >1 matches. Callers typically pass
|
||||
// config.SearchRoots() so both CTASK_ROOT and CTASK_PROJECT_ROOT are searched.
|
||||
func resolveOne(roots []string, query string, includeArchived bool) *workspace.QueryResult {
|
||||
results, err := workspace.ResolveQuery(roots, query, includeArchived)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
@@ -23,7 +25,7 @@ func resolveOne(root, query string, includeArchived bool) *workspace.QueryResult
|
||||
if len(results) > 1 {
|
||||
fmt.Fprintf(os.Stderr, "Multiple workspaces match %q:\n", query)
|
||||
for _, r := range results {
|
||||
fmt.Fprintf(os.Stderr, " %s\n", workspace.RelativePath(root, r.Path))
|
||||
fmt.Fprintf(os.Stderr, " %s\n", workspace.RelativePath(r.Root, r.Path))
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "Specify a more precise query.")
|
||||
os.Exit(1)
|
||||
|
||||
+2
-2
@@ -24,8 +24,8 @@ func init() {
|
||||
}
|
||||
|
||||
func runInfo(cmd *cobra.Command, args []string) error {
|
||||
root := config.ResolveRoot()
|
||||
ws := resolveOne(root, args[0], infoAll)
|
||||
roots := config.SearchRoots()
|
||||
ws := resolveOne(roots, args[0], infoAll)
|
||||
m := ws.Meta
|
||||
|
||||
fmt.Printf("Task: %s\n", m.Slug)
|
||||
|
||||
+2
-2
@@ -31,9 +31,9 @@ func init() {
|
||||
}
|
||||
|
||||
func runLast(cmd *cobra.Command, args []string) error {
|
||||
root := config.ResolveRoot()
|
||||
roots := config.SearchRoots()
|
||||
|
||||
best, err := workspace.MostRecentActive(root)
|
||||
best, err := workspace.MostRecentActive(roots)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+2
-2
@@ -46,7 +46,7 @@ func runList(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("--task and --projects are mutually exclusive; pass at most one")
|
||||
}
|
||||
|
||||
root := config.ResolveRoot()
|
||||
roots := config.SearchRoots()
|
||||
|
||||
wsType := workspace.TypeAny
|
||||
switch {
|
||||
@@ -56,7 +56,7 @@ func runList(cmd *cobra.Command, args []string) error {
|
||||
wsType = workspace.TypeProject
|
||||
}
|
||||
|
||||
results, err := workspace.ListWorkspaces(root, workspace.ListOpts{
|
||||
results, err := workspace.ListWorkspaces(roots, workspace.ListOpts{
|
||||
IncludeArchived: listAll,
|
||||
Category: listCategory,
|
||||
Limit: listLimit,
|
||||
|
||||
+3
-3
@@ -31,8 +31,8 @@ func init() {
|
||||
}
|
||||
|
||||
func runOpen(cmd *cobra.Command, args []string) error {
|
||||
root := config.ResolveRoot()
|
||||
ws := resolveOne(root, args[0], openAll)
|
||||
roots := config.SearchRoots()
|
||||
ws := resolveOne(roots, args[0], openAll)
|
||||
|
||||
// Update updated_at
|
||||
now := time.Now().UTC().Truncate(time.Second)
|
||||
@@ -42,7 +42,7 @@ func runOpen(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("updating metadata: %w", err)
|
||||
}
|
||||
|
||||
envVars := config.EnvVars(ws.Meta.Slug, ws.Meta.Mode, root, ws.Path, ws.Meta.Category, workspace.EffectiveType(ws.Meta))
|
||||
envVars := config.EnvVars(ws.Meta.Slug, ws.Meta.Mode, ws.Root, ws.Path, ws.Meta.Category, workspace.EffectiveType(ws.Meta))
|
||||
|
||||
return session.Run(session.LaunchOpts{
|
||||
WsDir: ws.Path,
|
||||
|
||||
+3
-3
@@ -46,8 +46,8 @@ func doResume(query string, container, useShell, force bool, agentOverride strin
|
||||
return nil
|
||||
}
|
||||
|
||||
root := config.ResolveRoot()
|
||||
ws := resolveOne(root, query, false)
|
||||
roots := config.SearchRoots()
|
||||
ws := resolveOne(roots, query, false)
|
||||
|
||||
// Update updated_at
|
||||
now := time.Now().UTC().Truncate(time.Second)
|
||||
@@ -62,7 +62,7 @@ func doResume(query string, container, useShell, force bool, agentOverride strin
|
||||
agent = ws.Meta.Agent
|
||||
}
|
||||
|
||||
envVars := config.EnvVars(ws.Meta.Slug, ws.Meta.Mode, root, ws.Path, ws.Meta.Category, workspace.EffectiveType(ws.Meta))
|
||||
envVars := config.EnvVars(ws.Meta.Slug, ws.Meta.Mode, ws.Root, ws.Path, ws.Meta.Category, workspace.EffectiveType(ws.Meta))
|
||||
|
||||
return session.Run(session.LaunchOpts{
|
||||
WsDir: ws.Path,
|
||||
|
||||
Reference in New Issue
Block a user