@neocompose/cli 0.89.4 → 0.89.6

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.4",
3
+ "version": "0.89.6",
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.4 -->
12
+ <!-- reviewed-through-cli: 0.89.6 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -58,6 +58,12 @@ Specs to read in full when relevant:
58
58
  those. App context projection, database adapters, and reactive hosts stay
59
59
  in the app. `npm run lint:architecture` checks boundaries and cycles;
60
60
  `npm run test:runtime-package` checks a standalone database host.
61
+ - Default-value document adapters must carry constructor descriptors along
62
+ with members and values. Nested declaration defaults can contain constructor
63
+ recipes that construction checks must resolve before copying their rows.
64
+ Default copies pass the closed member placement to `defaultValueSource` and
65
+ read expanded children from that copy's rows. Declaration row IDs alone do
66
+ not identify a generic instantiation.
61
67
  - Compiled test caches include the relative spec path because source
62
68
  coordinates are part of the compiled body. Debug output stays on stderr,
63
69
  including in JSON test runs.
@@ -100,6 +106,29 @@ commits use the shared client preparation protocol.
100
106
  either changes. Undo/reset metadata changes invalidate the incremental
101
107
  cursor and fall back to a full snapshot.
102
108
 
109
+ For Unity export changes to collection entry readers, compile the generated C#.
110
+ Nested `Set<Reference<T>>` entries in lists and dictionaries must construct set
111
+ views for class, slot, and collection targets, preserving read-only membership
112
+ and each selected value's own storage permissions.
113
+ Tuple fields, readers, and factory parameters retain enum-set, reference-handle,
114
+ and nullable-entry metadata. Closed class and interface generic arguments use the same storage representation
115
+ in fields, tuples, factories, and function signatures. Ordinary function
116
+ collections retain read-only interfaces. Check generated C# compilation and SDK
117
+ codec reads when changing either projection. Class-generic results whose binding
118
+ is known only at runtime use the SDK generic reader, including recursive tuple,
119
+ collection, enum, and reference projections; scalar conversion alone is insufficient.
120
+
121
+ A stored `Reference<T>` implementing an inherited get-only `T` property emits a
122
+ value getter that reads the reference target. Keep its interface and field tokens
123
+ on the inherited type, and compile both open and closed generic overrides.
124
+ Reference-valued contracts retain their handles and their constructed base's
125
+ class family. Interface adapters project invariant reference wrappers explicitly.
126
+ When reading a selected collection, resolve its own descriptor, not its entry codec.
127
+ Generic constructor initializers must close Reference target types before encoding
128
+ a selection, so a reference to a list retains the list row rather than its entries.
129
+ Preserve absent optional references through nullable value contracts; required
130
+ references still reject a missing selection.
131
+
103
132
  ## Package and release maintenance
104
133
 
105
134
  Publish native JavaScript only: no `.csproj`, `.cs`, `.dll`, Roslyn host
@@ -109,7 +138,7 @@ The marker near the top of `SKILL.md` must exactly match the package version,
109
138
  and this quoted copy is checked too:
110
139
 
111
140
  ```html
112
- <!-- reviewed-through-cli: 0.89.4 -->
141
+ <!-- reviewed-through-cli: 0.89.6 -->
113
142
  ```
114
143
 
115
144
  Keep this skill on current behavior. Upgrade steps, rollout prerequisites,
@@ -147,3 +176,5 @@ or candidate-materialization changes also need a real `neo test` against the
147
176
  affected full-project candidate; Vitest doesn't replace it. Run
148
177
  `npm run doctor` last, and don't rerun passing suites just because doctor
149
178
  formatted files.
179
+
180
+ Class collection assignment must validate all incoming owned entries before replacing a stored row or changing its aliases. Keep caught-rejection, late-entry failure, duplicate-row, and successful retry controls in `class-collection-assignment.test.ts`.
@@ -49,6 +49,8 @@ class Foo {
49
49
  ```
50
50
 
51
51
  Their parameters are visible only in that body, never in member initializers.
52
+ A sole declared constructor accepts positional or named arguments and runs its
53
+ body in either form. Overloads require named arguments to select the constructor.
52
54
  Each declared constructor must settle every required member itself; a
53
55
  call-site block can't repair an invalid constructor.
54
56
 
@@ -41,8 +41,10 @@ pinned until reset.
41
41
  inside `new() { Year = root.Save.World.Time.Year }`.
42
42
  - Literal-only positions: dictionary keys (string literals, or option literals
43
43
  for enum keys) and Color components. Instance member defaults need numeric
44
- literal vector components; statics may compute them
45
- (`new Vector2(Probe.X, 1)`).
44
+ literal vector components, including vectors nested in stored object/list
45
+ defaults. A rejected stored component is reported at its authored location
46
+ with the containing member name. Statics may compute supported component
47
+ expressions (`new Vector2(Probe.X, 1)`).
46
48
  - Parenthesize a computed list or dictionary entry that has an `@id`:
47
49
  `@id("row") (A.B / A.C)`. Push adds these parentheses when it assigns IDs.
48
50
 
@@ -80,6 +80,12 @@ public static T? FirstOf<T extends Item = Item>(List<T> items) => items.FirstOrD
80
80
  evidence. The expected return type is not evidence. Explicit `<...>`
81
81
  never infers the omitted tail. Conflicting types need explicit arguments;
82
82
  inference does not invent a common ancestor.
83
+ - Tuple arguments infer element by element, including nested tuples; labels do
84
+ not affect inference. `(T,T)` with `(1,2.5)` infers `float`. An enclosing
85
+ invariant position, such as `List<(T,T)>`, still requires exact element
86
+ types. Nullable elements matched against `T?` contribute their non-null
87
+ type. Null literals, target-typed `new()`, and empty collections supply no
88
+ evidence, but do not discard evidence from sibling tuple elements.
83
89
  - Function type parameters take no `@id`. Overrides declare the same count,
84
90
  constraints, and defaults but may rename them.
85
91
 
@@ -6,6 +6,9 @@ conflicts and recovery, branches and releases, or Unity export.
6
6
 
7
7
  ## Pull
8
8
 
9
+ - If a push committed but local reconciliation failed, normal pull first
10
+ recovers the saved transaction without submitting it again. Stored instance
11
+ bindings also close inherited generic fields during source reconstruction.
9
12
  - Normal pull fetches only changed records and merges them three-way by
10
13
  record identity. If the remote head is unchanged it leaves source alone
11
14
  without compiling; use `neo status` for local diagnostics.
@@ -22,7 +22,11 @@ AudioClipRegistry AudioClips = new() {
22
22
 
23
23
  - `Images.Sword.Slice(0)` is a sprite; `AudioClips.SwordHit` is a clip. A bare
24
24
  `Images.Sword` is only a file ID, valid in file-valued contexts such as
25
- `SpriteInfo.FileId`.
25
+ `SpriteInfo.FileId`. Assigning it directly to `SpriteInfo` is an error;
26
+ use `.Slice(0)` to select a sprite. Status, editor validation, and export
27
+ preparation report this at the assignment, including declaration defaults
28
+ and unused top-level object initializers. Uploading the image does not make
29
+ an unsliced assignment valid.
26
30
  - Registries and binaries may sit in any non-ignored folder. Update the path
27
31
  when moving a binary.
28
32
  - Renaming the symbol or replacing bytes keeps the file ID when `@id` stays.
@@ -42,6 +42,10 @@ public Reference<int> TrackedStat; // another member's int
42
42
  - A single reference's initializer body returns one row, never a set.
43
43
  - `Reference<T>` satisfies interface `T Foo { get; }` or `{ get; set; }` and
44
44
  abstract `T Foo { get; }`.
45
+ - Reads through a base getter use its declared return type. A stored
46
+ `Reference<T>` implementing a `T` getter reads the target value, including
47
+ closed generic targets. A getter declared to return `Reference<T>` keeps
48
+ that reference, so callers can retain its identity or write through it.
45
49
  - Generated C# exposes a read-only interface; call `TryWritable` to write.
46
50
 
47
51
  ## Defaults
@@ -70,6 +70,9 @@ Rules push and the language service enforce:
70
70
  - `Base` is reserved case-insensitively; `<Class>.Variants.Base` is the class
71
71
  with no variant.
72
72
  - Names must survive C# identifier normalization.
73
+ - A selection such as `ExampleObject.Variants.Down` must name a declared
74
+ class. An unknown class is reported on that identifier in the editor; CLI
75
+ validation and export retain its authored file, line, and column.
73
76
 
74
77
  Push accepts variants in any `.neo` file. Pull writes
75
78
  `Variants/<Class>.neo` and `Variants/<Class>/<Folder path>.neo`, one file per
@@ -111,3 +114,27 @@ NeoLookupVariant<ExampleObject, NeoSortingLayer> Layered = new(
111
114
  `NeoVariantFolder` and `NeoLookupVariantFolder` are top-level records, never
112
115
  member or parameter types. Variant handles are valid as Variant members only,
113
116
  not as collection entries, lookup targets, parameters, or generic bindings.
117
+
118
+ ## Stored overrides
119
+
120
+ A stored `NeoVariant<T>` field override may keep its target or narrow it to a
121
+ descendant class. It may also remove `?`. A required override does not inherit
122
+ an optional base member's null default: supply a compatible selection on every
123
+ construction path, or declare a non-null default on the override. An inherited
124
+ non-null default must satisfy the narrowed target; replace an incompatible
125
+ default on the override. Explicit null
126
+ defaults and selections remain invalid for required members.
127
+
128
+ ```neo
129
+ class InventoryItem {
130
+ public virtual NeoVariant<PlacedItem>? Placed = null;
131
+ }
132
+ class MailboxItem : InventoryItem {
133
+ public override NeoVariant<PlacedMailboxItem> Placed;
134
+ }
135
+ ```
136
+
137
+ `PlacedMailboxItem` must derive from `PlacedItem`. A selection must satisfy the
138
+ override's target, including when it uses `Class.Variants.Base`. This rule does
139
+ not make unrelated generic wrappers covariant. Generated C# overrides retain
140
+ the inherited `NeoVariant<PlacedItem>` wrapper because that wrapper is invariant.