@neocompose/cli 0.23.2 → 0.24.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/CHANGELOG.md CHANGED
@@ -1,5 +1,44 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.24.0] - 2026-08-06
4
+
5
+ ### Added
6
+
7
+ - Add local NeoScript unit testing with colocated `*.spec.neo` files,
8
+ `neo test` file/name selection, human and JSON reporting, typed assertions,
9
+ and fail-closed native/NeoScript function mocks. Tests compile the complete
10
+ unpushed project through the same offline local-candidate preparation used
11
+ by push and keep their build metadata under `.neo/test-build/`.
12
+ - Add independent `prePushHook` and `prePushDryRunHook` commands in `neo.json`.
13
+ They run after successful local preparation but before authentication or
14
+ network activity, abort on failure, and can be bypassed explicitly with
15
+ `neo push --no-verify`.
16
+ - Add stable `neo test` process outcomes for automation: 0 for success, 1 for
17
+ test/preparation/compilation failure, 2 for usage or runner failure, and 130
18
+ for SIGINT. JSON output is written on every one of those paths when an
19
+ `--outputFile` is configured.
20
+
21
+ ### Changed
22
+
23
+ - Classify `*.spec.neo` as a fourth, test-only project-source kind shared by
24
+ CLI discovery, project analysis, Monaco, and the VS Code language server.
25
+ Specs never enter status, source identity, pull/reset, or push.
26
+ - Project discovery now shares generated/private directory exclusions and
27
+ honors applicable `.gitignore` rules.
28
+ - `neo doctor` now compiles every discovered `*.spec.neo` file against the
29
+ offline local candidate and exits nonzero for spec diagnostics. Specs remain
30
+ excluded from production push inputs, so this does not make test-source
31
+ diagnostics a push blocker.
32
+ - Neo test build artifacts use a versioned manifest, sweep abandoned temporary
33
+ writes, and enforce a 512 MiB least-recently-used cache ceiling while
34
+ protecting the candidate currently being consumed by a push hook.
35
+
36
+ ### Fixed
37
+
38
+ - Dialogue dry-runs continue treating unavailable device-native actions as
39
+ warnings after the evaluator diagnostic wording change by matching the
40
+ native-unavailable error type instead of its message text.
41
+
3
42
  ## [0.23.2] - 2026-08-06
4
43
 
5
44
  ### Fixed
package/README.md CHANGED
@@ -71,13 +71,16 @@ neo/
71
71
  DialogueGroups/
72
72
  Dialogues/*.neoflow
73
73
  Migrations/*.neo
74
+ **/*.spec.neo # colocated local-only NeoScript tests
74
75
  .neo/
75
76
  state.json # private merge/CAS bases; never hand-edit
76
77
  conflicts/
78
+ test-build/ # local test compilation metadata
77
79
  ```
78
80
 
79
- All non-hidden `.neo`, `.neoflow`, and supported managed binaries are tracked.
80
- `.neo/` is ignored private state. There is no schema `.csproj`, C# authoring
81
+ Production `.neo`, `.neoflow`, and supported managed binaries are tracked.
82
+ Colocated `.spec.neo` files are test-only: they never enter status, source
83
+ identity, pull/reset, or push. `.neo/` is ignored private state. There is no schema `.csproj`, C# authoring
81
84
  tree, Roslyn compiler, generated authoring DLL, per-function sidecar tree, or
82
85
  checked-in dialogue JSON.
83
86
 
@@ -356,6 +359,58 @@ neo files add Files/Images/Sword.png --template PixelArt
356
359
  neo dialogue new CapitolColdBoot --primary Outpost=Assets.Capitol --group CapitolDialogues
357
360
  ```
358
361
 
362
+ ## NeoScript unit tests
363
+
364
+ Place `*.spec.neo` files anywhere beside project source. They see the complete
365
+ locally prepared production graph—including unpushed declarations, values, and
366
+ function bodies—plus a test-only typed prelude. Production source never sees
367
+ test globals.
368
+
369
+ ```neo
370
+ describe("Player.TakeDamage", () => {
371
+ test("rejects negative damage", () => {
372
+ var player = new Player();
373
+ expect(() => { player.TakeDamage(-1); }).toThrow("negative");
374
+ });
375
+ });
376
+ ```
377
+
378
+ Run all tests, narrow by file/directory, or filter the full test name with a
379
+ JavaScript regular expression:
380
+
381
+ ```sh
382
+ neo test
383
+ neo test Classes/Player.spec.neo
384
+ neo test -t "TakeDamage"
385
+ neo test --reporter=json --outputFile=.neo/test-results.json
386
+ ```
387
+
388
+ The JSON output file is written atomically. Test compilation metadata lives in
389
+ `.neo/test-build/`; neither it nor test files are server records. A workspace
390
+ must have been initialized or pulled once so `.neo/state.json` contains the
391
+ offline project facts, but running tests performs no login or network request.
392
+
393
+ Native functions cannot execute in the local evaluator and therefore fail
394
+ closed unless mocked. Use `mock.native(Member)`, `mock.function(Member)`, or
395
+ `spyOn(Member)`, then configure `returns`,
396
+ `returnsOnce`, `throws`, `throwsOnce`, `doesNothing`, or `implementation`.
397
+ Mocks and call history are isolated per test.
398
+
399
+ To gate pushes, add either or both commands to `neo.json`:
400
+
401
+ ```json
402
+ {
403
+ "prePushHook": "neo test",
404
+ "prePushDryRunHook": "neo test --reporter=json --outputFile=.neo/test-results.json"
405
+ }
406
+ ```
407
+
408
+ The real-push hook is intentionally not reused for dry runs: arbitrary hook
409
+ commands may have side effects. Each applicable hook runs only after local
410
+ candidate validation and before authentication/network activity; a non-zero
411
+ exit aborts. `neo push --no-verify` is an explicit local bypass, not a server
412
+ authorization boundary.
413
+
359
414
  ## Commands
360
415
 
361
416
  | Command | Purpose |
@@ -365,7 +420,8 @@ neo dialogue new CapitolColdBoot --primary Outpost=Assets.Capitol --group Capito
365
420
  | `doctor` | Validate format/compiler/editor/source/file contracts; no .NET discovery. |
366
421
  | `pull [--force\|--reset] [--regenerate-source-names]` | Merge remote changes or regenerate canonical source, names, and binaries. |
367
422
  | `status [--json]` / `diff [--json]` | Compile source and show semantic records, spans, digests, and upload intent. |
368
- | `push [--dry-run] [--accept-bump]` | Validate or commit one atomic compare-and-swap transaction. |
423
+ | `push [--dry-run] [--accept-bump] [--no-verify]` | Validate or commit one atomic compare-and-swap transaction. |
424
+ | `test [file-or-dir ...] [-t pattern]` | Compile the unpushed local candidate and run `*.spec.neo` tests. |
369
425
  | `dev [--push]` | Watch remote/local changes; pushing remains opt-in. |
370
426
  | `resolve --mine\|--theirs` | Resolve all current source/binary conflicts with one side. |
371
427
  | `class new` / `value new` / `files add` / `dialogue new` | Create pending native source scaffolds. |