@neocompose/cli 0.76.3 → 0.77.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.76.3",
3
+ "version": "0.77.1",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,7 +9,7 @@ description: >-
9
9
  `@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
10
10
  ---
11
11
 
12
- <!-- reviewed-through-cli: 0.76.3 -->
12
+ <!-- reviewed-through-cli: 0.77.1 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -129,7 +129,7 @@ wrappers.
129
129
  The marker near the top of `SKILL.md` must exactly match the package version:
130
130
 
131
131
  ```html
132
- <!-- reviewed-through-cli: 0.76.3 -->
132
+ <!-- reviewed-through-cli: 0.77.1 -->
133
133
  ```
134
134
 
135
135
  The quoted version above is checked too, so this instruction cannot go stale
@@ -86,11 +86,11 @@ that does not authorize copying the annotation onto authored records.
86
86
 
87
87
  Use context-aware typed annotations:
88
88
 
89
- - `@settings(...)` for format/search/selection/editor constraints.
89
+ - `@settings(...)` for format/search/collection/editor constraints.
90
90
  - `@storage(allowed: ...)` on classes and storage keys on members.
91
91
  - `@visibility(.Hidden)` only on a class; absence means visible.
92
92
  - Stateful settings use contextual enum cases, such as
93
- `@settings(format: .Plain)` and `@settings(selection: .Multi)`.
93
+ `@settings(format: .Plain)` and `@settings(kind: .Unordered)`.
94
94
  - `@settings(...)` before a `List` element or `Dictionary` value type
95
95
  configures the collection's entries: `List<@settings(format: .Plain) string>`,
96
96
  `Dictionary<string, @settings(min: 0) int>`. Only the member that declares
@@ -213,6 +213,19 @@ An explicit construction must be assignable to its receiving type. For example,
213
213
  `List<Base>` accepts `new Derived()` when `Derived` inherits `Base`, but rejects
214
214
  an unrelated class at `new`. Generic arguments must also be compatible.
215
215
 
216
+ A generic class without a declared constructor is constructed with its type
217
+ arguments, such as `new Box<int> { Item = 4 }` or a target-typed
218
+ `new() { Item = 4 }`. A `T` field is required unless the type argument is
219
+ nullable, so `new Box<int?>()` may omit it. `new Box()` is rejected as an open
220
+ generic Class. Inside the class, methods and field initializers construct with
221
+ the class's own parameter, such as `public Bag<T> B = new Bag<T>();`. Such an
222
+ initializer with fields or entries, like `new Bag<T> { N = 3 }`, runs per
223
+ instance, since each instance closes `T` differently. A type
224
+ argument that wraps the parameter, such as `new Bag<List<T>>()`, is rejected.
225
+ Type arguments must satisfy `extends` constraints in bodies too.
226
+ A type argument may be a delegate, such as `Box<NeoDelegate<int, int>>`, but
227
+ not a `NeoAction`, which is never a value.
228
+
216
229
  Primary-constructor parameters can initialize generic collection fields directly:
217
230
 
218
231
  ```neo
@@ -221,7 +234,8 @@ class Box<T>(List<T> value) {
221
234
  }
222
235
  ```
223
236
 
224
- The same rule applies to `Dictionary<string, T>` and nested collections.
237
+ The same rule applies to `Dictionary<string, T>`, nested collections, and
238
+ stored instances such as `public static Box<int> Value = new([1, 2]);`.
225
239
 
226
240
  ## Member and relation rules
227
241
 
@@ -231,14 +245,31 @@ the instance's recorded constructor or variant. They track later source-default
231
245
  edits until that field is explicitly overridden; resetting an override makes it
232
246
  virtual again.
233
247
 
234
- A lookup member's arity is its declared type. `public Config Config` selects one
235
- entry and its declared type is the entry type; `public Set<Config> Configs`
236
- selects several. An initializer body for a single-select lookup returns one
237
- entry, never a set.
248
+ Declare a lookup member as `Reference<T>`. `public Reference<Config> Config`
249
+ selects one row and reads as `Config`. `public Set<Reference<Config>> Configs`
250
+ selects several and reads as `Set<Config>`. An initializer body for a single
251
+ reference returns one row, never a set. `T` with `@settings(collection:)` is an
252
+ error; the language server's quick fix respells it.
253
+
254
+ `@settings(collection: Owner.Member)` binds the reference to one collection.
255
+ Without it the reference is unbound: it selects any stored row of `T` or a
256
+ subclass, anywhere in the project. The selected row's store decides writes. A
257
+ write through it to a Save row lands, and to an asset row it errors. Its
258
+ generated C# property is the read-only interface; call `TryWritable` to write.
259
+
260
+ An unbound default can name its row by a unique index:
261
+
262
+ ```neo
263
+ public Reference<Item> StarterSeed = root.Assets.Items.Index.Slug["seed.carrot"]!;
264
+ ```
265
+
266
+ The receiver is a `root` path to a List, `.Index.<Name>` is a unique index on
267
+ it, and the key is a string literal. Any other shape stays initializer code.
268
+
269
+ A `Reference<T>` member satisfies an interface `T Foo { get; }` or
270
+ `{ get; set; }` and an abstract `T Foo { get; }`.
238
271
 
239
- The CLI also accepts `List<T>` with `selection: .Multi` on a member. Emitted
240
- source uses `Set<T>`; constructor and function parameters must use `Set<T>`
241
- to carry selection semantics.
272
+ Constructor and function parameters use `Set<T>` for several selections.
242
273
 
243
274
  Declare a multicast event as `NeoAction<…>`. Its value is an ordered listener
244
275
  set, so give it a bracketed list of method groups — never a lambda, and never
@@ -393,7 +424,12 @@ class Foo(string bar, bool isFun) {
393
424
  Foo value = new(bar: "BAR", isFun: true) { IsFun = false };
394
425
  ```
395
426
 
396
- Header parameters are in scope throughout the class. Permit at most one `init`
427
+ Header parameters are in scope throughout the instance members of the class.
428
+ Field initializers, collection entries, object initializers, and lambdas read
429
+ them per construction, so `public NeoDelegate<int> Value = () => n;` returns
430
+ each instance's own `n`. A lambda can also read `this`, as in
431
+ `() => n + this.M`; the rest of an initializer can't. Static members have no
432
+ construction and can't read header parameters. Permit at most one `init`
397
433
  block. A header constructor disables implicit parameterless `new` and forbids
398
434
  additional constructor overloads. Its derived constructor identity is not
399
435
  authored with `@id`.
@@ -137,6 +137,15 @@ Other static fields can call them in their initializers, as in
137
137
  `public static int First = Helper.Run();`. Outside a lambda body, a field
138
138
  initializer qualifies the members it reads; a bare `Run()` or `Number` there is
139
139
  an unknown name.
140
+ A delegate field default is the exception: it may name a method group bare.
141
+ `Value = Read` or `this.Read` binds each new instance to its own `Read`, and a
142
+ static function may be named as `Read` or qualified as `Holder.Read`/`Other.Read`.
143
+ A qualified method group must name a static function. Method groups use the same
144
+ signature rule as in a body, and a mismatch is reported at the declaration.
145
+ A static field that names another static copies a value, as in
146
+ `public static int B = Holder.A;`; a class, List, or Dictionary static shares
147
+ the same object. A static delegate cannot copy another Class's delegate field,
148
+ because its closure compiles in its own Class; wrap it as `() => Other.Call()`.
140
149
  Collection type arguments in constructions, such as `new Box<List<int>>([1, 2])`,
141
150
  work even when no field declares that collection type. Preparation includes the
142
151
  needed type descriptors; spec-only types remain in the test candidate.
@@ -569,7 +578,7 @@ locally, like push. If another commit lands while it runs, the run is refused:
569
578
  run it again. `neo loc` writes work the same way: a write refused because
570
579
  another commit landed is run again.
571
580
 
572
- VS Code rename follows override families and class constructors, resolves contextual enum options such as `.Success`, renames a constructor parameter's named arguments (`new Item(count: 1)`) in bodies, initializers, specs, and base clauses, and keeps local-variable renames scoped to their declaration. Assigned IDs are not required for these refactorings. Inferred locals initialized with conditional expressions retain their common branch type for member completion, navigation, and rename. Typed delegate calls retain their return type too. Lambda returns use the delegate signature for target-typed constructors and enum argument suggestions. Member completion also follows optional access and null-forgiving receivers, including dictionary lookups.
581
+ VS Code rename follows override families and class constructors, resolves contextual enum options such as `.Success`, renames a constructor parameter's named arguments (`new Item(count: 1)`) in bodies, initializers, specs, and base clauses, and keeps local-variable renames scoped to their declaration. Assigned IDs are not required for these refactorings. Inferred locals initialized with conditional expressions retain their common branch type for member completion, navigation, and rename. Direct parenthesized expressions and chained delegate factory calls retain their result type too. `List.Repeat` results infer their element type from the value, explicit call-site type arguments, and expected list type, including for inferred locals and direct indexed access. Lambda returns use the delegate signature for target-typed constructors and enum argument suggestions. Member completion also follows optional access and null-forgiving receivers, including dictionary lookups.
573
582
 
574
583
  ## Member change listeners
575
584