cmd/cue/cmd: ignore possible top-level tasks

This mimics the behavior of v0.2.2. Not doing so
caused some cue tool scripts to fail.

Change-Id: Iea6571d19daea31b7970d5603e8980911fec01f3
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7748
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/custom.go b/cmd/cue/cmd/custom.go
index bca4570..4f743a5 100644
--- a/cmd/cue/cmd/custom.go
+++ b/cmd/cue/cmd/custom.go
@@ -141,6 +141,11 @@
 // }
 
 func isTask(v cue.Value) bool {
+	// This mimics the v0.2 behavior. The cutoff is really quite arbitrary. A
+	// sane implementation should not use InferTasks, really.
+	if len(v.Path().Selectors()) == 0 {
+		return false
+	}
 	return v.Kind() == cue.StructKind &&
 		(v.Lookup("$id").Exists() || v.Lookup("kind").Exists())
 }
diff --git a/cmd/cue/cmd/testdata/script/cmd_issue596.txt b/cmd/cue/cmd/testdata/script/cmd_issue596.txt
new file mode 100644
index 0000000..fee1d00
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/cmd_issue596.txt
@@ -0,0 +1,29 @@
+cue cmd dump
+cmp stdout expect-stdout
+-- f1.cue --
+package kube
+
+test: {
+    a: 1
+}
+
+// A kind at the top-level should not be allowed.
+
+kind: "foo"
+$id: "bar"
+
+-- dump_tool.cue --
+package kube
+
+import (
+	"tool/cli"
+	"encoding/yaml"
+)
+
+command: dump: {
+	task: print: cli.Print & { text: yaml.Marshal(test) }
+}
+
+-- expect-stdout --
+a: 1
+
diff --git a/tools/flow/flow.go b/tools/flow/flow.go
index f028cee..44d0dde 100644
--- a/tools/flow/flow.go
+++ b/tools/flow/flow.go
@@ -134,6 +134,11 @@
 	// InferTasks allows tasks to be defined outside of the Root. Such tasks
 	// will only be included in the workflow if any of its fields is referenced
 	// by any of the tasks defined within Root.
+	//
+	// CAVEAT EMPTOR: this features is mostly provided for backwards
+	// compatibility with v0.2. A problem with this approach is that it will
+	// look for task structs within arbitrary data. So if not careful, there may
+	// be spurious matches.
 	InferTasks bool
 
 	// IgnoreConcrete ignores references for which the values are already