@neocompose/cli 0.56.0 → 0.57.0

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.56.0",
3
+ "version": "0.57.0",
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.56.0 -->
12
+ <!-- reviewed-through-cli: 0.57.0 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -42,7 +42,10 @@ Those are not part of format 4.
42
42
  materialization and whole-graph validation — against the pulled document,
43
43
  without prompting, uploading, committing, or rewriting the checkout. Pull
44
44
  once with the installed CLI so the workspace carries compatible
45
- derived-edge extractor metadata.
45
+ derived-edge extractor metadata. Pending getters and functions compile before
46
+ local initializer evaluation, including on a project's first push. Initializers
47
+ resolve pending value dependencies before their consumers; cyclic dependencies
48
+ report the participating values.
46
49
  6. Push one reviewed atomic change with `neo push`.
47
50
  Completion arrives through a live subscription. Progress counts refresh every
48
51
  five seconds while the durable job runs; a disconnect does not cancel it.
@@ -97,7 +97,7 @@ wrappers.
97
97
  The marker near the top of `SKILL.md` must exactly match the package version:
98
98
 
99
99
  ```html
100
- <!-- reviewed-through-cli: 0.56.0 -->
100
+ <!-- reviewed-through-cli: 0.57.0 -->
101
101
  ```
102
102
 
103
103
  The quoted version above is checked too, so this instruction cannot go stale
@@ -201,8 +201,9 @@ it is reset.
201
201
  Operator expressions are valid member defaults and store as computed
202
202
  initializers, the same way calls do — `public float Derived =
203
203
  Flags.Start / Flags.Scale;` is fine. Positions that store no rows still
204
- require literals: dictionary keys must be string literals and Vector/Color
205
- components must be numeric literals. When a computed list or dictionary entry
204
+ require literals: dictionary keys must be string literals or enum option
205
+ literals for enum-keyed dictionaries, and Vector/Color components must be numeric
206
+ literals. When a computed list or dictionary entry
206
207
  carries an authored `@id`, parenthesize the expression — `@id("row")
207
208
  (A.B / A.C)` — so the annotation names the row rather than its left operand.
208
209
 
@@ -271,8 +271,28 @@ foreach (var item in root.Save.Items) {
271
271
 
272
272
  A `foreach` receiver must be non-null. It snapshots membership/order once at
273
273
  entry, so adding/removing collection rows does not alter the scheduled
274
- iterations. Dictionary iteration binds values, not keys. The iterator binding
275
- is read-only, although writes through a writable entry remain valid.
274
+ iterations. `foreach (var value in dictionary)` binds each value. To read keys
275
+ as well, deconstruct a dictionary entry:
276
+
277
+ ```neo
278
+ foreach (var (key, value) in this.Damage) {
279
+ if (key == ToolType.Pickaxe) {
280
+ ApplyDamage(value);
281
+ }
282
+ }
283
+
284
+ foreach ((ToolType key, float value) in this.Damage) {
285
+ ApplyDamage(value);
286
+ }
287
+ ```
288
+
289
+ Deconstruction accepts a dictionary local or member path. Assign a computed
290
+ receiver to a local first. It snapshots keys once at loop entry and reads each
291
+ value through `dictionary[key]`; removing a key follows the normal missing-key
292
+ read behavior. Both bindings are read-only, although writes through a writable
293
+ entry remain valid. Enum-keyed dictionaries yield enum keys, including in
294
+ collection lambdas such as `Where((key, value) => key == ToolType.Pickaxe)`
295
+ and `Select((key, value) => key)`. String-keyed dictionaries yield strings.
276
296
 
277
297
  Use `break` for the nearest loop or switch and `continue` for the nearest
278
298
  loop. A `continue` inside a switch nested in a loop continues the loop.
@@ -44,6 +44,17 @@ class Assets {
44
44
 
45
45
  A computed static getter is an alias; it creates neither a binding nor a row.
46
46
 
47
+ Enum-keyed dictionaries accept contextual or qualified option keys in defaults
48
+ and stored values:
49
+
50
+ ```neo
51
+ Dictionary<ToolType, float> Damage = { .Pickaxe: 10, ToolType.Axe: 2 };
52
+ ```
53
+
54
+ Pull writes `.Option` for known keys. A quoted raw option ID is also accepted;
55
+ a quoted option name such as `"Pickaxe"` is not an ID. Pull preserves orphaned
56
+ keys as quoted IDs when their option has been deleted.
57
+
47
58
  ## Identity rules
48
59
 
49
60
  Preserve every existing ID through rename, reorder, and file moves. For a new