@neocompose/cli 0.89.7 → 0.89.9

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.89.7",
3
+ "version": "0.89.9",
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.89.7 -->
12
+ <!-- reviewed-through-cli: 0.89.9 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -118,6 +118,11 @@ codec reads when changing either projection. Class-generic results whose binding
118
118
  is known only at runtime use the SDK generic reader, including recursive tuple,
119
119
  collection, enum, and reference projections; scalar conversion alone is insufficient.
120
120
 
121
+ Direct class-constrained `Reference<T>` and `Set<Reference<T>>` fields emit concrete
122
+ accessors using the SDK generic reader, even while the declaring class leaves `T`
123
+ open. Only authored abstract declarations emit abstract members. Compile the
124
+ open class and exercise direct, inherited, closed, and read-only instances.
125
+
121
126
  A stored `Reference<T>` implementing an inherited get-only `T` property emits a
122
127
  value getter that reads the reference target. Keep its interface and field tokens
123
128
  on the inherited type, and compile both open and closed generic overrides.
@@ -138,7 +143,7 @@ The marker near the top of `SKILL.md` must exactly match the package version,
138
143
  and this quoted copy is checked too:
139
144
 
140
145
  ```html
141
- <!-- reviewed-through-cli: 0.89.7 -->
146
+ <!-- reviewed-through-cli: 0.89.9 -->
142
147
  ```
143
148
 
144
149
  Keep this skill on current behavior. Upgrade steps, rollout prerequisites,
@@ -31,6 +31,26 @@ Foo value = new(bar: "BAR", isFun: true) { IsFun = false };
31
31
  - A header constructor disables implicit parameterless `new` and forbids
32
32
  other constructor overloads. Its derived identity takes no `@id`.
33
33
 
34
+ ## Variant parameters
35
+
36
+ Constructors accept `NeoVariant<T>` and `NeoLookupVariant<T, TValue>` selections,
37
+ including nullable selections and generic targets such as `NeoVariant<Kid<int>>`.
38
+ A member initializer can retain the selection for each instance:
39
+
40
+ ```neo
41
+ class Box : NeoObject {}
42
+ class Made(NeoVariant<Box> selection) {
43
+ public NeoVariant<Box> Selection = selection;
44
+ }
45
+ Made value = new(Box.Variants.Base);
46
+ ```
47
+
48
+ Push and export retain the selected variant and any bound lookup row for replay.
49
+ `null` is an empty nullable selection; `Box.Variants.Base` selects the base class.
50
+ To pass a bound lookup selection directly, use a declared variant path and a
51
+ stored row ID, such as `new Made(Box.Variants.Seeds.BySeed.Bind(Reference(id: "row-id")))`.
52
+ This compiles to a fixed selection; `Bind` does not evaluate a dynamic row expression.
53
+
34
54
  ## Declared constructors
35
55
 
36
56
  Declare overloadable constructors as members when each body owns its own
@@ -142,6 +162,10 @@ class Child(string name) : Base {
142
162
  explicitly when needed.
143
163
  - Base-constructor arguments use the constructed class's concrete generic
144
164
  bindings, including an `Item<T>` parameter forwarded through its base chain.
165
+ - Recording a constructor argument does not claim ownership. An initializer
166
+ may pass it to a nested constructor or attach it to a collection while
167
+ retaining its identity. Giving the same aggregate two owned fields or
168
+ collection positions still requires an explicit `Clone()`.
145
169
  - Constraints may construct another generic from a sibling parameter:
146
170
 
147
171
  ```neo
@@ -39,6 +39,9 @@ abstract class Item<TContext extends SomeClass> : INamed {
39
39
  The `@id`s above are pulled IDs. New declarations omit them; push assigns them.
40
40
  Never put `@id` on inferred list/dictionary entry types or derived structural
41
41
  descriptors.
42
+ Generic bindings and their nested collection descriptors follow the owning
43
+ declaration's identity. Deleting and recreating an idless declaration creates
44
+ fresh bindings; retaining its pulled IDs preserves them.
42
45
 
43
46
  ## Modifiers
44
47
 
@@ -3,6 +3,11 @@
3
3
  Member defaults: what they may read, when they compute, generic and
4
4
  Immutable construction, and edits to stored constructions.
5
5
 
6
+ Object initializer fields indent one level below the construction's header,
7
+ including inside call arguments. The opening brace may be on the header line
8
+ or the following line. Multiline argument lists retain their continuation
9
+ indentation, using the project's configured spaces or tabs.
10
+
6
11
  ## Initializer scope
7
12
 
8
13
  - Field initializers may read their class's static members unqualified,
@@ -28,6 +33,10 @@ Immutable construction, and edits to stored constructions.
28
33
 
29
34
  ## Computed initializers
30
35
 
36
+ The editor checks computed defaults with the same expression resolver as push.
37
+ Unknown names, missing members, invalid type arguments, and expression type
38
+ errors appear at the offending initializer expression, including nested defaults.
39
+
31
40
  A default that isn't a closed literal stores as a computed initializer and
32
41
  replays for omitted members in push, web, and SDK. A stored override stays
33
42
  pinned until reset.
@@ -4,6 +4,10 @@ Queries and mutations on `List`, `Set`, and `Dictionary` values. Collection
4
4
  declarations and storage live in
5
5
  [member kinds](../declarations/member-kinds.md).
6
6
 
7
+ Collections have no constructors. Initialize List and Set members with `[]`
8
+ and Dictionary members with `{}`, including static members. Writing `new()`
9
+ reports an editor diagnostic with the appropriate empty literal before push.
10
+
7
11
  ## Counting and matching
8
12
 
9
13
  - `items.Count` and `items.Count()` give the size; `items.Count(pred)` counts
@@ -43,7 +47,11 @@ return this.Beds
43
47
  snapshot through a writable alias makes `ThenBy` throw until a new `OrderBy`.
44
48
  - Negative skip/take counts behave as zero.
45
49
  - Read-only results keep entry identity and grant no extra write access to
46
- entries.
50
+ entries. Declared index lookups (`items.Index.Name[key]`) preserve the source
51
+ entries' write permissions: writable fields can be updated through unique
52
+ results or a bucket's entries, while bucket membership stays read-only.
53
+ Subsequent index lookups reflect writes to indexed fields, including writes
54
+ through `Where` results.
47
55
 
48
56
  ## Reductions
49
57
 
@@ -69,6 +77,8 @@ return this.Beds
69
77
 
70
78
  These apply to writable collections and are statements:
71
79
 
80
+ - String-keyed dictionaries accept any string, including `__proto__` and
81
+ `constructor`, in both indexed assignment and `Add(key, value)`.
72
82
  - `items.Add(value)` appends an entry. An aggregate already owned by another
73
83
  entry or field can't be added again. Add a new value, or `Clone()` a class
74
84
  instance.
@@ -18,6 +18,8 @@ List<Item> ready = this.Items.Where((item) => item.Count > 0);
18
18
  - Call any non-null delegate expression directly: `callbacks[0](value)`,
19
19
  `(cond ? a : b)()`, `Factory.Make()()`. Force-unwrap a nullable one first:
20
20
  `callbacks["key"]!()`. Void delegates are statements only.
21
+ - A typed lambda can be called immediately when its result has an expected
22
+ type: `int n = ((int x) => x + 1)(2);`. Declare each parameter's type.
21
23
  - Inside a class body, invoke delegate and action members directly:
22
24
  `Selector()`, `OnUpdated()`.
23
25
 
@@ -70,7 +70,6 @@ stored instance rather than building a copy. Its owning placement keeps it,
70
70
  so a constructor that stores it needs a `Reference` field:
71
71
 
72
72
  ```neo
73
- @id("86ac7c7d-8d3b-4642-9def-cdf32643bdc5")
74
73
  DeliveryQuest HARD_AS_STONE = new();
75
74
  // The core quest list owns HARD_AS_STONE.
76
75
  WorkflowStep UNLOCK = new QuestUnlockStep(HARD_AS_STONE);
@@ -82,13 +81,15 @@ class QuestUnlockStep(DeliveryQuest quest) : WorkflowStep {
82
81
 
83
82
  - The local needs exactly one owning placement. Unowned locals, ambiguous
84
83
  placements, and cycles are source errors.
85
- - A nested target needs its existing `@id`. A structurally owned list entry
86
- may use an unused UUID-v4 in the same push.
87
- - A local nested inside an evaluated constructor stays idless on first push;
88
- push assigns its identity before it can be referenced. Don't give it a fresh
89
- UUID.
90
- - A direct static owner supplies a pending identity for an idless local, and
91
- aliases of that static local work too.
84
+ - New nested locals can be referenced before their first push or export, including
85
+ inside lists, dictionaries, and constructor-backed owners. Preparation resolves
86
+ each reference to the row its unique owner creates. Aliases share that identity.
87
+ Sibling constructor arguments and explicit `Reference(LOCAL)` calls reuse the
88
+ child within the same owning tree. A parent constructor may borrow a child
89
+ that one of its field overrides owns; pull preserves both uses.
90
+ Direct `Reference(LOCAL)` fields resolve after the owning constructor runs.
91
+ - Push writes assigned IDs back to source. Dry-run and export prepare the same
92
+ references without requiring hand-written IDs or an earlier push.
92
93
  - A member default is a construction template, so its local is not a single
93
94
  stored instance.
94
95
  - Owned locals inside evaluated initializers need directly addressable fields,
@@ -44,6 +44,8 @@ frame. For editing an existing clip, see [frame overrides](animation.md).
44
44
  - Selections compare equal when class, variant, and bound lookup row match.
45
45
  An unset optional selection differs from `Base`.
46
46
 
47
+ Variant selections can also be [constructor parameters](../declarations/constructors.md#variant-parameters). A constructor can retain a named, base, or bound lookup selection in a member initializer.
48
+
47
49
  ## Folders
48
50
 
49
51
  ```neo
@@ -112,8 +114,9 @@ NeoLookupVariant<ExampleObject, NeoSortingLayer> Layered = new(
112
114
  ## Type restrictions
113
115
 
114
116
  `NeoVariantFolder` and `NeoLookupVariantFolder` are top-level records, never
115
- member or parameter types. Variant handles are valid as Variant members only,
116
- not as collection entries, lookup targets, parameters, or generic bindings.
117
+ member or parameter types. Variant handles are valid as Variant members and
118
+ constructor parameters, not as collection entries, lookup targets, ordinary
119
+ function parameters, or generic bindings.
117
120
 
118
121
  ## Stored overrides
119
122