doc/ref/spec.md: disallow new definitions in closed structs

Closes #543
See also Issue #539

It is still possible, of course, to add those with
embeddings.

Change-Id: I91da99c8d8c7b892fe0ff555ceeee87b41d200d9
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8062
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/testdata/definitions/issue539.txtar b/cue/testdata/definitions/issue539.txtar
index a62afdf..3baedfa 100644
--- a/cue/testdata/definitions/issue539.txtar
+++ b/cue/testdata/definitions/issue539.txtar
@@ -6,7 +6,7 @@
 Component: {
 	hostname: string | *"localhost"
 
-	#foo: {
+	_#foo: {
 		hello: "world"
 	}
 }
@@ -18,13 +18,13 @@
   }
   Component: (struct){
     hostname: (string){ |(*(string){ "localhost" }, (string){ string }) }
-    #foo: (#struct){
+    _#foo: (#struct){
       hello: (string){ "world" }
     }
   }
   hello: (#struct){
     hostname: (string){ |(*(string){ "localhost" }, (string){ string }) }
-    #foo: (#struct){
+    _#foo: (#struct){
       hello: (string){ "world" }
     }
   }
@@ -37,7 +37,7 @@
   }
   Component: {
     hostname: (string|*"localhost")
-    #foo: {
+    _#foo: {
       hello: "world"
     }
   }
diff --git a/cue/testdata/definitions/visibility.txtar b/cue/testdata/definitions/visibility.txtar
index 3ce9b7d..c95e235 100644
--- a/cue/testdata/definitions/visibility.txtar
+++ b/cue/testdata/definitions/visibility.txtar
@@ -7,18 +7,30 @@
     _name: "foo"
     _#name: "bar"
 
-    #name: "baz" // TODO: this should not be allowed.
+    #name: "baz"
 }
 -- out/eval --
-(struct){
+Errors:
+foo: field `#name` not allowed:
+    ./in.cue:4:6
+    ./in.cue:9:5
+
+Result:
+(_|_){
+  // [eval]
   #foo: (#struct){
     name: (string){ string }
   }
-  foo: (#struct){
+  foo: (_|_){
+    // [eval]
     name: (string){ string }
     _name: (string){ "foo" }
     _#name: (string){ "bar" }
-    #name: (string){ "baz" }
+    #name: (_|_){
+      // [eval] foo: field `#name` not allowed:
+      //     ./in.cue:4:6
+      //     ./in.cue:9:5
+    }
   }
 }
 -- out/compile --
diff --git a/doc/ref/spec.md b/doc/ref/spec.md
index a5a1dec..da62c38 100644
--- a/doc/ref/spec.md
+++ b/doc/ref/spec.md
@@ -1251,11 +1251,11 @@
 ```
 
 A _closed struct_ `c` is a struct whose instances may not declare any field
-with a name that does not match the name of a regular or optional field,
+with a name that does not match the name of field
 or the pattern of a pattern constraint defined in `c`.
 Hidden fields are excluded from this limitation.
 A struct that is the result of unifying any struct with a [`...`](#Structs)
-declaration is defined for all fields.
+declaration is defined for all regular fields.
 Closing a struct is equivalent to adding `..._|_` to it.
 
 Syntactically, structs are closed explicitly with the `close` builtin or
diff --git a/internal/ci/workflows.cue b/internal/ci/workflows.cue
index c98ed15..26bf40c 100644
--- a/internal/ci/workflows.cue
+++ b/internal/ci/workflows.cue
@@ -107,7 +107,9 @@
 	if: "github.ref == 'refs/heads/master'"
 }
 
-test: json.#Workflow & {
+test: {
+	json.#Workflow
+
 	name: "Test"
 	on: {
 		push: {
@@ -133,7 +135,9 @@
 	}
 }
 
-test_dispatch: json.#Workflow & {
+test_dispatch: {
+	json.#Workflow
+	
 	#checkoutRef: #step & {
 		name: "Checkout ref"
 		run: """
@@ -282,7 +286,9 @@
 	}
 }
 
-rebuild_tip_cuelang_org: json.#Workflow & {
+rebuild_tip_cuelang_org: {
+	json.#Workflow
+	
 	name: "Push to tip"
 	on: push: branches: ["master"]
 	jobs: push: {
diff --git a/internal/core/adt/closed2.go b/internal/core/adt/closed2.go
index befde5e..09da29e 100644
--- a/internal/core/adt/closed2.go
+++ b/internal/core/adt/closed2.go
@@ -37,8 +37,7 @@
 		return true, nil
 	}
 
-	if !f.IsString() && f != InvalidLabel {
-		// if f.IsHidden() && f != InvalidLabel {
+	if f.IsHidden() && f != InvalidLabel {
 		return false, nil
 	}
 
diff --git a/internal/core/adt/context.go b/internal/core/adt/context.go
index 37e62ec..5b02207 100644
--- a/internal/core/adt/context.go
+++ b/internal/core/adt/context.go
@@ -94,8 +94,11 @@
 		v.Path(),
 	}, args...)
 	for i := 2; i < len(a); i++ {
-		if n, ok := a[i].(Node); ok {
-			a[i] = c.Str(n)
+		switch x := a[i].(type) {
+		case Node:
+			a[i] = c.Str(x)
+		case Feature:
+			a[i] = x.SelectorString(c)
 		}
 	}
 	s := fmt.Sprintf(" [%d] %s/%v"+format, a...)