@neocompose/cli 0.81.5 → 0.82.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.81.5",
3
+ "version": "0.82.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.81.5 -->
12
+ <!-- reviewed-through-cli: 0.82.1 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -229,6 +229,9 @@ NeoLookupVariant<ExampleObject, NeoSortingLayer> Layered = new(
229
229
  - `NeoLookupVariant<TObject, TValue>` members retain an unbound lookup handle.
230
230
  A plain `NeoVariant<TObject>` member may select one concrete row with
231
231
  `.Bind(Reference(...))`; do not bind a row to the lookup-handle member type.
232
+ - Variant selections compare equal with `==` when their target class, variant,
233
+ and bound lookup row match; repeated reads of `Variants.Base` are equal.
234
+ `!=` is the inverse, and an unset optional selection remains distinct from Base.
232
235
  - `NeoVariantFolder` and `NeoLookupVariantFolder` are top-level authoring
233
236
  records, never member or parameter types. Variant handle types are supported
234
237
  as the dedicated Variant member kind, but remain invalid as collection entry,
@@ -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.81.5 -->
132
+ <!-- reviewed-through-cli: 0.82.1 -->
133
133
  ```
134
134
 
135
135
  The quoted version above is checked too, so this instruction cannot go stale
@@ -30,8 +30,7 @@ neo push --dry-run --force-recompile
30
30
  ```
31
31
 
32
32
  `neo status` reports invalid constructor parameters at their `.neo` file, line,
33
- and column. Fix the reported parameter type before pushing. For example,
34
- constructor parameters use `Item`; `Reference<Item>` declares member storage.
33
+ and column. Fix the reported parameter type before pushing.
35
34
  A failed class or constructor declaration blocks candidate preparation.
36
35
 
37
36
  Use `neo pull --regenerate-source-names` to replace generated default dialogue
@@ -157,7 +156,9 @@ become real only after acceptance.
157
156
  ## Conflicts and files
158
157
 
159
158
  Conflict resolution accepts LF, CRLF, and mixed line endings. It retains the
160
- selected source lines and their existing line endings.
159
+ selected source lines and their existing line endings. Choosing a deleted side
160
+ removes the source file; deletion placeholders are display text, not authored
161
+ source. Empty files and ordinary comment-only files remain files.
161
162
 
162
163
  Resolve source conflicts by editing the final intended source. Use
163
164
  `neo resolve --mine` or `neo resolve --theirs` only for a deliberate whole-side
@@ -251,17 +251,24 @@ Editing an inline child preserves the outer construction's call-site values for
251
251
  its other fields. The child keeps that construction while its variant selection
252
252
  matches; selecting a different variant gives it an independent recipe.
253
253
 
254
- Declare a lookup member as `Reference<T>`. `public Reference<Config> Config`
255
- selects one row and reads as `Config`. `public Set<Reference<Config>> Configs`
256
- selects several and reads as `Set<Config>`. An initializer body for a single
257
- reference returns one row, never a set. `T` with `@settings(collection:)` is an
258
- error; the language server's quick fix respells it.
259
-
260
- `@settings(collection: Owner.Member)` binds the reference to one collection.
261
- Without it the reference is unbound: it selects any stored row of `T` or a
262
- subclass, anywhere in the project. The selected row's store decides writes. A
263
- write through it to a Save row lands, and to an asset row it errors. Its
264
- generated C# property is the read-only interface; call `TryWritable` to write.
254
+ Declare a lookup member as `Reference<T>`. `T` can be any value type except
255
+ code types; see the NeoScript reference for handle and slot references.
256
+ `public Reference<Config> Config` selects one row and reads as `Config`.
257
+ `public Set<Reference<Config>> Configs` selects several and reads as
258
+ `Set<Config>`. `public Reference<int> TrackedStat` names another member's int.
259
+ `Reference<T>` also works as a collection element, a dictionary value, and an
260
+ unbound generic argument such as `Box<Reference<int>>`. An initializer body for
261
+ a single reference returns one row, never a set. `T` with
262
+ `@settings(collection:)` is an error; the language server's quick fix respells
263
+ it.
264
+
265
+ `@settings(collection: Owner.Member)` binds a class reference to one
266
+ collection. Without it the reference is unbound: it selects any stored row of
267
+ `T` or a subclass, or any member slot of type `T`, anywhere in the project. A
268
+ bound reference can't be a generic argument. The selected row's store decides
269
+ writes. A write through it to a Save row lands, and to an asset row it errors.
270
+ Its generated C# property is the read-only interface; call `TryWritable` to
271
+ write.
265
272
 
266
273
  An unbound default can name its row by a unique index:
267
274
 
@@ -272,6 +279,20 @@ public Reference<Item> StarterSeed = root.Assets.Items.Index.Slug["seed.carrot"]
272
279
  The receiver is a `root` path to a List, `.Index.<Name>` is a unique index on
273
280
  it, and the key is a string literal. Any other shape stays initializer code.
274
281
 
282
+ A slot reference's default wraps a member path in `Reference()`. The path may
283
+ use the same index segments. A plain value isn't a default, and `this` doesn't
284
+ exist yet:
285
+
286
+ ```neo
287
+ public Reference<int> TrackedStat = Reference(root.Player.Gold);
288
+ public Reference<string> Greeting = Reference(root.Npcs.Index.Slug["mira"]!.Greeting);
289
+ public Reference<NeoVariant<Tree>> Look = Reference(root.Garden.Felled);
290
+ ```
291
+
292
+ A `NeoVariant<T>` member's own default stays the bare variant path. A
293
+ `Reference<NeoVariant<T>>` names a member that holds a variant, so its default
294
+ is a `Reference()` member path.
295
+
275
296
  A `Reference<T>` member satisfies an interface `T Foo { get; }` or
276
297
  `{ get; set; }` and an abstract `T Foo { get; }`.
277
298
 
@@ -287,6 +308,10 @@ element picks the storage:
287
308
  - `Set<NeoDialogueReference>` is a multi-select dialogue lookup.
288
309
  - Any other element makes an owned Set whose entries are rows, like a List.
289
310
 
311
+ Constructor mutations such as `Bag.Add(7)` keep owned collection entries as
312
+ backing rows during export and sparse replay. Existing entries retain their
313
+ identities; added entries receive stable identities under the instance.
314
+
290
315
  An owned Set holds `bool`, `int`, `float`, `decimal`,
291
316
  `@settings(format: .Plain) string`, vectors, `Color`, sprites, audio clips,
292
317
  or a class. Elements can't be nullable, collections, variants, delegates,
@@ -587,6 +612,9 @@ its own type arguments during first push and stored replay. Editing a nested
587
612
  constructor argument rebuilds its projected fields in place, including fields
588
613
  stored inside a packed parent; push followed by pull leaves a clean checkout.
589
614
 
615
+ Sparse children with their own declared constructor replay that constructor
616
+ when reconciling edits, including when passed as an aggregate argument.
617
+
590
618
  Schema export retains a constructed default's generic arguments, including
591
619
  nested collection references. For example, a `NeoAnimationClip<ArmPart>`
592
620
  default constructs `new NeoAnimationClip<ArmPart>` and its frames reference
@@ -7,6 +7,7 @@ runtime ownership, evaluation, and migrations.
7
7
 
8
8
  - Inline bodies and snippets
9
9
  - Nullability and ownership
10
+ - References
10
11
  - Numeric builtins
11
12
  - Collection builtins
12
13
  - Conditional and logical operators
@@ -276,6 +277,53 @@ Save, Session, Setter, or otherwise writable. A constructor writes only its
276
277
  `this` instance. A writable structured-leaf field still inherits the receiver's
277
278
  effective storage restrictions.
278
279
 
280
+ ## References
281
+
282
+ `Reference<T>` names one stored row. `T` can be any value type, including
283
+ collections and other references. Code types such as `Action<int>` are
284
+ rejected. `T` picks one of two categories:
285
+
286
+ - A handle is a class, interface, list, set, or dictionary. The reference is the
287
+ object itself, so `Reference<Item>` reads as `Item`. Assigning an `Item`
288
+ rebinds it.
289
+ - A slot is any other value type: `bool`, numbers, `string`, enums, vectors,
290
+ `Color`, sprites, audio clips, `NeoVariant<T>`, `NeoDialogueReference`, or a
291
+ single `Reference<U>`. The reference names another member and reads and writes
292
+ that member's value. It converts to its `T` by reading.
293
+
294
+ `Reference(place)` forms a reference to a stored member, such as `this.Gold`,
295
+ `root.Player.Gold`, `Npc.Mood`, or `item.Count`. Its type comes from the
296
+ member's declaration. When `Selected` is `Reference<Item>`,
297
+ `Reference(this.Selected)` is `Reference<Reference<Item>>` and names the
298
+ selection slot itself. Locals, parameters, list or dictionary elements, vector
299
+ components, getters, query results, and new values have no row to reference.
300
+ Access checks apply where the reference is formed.
301
+
302
+ Assigning to a reference rebinds it when the right side is a reference of the
303
+ same type. Otherwise the value is written into the target:
304
+
305
+ ```neo
306
+ this.A = 5; // writes 5 into A's target
307
+ this.A = this.Count; // writes Count's value into A's target
308
+ this.A = this.B; // A now names B's target
309
+ this.A = Reference(this.Count); // A now names Count
310
+ this.A += 1; // reads A's target, writes it back
311
+ ```
312
+
313
+ A plain value never becomes a reference: passing `3` to a `Reference<int>`
314
+ parameter is an error. A handle reference never owns, so it can't hold a new
315
+ list or a query result.
316
+
317
+ `==` compares handles by identity and slots by value. A collection of
318
+ references compares entries by target, so a `Set<Reference<int>>` holds
319
+ distinct slots. Narrow a `Reference<T>?` with a null check before writing
320
+ through it.
321
+
322
+ The target row decides every write. Writing an asset-owned target errors, and a
323
+ `readonly` target can't be written after initialization. A slot reference's
324
+ `OnChanged` listeners fire when it rebinds and when its target's value changes.
325
+ Inside a generic body, `Reference<T>` takes the category of `T`'s binding.
326
+
279
327
  ## Numeric types
280
328
 
281
329
  `int` is a 32-bit integer and `float` is a 32-bit float, matching C#. Float
@@ -180,9 +180,9 @@ is one such row — its identity comes from the schema key its parameter settles
180
180
 
181
181
  ## Same-push references
182
182
 
183
- `Reference<T>` and `Set<Reference<T>>` declare lookup storage. Their runtime
184
- values are `T` and `Set<T>`, so a projection can assign existing class values
185
- directly:
183
+ `Reference<T>` and `Set<Reference<T>>` declare lookup storage. For a class
184
+ `T`, their runtime values are `T` and `Set<T>`, so a projection can assign
185
+ existing class values directly:
186
186
 
187
187
  ```neo
188
188
  EligibleIngredients = root.Assets.Crafting.FurnaceRecipes
@@ -196,12 +196,19 @@ not clone it or turn it into a separate wrapper object. An optional generic
196
196
  argument checks the target type. Lookup assignment still requires an existing
197
197
  backing row and enforces its declared target and collection constraints.
198
198
 
199
+ A class-constrained generic lookup may select from a collection of its bound
200
+ class. For example, `Reference<TAsset>` with `TAsset extends HeldItemAsset`
201
+ may use `@settings(collection: CosmeticAssets.HeldItems)` when that collection
202
+ holds `HeldItemAsset`. Derived classes may specialize the target and override
203
+ the member; retain the collection setting on each override.
204
+
199
205
  Use the `Reference` intrinsic. Prefer the most readable form the target
200
206
  supports:
201
207
 
202
208
  ```neo
203
209
  Reference(Assets.Capitol)
204
210
  Reference(root.Assets.Cosmetics.Pants)
211
+ Reference(root.Player.Gold)
205
212
  Reference<Outpost>(id: "capitol-value-id")
206
213
  Reference<NeoSpriteObject>(id: "authored-child-id", withProvenance: true)
207
214
  Reference<PantsAsset>(key: "pants.long")
@@ -209,7 +216,9 @@ Reference<PantsAsset>(key: "pants.long", index: Slug)
209
216
  Reference<NeoDialogue>(id: "capitol-dialogue-id")
210
217
  ```
211
218
 
212
- - Use a symbol or root path when source can name the value directly.
219
+ - Use a symbol or root path when source can name the value directly. A
220
+ value-type reference such as `Reference<int>` always names a member path or
221
+ an `id:`; a plain value is an error.
213
222
  - Use `key:` only for a collection with a unique index. Omit `index:` when the
214
223
  collection has exactly one usable unique index; supply the bare member name
215
224
  when it has more than one.