@neocompose/cli 0.4.0 → 0.5.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.
Files changed (168) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +335 -197
  3. package/dist/neo.mjs +47100 -32069
  4. package/package.json +6 -4
  5. package/skills/neocompose-cli/SKILL.md +490 -296
  6. package/dist/tooling/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  7. package/dist/tooling/Microsoft.CodeAnalysis.dll +0 -0
  8. package/dist/tooling/NeoCompose.Schema.Tooling.dll +0 -0
  9. package/dist/tooling/NeoCompose.Schema.Tooling.pdb +0 -0
  10. package/dist/tooling/NeoCompose.Schema.dll +0 -0
  11. package/dist/tooling/NeoCompose.Schema.pdb +0 -0
  12. package/dist/tooling/NeoCompose.Schema.xml +0 -1127
  13. package/dist/tooling/NeoCompose.SchemaCompiler.deps.json +0 -299
  14. package/dist/tooling/NeoCompose.SchemaCompiler.dll +0 -0
  15. package/dist/tooling/NeoCompose.SchemaCompiler.pdb +0 -0
  16. package/dist/tooling/NeoCompose.SchemaCompiler.runtimeconfig.json +0 -13
  17. package/dist/tooling/System.Collections.Immutable.dll +0 -0
  18. package/dist/tooling/System.Reflection.Metadata.dll +0 -0
  19. package/dist/tooling/System.Text.Encoding.CodePages.dll +0 -0
  20. package/dist/tooling/cs/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  21. package/dist/tooling/cs/Microsoft.CodeAnalysis.resources.dll +0 -0
  22. package/dist/tooling/de/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  23. package/dist/tooling/de/Microsoft.CodeAnalysis.resources.dll +0 -0
  24. package/dist/tooling/es/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  25. package/dist/tooling/es/Microsoft.CodeAnalysis.resources.dll +0 -0
  26. package/dist/tooling/fr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  27. package/dist/tooling/fr/Microsoft.CodeAnalysis.resources.dll +0 -0
  28. package/dist/tooling/it/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  29. package/dist/tooling/it/Microsoft.CodeAnalysis.resources.dll +0 -0
  30. package/dist/tooling/ja/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  31. package/dist/tooling/ja/Microsoft.CodeAnalysis.resources.dll +0 -0
  32. package/dist/tooling/ko/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  33. package/dist/tooling/ko/Microsoft.CodeAnalysis.resources.dll +0 -0
  34. package/dist/tooling/pl/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  35. package/dist/tooling/pl/Microsoft.CodeAnalysis.resources.dll +0 -0
  36. package/dist/tooling/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  37. package/dist/tooling/pt-BR/Microsoft.CodeAnalysis.resources.dll +0 -0
  38. package/dist/tooling/reference-assemblies/netstandard2.1/Microsoft.Win32.Primitives.dll +0 -0
  39. package/dist/tooling/reference-assemblies/netstandard2.1/System.AppContext.dll +0 -0
  40. package/dist/tooling/reference-assemblies/netstandard2.1/System.Buffers.dll +0 -0
  41. package/dist/tooling/reference-assemblies/netstandard2.1/System.Collections.Concurrent.dll +0 -0
  42. package/dist/tooling/reference-assemblies/netstandard2.1/System.Collections.NonGeneric.dll +0 -0
  43. package/dist/tooling/reference-assemblies/netstandard2.1/System.Collections.Specialized.dll +0 -0
  44. package/dist/tooling/reference-assemblies/netstandard2.1/System.Collections.dll +0 -0
  45. package/dist/tooling/reference-assemblies/netstandard2.1/System.ComponentModel.Composition.dll +0 -0
  46. package/dist/tooling/reference-assemblies/netstandard2.1/System.ComponentModel.EventBasedAsync.dll +0 -0
  47. package/dist/tooling/reference-assemblies/netstandard2.1/System.ComponentModel.Primitives.dll +0 -0
  48. package/dist/tooling/reference-assemblies/netstandard2.1/System.ComponentModel.TypeConverter.dll +0 -0
  49. package/dist/tooling/reference-assemblies/netstandard2.1/System.ComponentModel.dll +0 -0
  50. package/dist/tooling/reference-assemblies/netstandard2.1/System.Console.dll +0 -0
  51. package/dist/tooling/reference-assemblies/netstandard2.1/System.Core.dll +0 -0
  52. package/dist/tooling/reference-assemblies/netstandard2.1/System.Data.Common.dll +0 -0
  53. package/dist/tooling/reference-assemblies/netstandard2.1/System.Data.dll +0 -0
  54. package/dist/tooling/reference-assemblies/netstandard2.1/System.Diagnostics.Contracts.dll +0 -0
  55. package/dist/tooling/reference-assemblies/netstandard2.1/System.Diagnostics.Debug.dll +0 -0
  56. package/dist/tooling/reference-assemblies/netstandard2.1/System.Diagnostics.FileVersionInfo.dll +0 -0
  57. package/dist/tooling/reference-assemblies/netstandard2.1/System.Diagnostics.Process.dll +0 -0
  58. package/dist/tooling/reference-assemblies/netstandard2.1/System.Diagnostics.StackTrace.dll +0 -0
  59. package/dist/tooling/reference-assemblies/netstandard2.1/System.Diagnostics.TextWriterTraceListener.dll +0 -0
  60. package/dist/tooling/reference-assemblies/netstandard2.1/System.Diagnostics.Tools.dll +0 -0
  61. package/dist/tooling/reference-assemblies/netstandard2.1/System.Diagnostics.TraceSource.dll +0 -0
  62. package/dist/tooling/reference-assemblies/netstandard2.1/System.Diagnostics.Tracing.dll +0 -0
  63. package/dist/tooling/reference-assemblies/netstandard2.1/System.Drawing.Primitives.dll +0 -0
  64. package/dist/tooling/reference-assemblies/netstandard2.1/System.Drawing.dll +0 -0
  65. package/dist/tooling/reference-assemblies/netstandard2.1/System.Dynamic.Runtime.dll +0 -0
  66. package/dist/tooling/reference-assemblies/netstandard2.1/System.Globalization.Calendars.dll +0 -0
  67. package/dist/tooling/reference-assemblies/netstandard2.1/System.Globalization.Extensions.dll +0 -0
  68. package/dist/tooling/reference-assemblies/netstandard2.1/System.Globalization.dll +0 -0
  69. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.Compression.FileSystem.dll +0 -0
  70. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.Compression.ZipFile.dll +0 -0
  71. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.Compression.dll +0 -0
  72. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.FileSystem.DriveInfo.dll +0 -0
  73. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.FileSystem.Primitives.dll +0 -0
  74. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.FileSystem.Watcher.dll +0 -0
  75. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.FileSystem.dll +0 -0
  76. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.IsolatedStorage.dll +0 -0
  77. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.MemoryMappedFiles.dll +0 -0
  78. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.Pipes.dll +0 -0
  79. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.UnmanagedMemoryStream.dll +0 -0
  80. package/dist/tooling/reference-assemblies/netstandard2.1/System.IO.dll +0 -0
  81. package/dist/tooling/reference-assemblies/netstandard2.1/System.Linq.Expressions.dll +0 -0
  82. package/dist/tooling/reference-assemblies/netstandard2.1/System.Linq.Parallel.dll +0 -0
  83. package/dist/tooling/reference-assemblies/netstandard2.1/System.Linq.Queryable.dll +0 -0
  84. package/dist/tooling/reference-assemblies/netstandard2.1/System.Linq.dll +0 -0
  85. package/dist/tooling/reference-assemblies/netstandard2.1/System.Memory.dll +0 -0
  86. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.Http.dll +0 -0
  87. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.NameResolution.dll +0 -0
  88. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.NetworkInformation.dll +0 -0
  89. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.Ping.dll +0 -0
  90. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.Primitives.dll +0 -0
  91. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.Requests.dll +0 -0
  92. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.Security.dll +0 -0
  93. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.Sockets.dll +0 -0
  94. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.WebHeaderCollection.dll +0 -0
  95. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.WebSockets.Client.dll +0 -0
  96. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.WebSockets.dll +0 -0
  97. package/dist/tooling/reference-assemblies/netstandard2.1/System.Net.dll +0 -0
  98. package/dist/tooling/reference-assemblies/netstandard2.1/System.Numerics.Vectors.dll +0 -0
  99. package/dist/tooling/reference-assemblies/netstandard2.1/System.Numerics.dll +0 -0
  100. package/dist/tooling/reference-assemblies/netstandard2.1/System.ObjectModel.dll +0 -0
  101. package/dist/tooling/reference-assemblies/netstandard2.1/System.Reflection.DispatchProxy.dll +0 -0
  102. package/dist/tooling/reference-assemblies/netstandard2.1/System.Reflection.Emit.ILGeneration.dll +0 -0
  103. package/dist/tooling/reference-assemblies/netstandard2.1/System.Reflection.Emit.Lightweight.dll +0 -0
  104. package/dist/tooling/reference-assemblies/netstandard2.1/System.Reflection.Emit.dll +0 -0
  105. package/dist/tooling/reference-assemblies/netstandard2.1/System.Reflection.Extensions.dll +0 -0
  106. package/dist/tooling/reference-assemblies/netstandard2.1/System.Reflection.Primitives.dll +0 -0
  107. package/dist/tooling/reference-assemblies/netstandard2.1/System.Reflection.dll +0 -0
  108. package/dist/tooling/reference-assemblies/netstandard2.1/System.Resources.Reader.dll +0 -0
  109. package/dist/tooling/reference-assemblies/netstandard2.1/System.Resources.ResourceManager.dll +0 -0
  110. package/dist/tooling/reference-assemblies/netstandard2.1/System.Resources.Writer.dll +0 -0
  111. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.CompilerServices.VisualC.dll +0 -0
  112. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.Extensions.dll +0 -0
  113. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.Handles.dll +0 -0
  114. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.InteropServices.RuntimeInformation.dll +0 -0
  115. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.InteropServices.dll +0 -0
  116. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.Numerics.dll +0 -0
  117. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.Serialization.Formatters.dll +0 -0
  118. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.Serialization.Json.dll +0 -0
  119. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.Serialization.Primitives.dll +0 -0
  120. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.Serialization.Xml.dll +0 -0
  121. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.Serialization.dll +0 -0
  122. package/dist/tooling/reference-assemblies/netstandard2.1/System.Runtime.dll +0 -0
  123. package/dist/tooling/reference-assemblies/netstandard2.1/System.Security.Claims.dll +0 -0
  124. package/dist/tooling/reference-assemblies/netstandard2.1/System.Security.Cryptography.Algorithms.dll +0 -0
  125. package/dist/tooling/reference-assemblies/netstandard2.1/System.Security.Cryptography.Csp.dll +0 -0
  126. package/dist/tooling/reference-assemblies/netstandard2.1/System.Security.Cryptography.Encoding.dll +0 -0
  127. package/dist/tooling/reference-assemblies/netstandard2.1/System.Security.Cryptography.Primitives.dll +0 -0
  128. package/dist/tooling/reference-assemblies/netstandard2.1/System.Security.Cryptography.X509Certificates.dll +0 -0
  129. package/dist/tooling/reference-assemblies/netstandard2.1/System.Security.Principal.dll +0 -0
  130. package/dist/tooling/reference-assemblies/netstandard2.1/System.Security.SecureString.dll +0 -0
  131. package/dist/tooling/reference-assemblies/netstandard2.1/System.ServiceModel.Web.dll +0 -0
  132. package/dist/tooling/reference-assemblies/netstandard2.1/System.Text.Encoding.Extensions.dll +0 -0
  133. package/dist/tooling/reference-assemblies/netstandard2.1/System.Text.Encoding.dll +0 -0
  134. package/dist/tooling/reference-assemblies/netstandard2.1/System.Text.RegularExpressions.dll +0 -0
  135. package/dist/tooling/reference-assemblies/netstandard2.1/System.Threading.Overlapped.dll +0 -0
  136. package/dist/tooling/reference-assemblies/netstandard2.1/System.Threading.Tasks.Extensions.dll +0 -0
  137. package/dist/tooling/reference-assemblies/netstandard2.1/System.Threading.Tasks.Parallel.dll +0 -0
  138. package/dist/tooling/reference-assemblies/netstandard2.1/System.Threading.Tasks.dll +0 -0
  139. package/dist/tooling/reference-assemblies/netstandard2.1/System.Threading.Thread.dll +0 -0
  140. package/dist/tooling/reference-assemblies/netstandard2.1/System.Threading.ThreadPool.dll +0 -0
  141. package/dist/tooling/reference-assemblies/netstandard2.1/System.Threading.Timer.dll +0 -0
  142. package/dist/tooling/reference-assemblies/netstandard2.1/System.Threading.dll +0 -0
  143. package/dist/tooling/reference-assemblies/netstandard2.1/System.Transactions.dll +0 -0
  144. package/dist/tooling/reference-assemblies/netstandard2.1/System.ValueTuple.dll +0 -0
  145. package/dist/tooling/reference-assemblies/netstandard2.1/System.Web.dll +0 -0
  146. package/dist/tooling/reference-assemblies/netstandard2.1/System.Windows.dll +0 -0
  147. package/dist/tooling/reference-assemblies/netstandard2.1/System.Xml.Linq.dll +0 -0
  148. package/dist/tooling/reference-assemblies/netstandard2.1/System.Xml.ReaderWriter.dll +0 -0
  149. package/dist/tooling/reference-assemblies/netstandard2.1/System.Xml.Serialization.dll +0 -0
  150. package/dist/tooling/reference-assemblies/netstandard2.1/System.Xml.XDocument.dll +0 -0
  151. package/dist/tooling/reference-assemblies/netstandard2.1/System.Xml.XPath.XDocument.dll +0 -0
  152. package/dist/tooling/reference-assemblies/netstandard2.1/System.Xml.XPath.dll +0 -0
  153. package/dist/tooling/reference-assemblies/netstandard2.1/System.Xml.XmlDocument.dll +0 -0
  154. package/dist/tooling/reference-assemblies/netstandard2.1/System.Xml.XmlSerializer.dll +0 -0
  155. package/dist/tooling/reference-assemblies/netstandard2.1/System.Xml.dll +0 -0
  156. package/dist/tooling/reference-assemblies/netstandard2.1/System.dll +0 -0
  157. package/dist/tooling/reference-assemblies/netstandard2.1/mscorlib.dll +0 -0
  158. package/dist/tooling/reference-assemblies/netstandard2.1/netstandard.dll +0 -0
  159. package/dist/tooling/ru/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  160. package/dist/tooling/ru/Microsoft.CodeAnalysis.resources.dll +0 -0
  161. package/dist/tooling/runtimes/win/lib/net6.0/System.Text.Encoding.CodePages.dll +0 -0
  162. package/dist/tooling/schema-contract.json +0 -23
  163. package/dist/tooling/tr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  164. package/dist/tooling/tr/Microsoft.CodeAnalysis.resources.dll +0 -0
  165. package/dist/tooling/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  166. package/dist/tooling/zh-Hans/Microsoft.CodeAnalysis.resources.dll +0 -0
  167. package/dist/tooling/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  168. package/dist/tooling/zh-Hant/Microsoft.CodeAnalysis.resources.dll +0 -0
@@ -1,267 +1,470 @@
1
1
  ---
2
2
  name: neocompose-cli
3
3
  description: >-
4
- Edit and synchronize a Neo Compose format-v3 schema as real C# 11 plus
5
- tracked NeoScript sidecars. Use for classes, interfaces, members,
6
- enums, templates, localization, schema-aware NeoScript, or batch content
7
- edits. The working copy is a neo/ directory; run `neo` from the published
8
- package or `node cli/bin/neo.mjs` in the web repository.
4
+ Edit and synchronize a Neo Compose format-4 project as native .neo and
5
+ .neoflow source plus tracked image/audio files. Use for classes, interfaces,
6
+ enums, members, values, templates, localization, dialogue flows, files,
7
+ migrations, NeoScript, or batch content edits. The working copy is a neo/
8
+ directory; run `neo` from the published package or `node cli/bin/neo.mjs` in
9
+ the web repository.
9
10
  ---
10
11
 
11
- # Neo Compose schema-as-code CLI (`neo`)
12
+ # Neo Compose native project-source CLI (`neo`)
12
13
 
13
- A `neo/` working copy is a Git-like checkout of one Neo Compose project
14
- version. C# and NeoScript are peer authoring surfaces beside the web UI; the
15
- server remains the shared source of truth. The current contract is format v3
16
- and is documented in `specs/schema-as-code-cli.md`.
14
+ A format-4 `neo/` working copy is a Git-like checkout of one Neo Compose
15
+ project version. Native `.neo`/`.neoflow` source and the web UI are peer
16
+ authoring surfaces over the same granular records; the server remains the
17
+ shared source of truth. The complete contract is
18
+ `specs/neo-project-source-authoring.md`.
19
+
20
+ There is no C# schema project, Roslyn compiler, authoring DLL, .NET discovery,
21
+ generated SDK, per-member script sidecar tree, `ValueRegistry`, or checked-in
22
+ dialogue JSON source format.
17
23
 
18
24
  ## Non-negotiable workflow
19
25
 
20
- 1. Run `neo pull` before editing and before pushing after time has passed.
21
- 2. Edit real C# 11 and the tracked `.neo` sidecars. Never edit `.neo/state.json`
22
- or `.neo/tooling`.
23
- 3. Run `neo status` or `neo diff`, then `neo push --dry-run`.
24
- 4. Run `neo script check --all` after a schema rename or signature change.
26
+ 1. Run `neo pull` before editing and again before pushing after time has passed.
27
+ 2. Edit tracked `.neo`, `.neoflow`, and managed binary files. Never edit
28
+ `.neo/state.json`, analysis caches, or `.neo/conflicts` as source.
29
+ 3. Run `neo status` and `neo diff`; inspect every change, including changes
30
+ already present when the task began.
31
+ 4. Run `neo dialogue dryrun <ref>` after dialogue changes and
32
+ `neo push --dry-run` before every real push.
25
33
  5. Push one reviewed atomic change with `neo push`.
26
34
 
27
- **Pull followed immediately by status/push must be a no-op.** If it reports
28
- schema changes, stop and report a round-trip bug rather than pushing it.
35
+ **Pull followed immediately by status or push dry-run must be a semantic
36
+ no-op.** If it reports project changes, stop and report a round-trip bug rather
37
+ than pushing it.
29
38
 
30
- The compiler reports file:line:column diagnostics and never guesses. Unknown
31
- authorable server fields fail with “CLI contract upgrade required”; they never
32
- hide in an opaque JSON carrier.
39
+ The compiler reports file:line:column diagnostics and fails closed. Unknown
40
+ authorable server fields require a CLI contract upgrade; never preserve them
41
+ through opaque JSON or guessed syntax.
33
42
 
34
- ## Setup and format requirement
43
+ ## Setup and clean-break format
35
44
 
36
45
  ```sh
37
- npm i -g @neocompose/cli@0.3.0
46
+ npm i -g @neocompose/cli
38
47
  neo login [--api <url>] [--profile editor|release] [--save-project <id>]
39
48
  neo init --project <id> [--version <id>] [--dir neo]
40
49
  neo doctor
41
50
  ```
42
51
 
43
- Repository development uses `node cli/bin/neo.mjs`. Agents should always pass
44
- explicit flags/IDs. Human terminals may show pickers and confirms; non-TTY/CI
45
- use fails with an actionable missing-flag diagnostic rather than blocking.
52
+ Repository development uses `node cli/bin/neo.mjs`. Agents should pass
53
+ explicit flags and IDs. Interactive terminals may show pickers and confirms;
54
+ non-TTY/CI operation must never wait for input.
46
55
 
47
- `neo.json` must contain `formatVersion: 3`. Format 2 and every other marker are
48
- unsupported. There is no upgrader or compatibility reader. Preserve any source
49
- you need, then refresh a format-3 working copy from the authoritative server:
56
+ `neo.json` must contain `formatVersion: 4`. The compiler has no format-3 C#
57
+ reader or upgrader. Push intended format-3 edits with the old CLI, preserve
58
+ any local source needed for reference, then reconstruct authoritative records:
50
59
 
51
60
  ```sh
52
61
  neo init --project <id> [--version <id>] [--dir neo]
53
62
  ```
54
63
 
55
- `neo pull --reset` is only for an existing schema workspace; it reconstructs
56
- CLI-managed source from the server and refreshes the compiler SDK and analyzer.
57
-
58
- Neo never downloads or installs .NET. Compiler host discovery is:
59
-
60
- 1. explicit `NEO_DOTNET_HOST`;
61
- 2. a compatible Unity 6000 runtime;
62
- 3. a compatible system `dotnet`.
64
+ For an existing format-4 workspace, `neo pull --reset` regenerates canonical
65
+ source and managed binaries. `neo pull --force` discards local edits in favor
66
+ of the server. Use neither casually.
63
67
 
64
- The validated selection is cached under `.neo`; `neo doctor` reports its
65
- path, kind, runtime/Unity version, cache status, and compiler/SDK contract
66
- compatibility. An invalid explicit override is a hard error.
68
+ Neo never installs, discovers, or requires .NET. `neo doctor` validates the
69
+ format-4 browser compiler, VS Code analysis contract/cache, source bundle, and
70
+ managed-file capabilities.
67
71
 
68
72
  In Unity projects, `neo.json` may use `unityConfigPath` instead of
69
73
  `projectId`/`versionId`. The referenced `NeoComposeConfig.asset` is then the
70
- single source of truth, and branch switches update it. Never duplicate the IDs
71
- in `neo.json` in this mode.
74
+ single source of truth, and branch/version switches update it. Do not duplicate
75
+ the IDs in `neo.json` in this mode.
72
76
 
73
77
  ## Working-copy layout
74
78
 
75
79
  ```text
76
80
  neo/
77
81
  neo.json
78
- NeoCompose.Schema.csproj # netstandard2.1, C# 11, IDE-only
79
- Classes/ # schema classes
80
- Interfaces/ # interface declarations
82
+ Project.neo
83
+ Root.neo
84
+ Classes/
85
+ Interfaces/
81
86
  Enums/
82
- Root.cs # [NeoRegistry] roots and loose members
83
- Templates/ # typed texture/audio settings
84
- Localization.cs # typed localization settings
85
- LocalizationStatuses/*.cs # typed localization workflow statuses
86
- Scripts/<Class>/<Member>.neo # computed properties and NeoScript methods
87
+ Relations.neo
88
+ Templates/
89
+ Localization.neo
90
+ LocalizationStatuses/
91
+ Files/
92
+ Images.neo
93
+ AudioClips.neo
94
+ Images/
95
+ AudioClips/
96
+ DialogueGroups/
97
+ Dialogues/*.neoflow
87
98
  Migrations/*.neo
88
99
  .neo/
89
- state.json # bases/CAS hashes; never hand-edit
90
- dotnet-host.json
91
- tooling/ # bundled SDK, analyzer, generator, compiler
100
+ state.json
101
+ conflicts/
102
+ ```
103
+
104
+ All non-hidden `.neo`, `.neoflow`, and supported managed binaries are tracked.
105
+ `.neo/` is ignored private state. Normal pull preserves declaration placement
106
+ and spelling by stable ID when possible. Reset may regroup source into the
107
+ canonical layout.
108
+
109
+ ## Native project declarations
110
+
111
+ Classes, interfaces, and enums are legal only at the top level of definition
112
+ `.neo` files. Do not declare them inside another type, function, accessor,
113
+ lambda, initializer, migration, or `.neoflow`. A `.neoflow` file has the one
114
+ deliberate exception described below.
115
+
116
+ Use the shared typed declaration grammar for every top-level project object:
117
+
118
+ ```neo
119
+ Type Name = expression;
120
+ Type Name = new(arguments) {
121
+ // Typed owned declarations supported by Type.
122
+ }
92
123
  ```
93
124
 
94
- The schema project is not referenced by the game. `.neo/`, `bin/`, and `obj/`
95
- are gitignored; source and scripts are tracked.
96
-
97
- ## Authoring real C#
98
-
99
- Native C# carries native meaning:
100
-
101
- - Plain, `virtual`, `abstract`, and `override` members map directly to schema
102
- behavior. An override's base record identity comes from the resolved symbol.
103
- - Base classes, interfaces, generic parameters/arguments, and `where`
104
- constraints use ordinary syntax.
105
- - Property type determines Neo kind; nullable annotation determines whether it
106
- is optional; initializer determines its default.
107
- - Declaration order determines schema/enum order unless an explicit typed
108
- ordering attribute is present.
109
- - Method parameters and return type are the function signature.
110
- `Task`/`Task<T>` means deferred execution.
111
- - A C# `static` property or method is class-owned. Stored static properties use
112
- one replaceable binding and are excluded from instance construction;
113
- receiver kind cannot be changed in place.
114
- - Concrete `[NeoScript]`/`[NeoFunction]` methods are C# 11 partial
115
- declarations. The bundled source generator adds inert compile-only bodies.
116
- Abstract functions are ordinary abstract methods.
117
-
118
- ```csharp
119
- using System.Collections.Generic;
120
- using System.Threading.Tasks;
121
- using NeoCompose.Schema;
122
-
123
- [NeoEnum("enum-item-type")]
124
- public enum ItemType
125
- {
126
- [NeoEnumOption("option-food", Text = "Food")]
127
- Food,
125
+ There are no lowercase record-kind declaration keywords such as `project`,
126
+ `values`, `files`, or `relations`.
127
+
128
+ Schema identifiers are persisted names; there is no separate technical/display
129
+ name. `@id` preserves stable persisted identity. Keep assigned IDs through
130
+ rename, reorder, and file moves. Omit an ID only to create a record: a
131
+ successful real push assigns it and canonically inserts the annotation.
132
+ Dry-run, validation failure, upload failure, and CAS failure leave tracked
133
+ source unchanged.
134
+
135
+ ```neo
136
+ @id("enum-item-rarity-id")
137
+ enum ItemRarity {
138
+ @id("rarity-common-id")
139
+ Common = "Common text",
128
140
  }
129
141
 
130
- [NeoSchemaClass("class-inventory-item", AllowedStorage = NeoAllowedStorage.Immutable)]
131
- [NeoSchemaOrder(nameof(Name), nameof(Type), nameof(Tags), nameof(UsePrimary))]
132
- public abstract partial class InventoryItem<
133
- [NeoId("generic-stack")] TStack>
134
- where TStack : class
135
- {
136
- [NeoMember("member-name"), NeoText(SearchKey = true)]
137
- public virtual string Name { get; init; } = "";
138
-
139
- [NeoMember("member-type")]
140
- public abstract ItemType Type { get; init; }
141
-
142
- [NeoMember("member-tags"), NeoList(Kind = NeoListKind.Unordered)]
143
- [NeoEntries(nameof(TagEntries))]
144
- public virtual IReadOnlyList<string> Tags { get; init; } = new List<string>();
145
-
146
- private static readonly NeoEntrySettings[] TagEntries =
147
- {
148
- new()
149
- {
150
- Id = "entry-tag",
151
- Path = "[]",
152
- Kind = NeoEntryKind.String,
153
- Text = new NeoTextSettings { Localizable = false },
154
- },
142
+ @id("interface-named-id")
143
+ interface INamed {
144
+ @id("named-name-id")
145
+ string Name { get; }
146
+
147
+ @id("named-use-id")
148
+ void Use(SomeClass context);
149
+ }
150
+
151
+ @id("class-inventory-item-id")
152
+ @storage(allowed: .Immutable)
153
+ abstract class InventoryItem<
154
+ @id("inventory-context-generic-id")
155
+ TContext extends SomeClass
156
+ > : INamed {
157
+ @id("item-name-id")
158
+ @settings(localizable: true, searchKey: true)
159
+ virtual string Name = "";
160
+
161
+ @id("item-rarity-id")
162
+ abstract ItemRarity Rarity;
163
+
164
+ @id("item-stack-size-id")
165
+ @settings(min: 1, max: 999)
166
+ int StackSize = 1;
167
+
168
+ @id("item-display-name-id")
169
+ string DisplayName {
170
+ get {
171
+ return $"{Name} ({Rarity})";
172
+ }
173
+ }
174
+
175
+ @id("item-use-id")
176
+ abstract void Use(TContext context);
177
+
178
+ @id("item-load-id")
179
+ native async bool Load(TContext context);
180
+ }
181
+ ```
182
+
183
+ - Plain, `virtual`, `abstract`, and `override` declarations carry their native
184
+ meaning.
185
+ - Interfaces are non-generic. Class generics and constraints use ordinary Neo
186
+ syntax; do not put `@id` on inferred list/dictionary type entries.
187
+ - Field type and nullability determine member kind and optionality; the
188
+ initializer is the default.
189
+ - Inline getters, setters, and implemented functions are NeoScript. A bodyless
190
+ function must be `abstract`, `native`, or an interface contract. `async`
191
+ alone does not make a bodyless function valid.
192
+ - `@settings(...)` and `@storage(...)` are context-aware typed contracts.
193
+ Numeric limits are numeric literals. A class supports only
194
+ `@storage(allowed: ...)`; storage keys are member-only.
195
+ - Keep focused annotations such as `@locked`, `@system`, and `@relations`
196
+ separate from contextual settings.
197
+ - `.EnumCase` works only when one expected enum type is known. Use explicit
198
+ `EnumType.Case` when context is ambiguous.
199
+ - Defaults and settings must be statically analyzable. Project source is parsed
200
+ and compiled, never executed to discover declarations.
201
+
202
+ `@relations(...)` belongs on the source class for specialized direct
203
+ relations. `Relations.neo` holds generic project relations as typed top-level
204
+ declarations. Structurally owned descriptors and concrete generic bindings
205
+ derive their identities from stable owner roles; do not invent `@id`
206
+ annotations for them.
207
+
208
+ ## Root and authored values
209
+
210
+ `Root.neo` contains a compiler-owned envelope of this form:
211
+
212
+ ```neo
213
+ // Root member declarations are read only. Their values are editable.
214
+
215
+ Root root = new() {
216
+ @id("root-assets-member-id")
217
+ @locked
218
+ @storage(allowed: .Immutable)
219
+ Assets Assets =
220
+ @id("assets-root-value-id")
221
+ new() {
222
+ Outposts = [Assets.Capitol],
155
223
  };
156
224
 
157
- [NeoMember("function-use-primary"), NeoScript]
158
- public virtual partial Task<bool> UsePrimary(InventoryItem<TStack> target);
225
+ @id("root-save-member-id")
226
+ @locked
227
+ @storage(allowed: .Save)
228
+ Save Save =
229
+ @id("save-root-value-id")
230
+ new();
231
+
232
+ @id("root-session-member-id")
233
+ @locked
234
+ @storage(allowed: .Session)
235
+ Session Session =
236
+ @id("session-root-value-id")
237
+ new();
159
238
  }
160
239
  ```
161
240
 
162
- Stable IDs are visible in `[NeoSchemaClass]`, `[NeoInterface]`, `[NeoEnum]`,
163
- `[NeoEnumOption]`, `[NeoId]`, and `[NeoMember]`. Omit a nullable positional ID
164
- only when creating a record; a successful push assigns it and canonically
165
- rewrites the source. Once assigned, preserve it through renames.
166
-
167
- `[NeoMember]` owns identity/common options. Use narrow typed attributes for
168
- Neo behavior: `NeoText`, `NeoNumber`, `NeoDictionary`, `NeoList`, `NeoEntries`,
169
- `NeoIndex`, `NeoColumn`, `NeoLookup`, `NeoDialogue`, `NeoFile`, `NeoComputed`,
170
- `NeoScript`, `NeoFunction`, `NeoSystem`, and explicit schema/generic binding
171
- attributes. Use the typed settings classes for nested entries, template import
172
- options, localization, and system metadata. This is intentional: every valid
173
- option should appear in C# IntelliSense.
174
-
175
- A bodyless `[NeoComputed]` property needs no initializer or `#pragma`. The
176
- bundled analyzer suppresses only its sidecar-backed `CS8618`; ordinary nullable
177
- warnings remain enabled.
178
-
179
- Allowed values are statically analyzable literals, enum values, `nameof`,
180
- `typeof`, arrays/collections, object initializers, approved Neo value types,
181
- and `Neo.Ref<T>`, `Neo.Lookup<T>`, `Neo.Dialogue`, `Neo.Sprite`, `Neo.Audio`,
182
- or `Neo.Member` references. Authored code is never executed.
183
-
184
- Never introduce opaque carriers or identity escapes: `ExtraJson`, `DefaultJson`,
185
- `RetJson`, `ArgsJson`, `EntryChainJson`, `SchemaKeyOrderJson`,
186
- `GenericParamIds`, `ChainJson`, `SignatureJson`, `ExtendsId`, `isVirtual`, or
187
- `isAbstract`.
188
-
189
- Define each localization workflow status in
190
- `LocalizationStatuses/<Name>.cs` using `[NeoLocalizationStatus("stable-id")]`
191
- and a static `NeoLocalizationStatusSettings` object. The marker owns identity;
192
- typed properties cover slug, display metadata, archive state, transition
193
- rules, automatic transitions, and system restrictions. Keep the order in
194
- `NeoLocalizationSettings.StatusIds`.
195
-
196
- ## NeoScript sidecars
197
-
198
- Scripted member bodies live at exactly
199
- `Scripts/<DeclaringClass>/<Member>.neo`.
200
-
201
- A computed property uses one complete contextual file. The outer signature
202
- matches the linked C# declaration's semantic result (`Task<T>` functions use
203
- `T`) and adds the implicit `this` and `root` execution parameters:
204
-
205
- ```neoscript
206
- string Description(InventoryItem this, Root root) {
207
- get {
208
- return $"{this.Name} ({this.Type})";
209
- }
241
+ The language service protects the root member name, type, member ID, lock, and
242
+ storage metadata. Edit only the value initializer after `=`. The three root
243
+ values use the same nested construction syntax as any other authored value.
244
+
245
+ Reusable values are stored static members on real classes; there is no
246
+ `ValueRegistry` or compiler-defined `Values` global:
247
+
248
+ ```neo
249
+ @id("assets-class-id")
250
+ @storage(allowed: .Immutable)
251
+ class Assets {
252
+ @id("capitol-member-id")
253
+ static Outpost Capitol =
254
+ @id("capitol-value-id")
255
+ new {
256
+ Name = "Capitol",
257
+ Image = Images.Capitol.Slice(0),
258
+ };
210
259
 
211
- set(string value) {
212
- this.Name = value;
260
+ @id("home-getter-id")
261
+ static Outpost Home {
262
+ get {
263
+ return Assets.Capitol;
264
+ }
213
265
  }
214
266
  }
215
267
  ```
216
268
 
217
- A concrete `[NeoScript]` method uses the same outer contextual signature and
218
- puts its declared arguments and executable body in a nested unit:
269
+ The member ID anchors the replaceable stored binding; the initializer ID is
270
+ the actual value row. A computed static getter is an alias and creates no
271
+ binding or value row. Values may also live directly on their domain class.
272
+
273
+ Omitted members materialize the current defaults once during creation. Later
274
+ default changes do not mutate existing values. Removing an explicitly
275
+ materialized field from an existing initializer requests reset through the
276
+ current default, which must appear in `neo diff`.
277
+
278
+ List items use native inline identity, never a wrapper:
279
+
280
+ ```neo
281
+ Tags = [
282
+ @id("story-tag-item-id")
283
+ "story",
284
+
285
+ @id("key-tag-item-id")
286
+ "key",
287
+ ];
288
+ ```
289
+
290
+ A bare new element is pending-create shorthand. The compiler never matches an
291
+ existing ordered item by index or payload.
292
+
293
+ Logical project references use the native `Reference` intrinsic:
294
+
295
+ ```neo
296
+ Reference(Assets.Capitol)
297
+ Reference<Outpost>(id: "capitol-value-id")
298
+ Reference<CapitolColdBoot>(CapitolColdBoot)
299
+ Reference<Dialogue>(id: "capitol-dialogue-id")
300
+ ```
219
301
 
220
- ```neoscript
221
- bool UsePrimary(InventoryItem this, Root root) {
222
- (InventoryItem target) {
223
- return target.IsStackable;
302
+ Use symbols when available. Use the generic ID overload only when the ID is
303
+ the target information. The expected lookup/dialogue member contract still
304
+ validates collection membership, multiplicity, group, and assignability.
305
+
306
+ Localizable string initializers contain the main-locale text, not a
307
+ localized-text ID. Pull/lower preserves other locales, comments, statuses,
308
+ archive state, and unrelated links.
309
+
310
+ ## Project configuration
311
+
312
+ Use typed top-level globals for configuration:
313
+
314
+ - `Project Project = new(...)` for project defaults;
315
+ - `TextureTemplate` and `AudioTemplate` declarations under `Templates/`;
316
+ - `LocalizationStatus` and `Localization` declarations;
317
+ - `PriorityGroup Name = new() { PriorityOption ... }`;
318
+ - `DialogueGroup Name = new(...)`, with inline functions/conditions when
319
+ supported;
320
+ - typed generic relation globals in `Relations.neo`.
321
+
322
+ Named arguments and contextual enum literals come from generated contracts.
323
+ Do not invent raw persistence fields or generic property bags. Translations
324
+ other than the main locale, layout, compiled IR, hashes, storage stamps, and
325
+ upload metadata are not project source.
326
+
327
+ ## Project files
328
+
329
+ Typed editable registries own project files:
330
+
331
+ ```neo
332
+ ImageRegistry Images = new() {
333
+ @id("sword-image-file-id")
334
+ @settings(template: PixelArt)
335
+ NeoImage Sword = new("Files/Images/Sword.png");
336
+ }
337
+
338
+ AudioClipRegistry AudioClips = new() {
339
+ @id("sword-hit-audio-file-id")
340
+ @settings(template: SoundEffect)
341
+ NeoAudioClip SwordHit = new("Files/AudioClips/SwordHit.wav");
342
+ }
343
+ ```
344
+
345
+ Use `Images.Sword.Slice(0)` for sprite members and
346
+ `AudioClips.SwordHit` for audio members. The annotation is the project-file ID;
347
+ renaming/moving local presentation or replacing bytes retains it.
348
+
349
+ A supported binary dropped under `Files/Images/` or `Files/AudioClips/` is a
350
+ pending file. The language service injects a provisional deterministic symbol.
351
+ Status/diff/dry-run do not change registry source; a successful push creates
352
+ the record, uploads verified bytes, and materializes the declaration and ID.
353
+ `neo files add <path> [--template <Name>]` may scaffold that declaration
354
+ explicitly before push.
355
+
356
+ Pull and push use server-verified SHA-256, not storage ETags. Divergent
357
+ local/remote changes keep local bytes and write the verified remote side under
358
+ `.neo/conflicts/files/<file-id>/`. A missing binary with a retained declaration
359
+ is an error; remove the declaration to request deletion.
360
+
361
+ ## NeoFlow dialogues
362
+
363
+ Each `.neoflow` contains exactly one top-level `sealed class Name : Dialogue`.
364
+ It must be non-generic, directly derive from the compiler-owned system
365
+ `Dialogue`, and override the required `Trigger Trigger` exactly once. No other
366
+ class, interface, enum, nested type, or local type is legal in NeoFlow.
367
+
368
+ ```neoflow
369
+ @id("capitol-dialogue-id")
370
+ @settings(
371
+ name: "Capitol: cold boot",
372
+ description: "Capitol recognizes a returning player.",
373
+ saveOptionChoices: true
374
+ )
375
+ sealed class CapitolColdBoot : Dialogue {
376
+ @primary Outpost capitol = Assets.Capitol;
377
+ Player player = Player.Current;
378
+
379
+ @id("can-start-function-id")
380
+ bool CanStart() {
381
+ return !player.HasSeenCapitol;
382
+ }
383
+
384
+ @id("trigger-id")
385
+ override Trigger Trigger = new(
386
+ group: CapitolDialogues.High,
387
+ when: [
388
+ @id("can-start-use-id")
389
+ CanStart,
390
+ ]
391
+ ) => Welcome;
392
+
393
+ @id("welcome-node-id")
394
+ Text Welcome = new(name: "Welcome!") {
395
+ """
396
+ Hello, {player.Name}. Welcome to {capitol.Name}.
397
+ """
398
+
399
+ @id("continue-option-id")
400
+ Option Continue = new() {
401
+ """
402
+ Tell me more.
403
+ """
404
+ return Remember;
405
+ }
406
+ }
407
+
408
+ @id("remember-node-id")
409
+ Actions Remember = new() {
410
+ @id("seen-mutation-id")
411
+ player.HasSeenCapitol = true;
412
+
413
+ @id("pause-id")
414
+ Pause(reason: "remember", duration: 0.5);
415
+
416
+ return Finish;
417
+ }
418
+
419
+ @id("finish-node-id")
420
+ Text Finish = new() {
421
+ """
422
+ Until next time.
423
+ """
224
424
  }
225
425
  }
226
426
  ```
227
427
 
228
- The complete wrapper is tracked on disk and displayed identically in editors;
229
- Monaco protects the signature/braces while leaving the getter, setter, or
230
- function body editable. Abstract scripted members have no file.
231
-
232
- Missing, duplicate, case-colliding, ambiguous, and orphaned sidecars are hard
233
- diagnostics. A sidecar for an abstract member is also invalid. The stable C#
234
- member ID lets canonical renames move the file safely; include C# and sidecar
235
- renames in the same reviewed change.
236
-
237
- Canonical C# places `// NeoScript: Scripts/<Class>/<Member>.neo` above the
238
- linked declaration. Go-to-definition, references, and rename use the Roslyn
239
- source identity plus stable member ID to navigate between C# and `.neo`.
240
-
241
- NeoScript is C#-flavored. Locals may use an explicit type
242
- (`string name = ...;`) or inference (`var name = ...;`); inferred locals retain
243
- the same static type and editor intelligence. `this` is the containing
244
- instance; roots include `root.Assets`, `root.Save`, and `root.Session`.
245
-
246
- Every executable NeoScript unit uses the same mutation-capable resolver and
247
- executor. Getter and dialogue-condition bodies may write just like actions,
248
- setters, Functions, and migrations; the resolved target's Immutable, Save,
249
- Session, or runtime ownership—not the body kind—decides whether the write is
250
- legal. The non-code Condition builder remains a restricted read form.
251
-
252
- Concrete, closed, writable classes expose the same public constructor
253
- shape as generated C#. Use `new ClassName(required, optional, ...)`; required
254
- parameters come first, optional parameters follow in generated-code order,
255
- and `null` skips an optional positional slot. Arguments remain positional;
256
- editor parameter-name hints are previews, not named-argument syntax.
257
- Constructor graphs begin as parentless Session values. They survive only when
258
- attached, returned, or otherwise escaped from the invocation; abandoned
259
- graphs are reclaimed.
260
-
261
- Static members use a class receiver (`GameRules.EncounterCount`), while
262
- instance members use a value receiver. Stored static members resolve through
263
- their authored/Save/Session binding layer and are never copied into class
264
- instances.
428
+ - `@primary` explicitly selects the primary value. Ordinary typed bindings are
429
+ manual linked values. Primary is never inferred.
430
+ - Dialogue bindings are visible throughout the flow; node bindings are scoped
431
+ to that node and its owned children.
432
+ - Direct and transitive function references derive Logic linked values by
433
+ stable dependency graph. Do not add redundant manual links.
434
+ - Inline functions are reusable. A function definition has one ID; every
435
+ persisted condition use, action invocation, mutation, and pause has its own
436
+ owner-scoped ID.
437
+ - Triple-quoted prose is main-locale localized text with typed interpolation.
438
+ - Graph constructor bodies are NeoFlow-only optional escaping trailing bodies
439
+ with contextual `void | Node`. `=> Next` is the concise form; a block may
440
+ finish with `return Next;`. There is no authorable `to:` argument.
441
+ - Triggers, options, and outcomes require a node destination. Terminal text and
442
+ actions may fall through. Text with options and conditions with outcomes do
443
+ not also return a direct destination.
444
+ - `Actions Empty = new();` is valid. Put all action statements inside its body.
445
+ - Web layout and compiled IR are derived state and do not dirty source.
446
+
447
+ After dialogue edits:
448
+
449
+ ```sh
450
+ neo dialogue dryrun <dialogue-ref>
451
+ ```
452
+
453
+ The dry run traverses option paths from a fresh save and applies runtime
454
+ mutation-ownership rules. Exit 1 means the graph would fail on device. Whole
455
+ dialogue JSON export/apply is not a supported source workflow. Low-level
456
+ `neo dialogue compile` remains available for repair/inspection of a logic
457
+ block.
458
+
459
+ ## Inline NeoScript and snippets
460
+
461
+ Computed getters, setters, functions, dialogue logic, and group logic are
462
+ inline in their owning `.neo`/`.neoflow` declaration. The browser-safe shared
463
+ language service compiles them with the same project symbols used by Monaco,
464
+ VS Code, CLI, and the trusted server. There is no `Scripts/<Class>/<Member>.neo`
465
+ sidecar path.
466
+
467
+ Use snippet commands for focused checking and evaluation:
265
468
 
266
469
  ```sh
267
470
  neo script check --all
@@ -274,29 +477,55 @@ neo script eval --function Outpost.RefreshUnlock --this-value <id> --args '[3]'
274
477
  neo script apply --mode action '...'
275
478
  ```
276
479
 
277
- `eval` uses authored values and the same evaluator as the web app. `apply` is
278
- preview-only unless its command explicitly supports a commit; it reports
279
- return values, ordered write intents, and surviving constructor rows in
280
- `createdSessionValues`. Prefer `--json` for automation.
480
+ `eval` uses authored values and the same evaluator as the web app. `apply`
481
+ previews ordered write intents unless its explicit command contract supports a
482
+ commit. Prefer `--json` for automation. Runtime ownership—not body kind—decides
483
+ whether a write target is Immutable, Save, Session, or otherwise writable.
281
484
 
282
- ## Conflicts and version bumps
485
+ Migrations remain tracked NeoScript action files under `Migrations/`:
283
486
 
284
- Overlapping concurrent schema edits produce explicit local/server conflict
285
- markers. They intentionally fail compilation. Edit source to the desired final
286
- state and push; that push is the resolution. `neo resolve --mine|--theirs` is
287
- whole-side convenience only.
487
+ ```sh
488
+ neo migrate new <name> --target <ClassName|project>
489
+ neo migrate list
490
+ neo migrate check
491
+ neo migrate run [--dry-run] [--skip-invalid]
492
+ neo migrate prune
493
+ ```
494
+
495
+ ## Conflicts, identity, and push
496
+
497
+ Pull performs a record-aware three-way merge by stable identity:
498
+
499
+ - unchanged local accepts server authored fields;
500
+ - unchanged server retains local edits;
501
+ - disjoint fields/children merge;
502
+ - collection and graph children merge by ID, never index;
503
+ - conflicting scalar, edge, order, delete/edit, or binary changes are explicit.
504
+
505
+ Conflict source intentionally fails compilation. Edit the desired final source
506
+ or use `neo resolve --mine|--theirs` as a whole-side convenience. Then pull,
507
+ review, dry-run, and push again. Never seek a force-CAS bypass.
508
+
509
+ `neo push` sends the complete hashed source bundle for trusted server
510
+ recompilation but writes only the semantic diff. One accepted push atomically
511
+ commits records, main-locale text, stored bindings, and staged file metadata
512
+ under CAS. Server compilation independently derives IR, linked values,
513
+ placements, structural rows, and generic/storage stamps; client products are
514
+ not trusted.
288
515
 
289
- For `base-hash-conflict`, pull, resolve, and push again. Never seek a force
290
- bypass. For `version-bump-required`, inspect the classification and repeat
291
- with `neo push --accept-bump` only when intended.
516
+ Pending IDs are assigned only inside a successful real commit. Source and
517
+ `.neo/state.json` are rewritten only after acceptance. Dry-run never uploads,
518
+ allocates a durable ID, or changes tracked bytes.
292
519
 
293
- Script conflicts block validation in the same way and must be resolved in the
294
- tracked `.neo` file.
520
+ For `base-hash-conflict`, pull, resolve, and retry. For
521
+ `version-bump-required`, inspect the classification and pass
522
+ `neo push --accept-bump` only when intended.
295
523
 
296
- ## Content stays in commands
524
+ ## Low-level content operations
297
525
 
298
- Values, dialogue instances, localized text, and project files are records, not
299
- schema source files:
526
+ Checked-in source is the normal way to author project values, files, and
527
+ dialogues. Low-level commands remain peer mutation surfaces for automation and
528
+ repair:
300
529
 
301
530
  ```sh
302
531
  neo records query [--kind <recordKind>]
@@ -310,92 +539,57 @@ neo values create '<raw-json-value>' [--class <classId>] --bind <staticMemberId>
310
539
  neo loc locales
311
540
  neo loc list
312
541
  neo loc set <textId> <locale> "text"
542
+ neo dialogue list
543
+ neo dialogue show <ref>
544
+ neo files list
313
545
  ```
314
546
 
315
- Write verbs accept a JSON-array batch on stdin or `--file`; use one batch when
316
- edits must be atomic. A `values set` payload is the raw value, not
317
- `{"value": ...}`. `values bind` and `unbind` edit only a stored static
318
- member's authored binding; `create --bind` can atomically create and bind a
319
- complete class/collection graph supplied as one batch. For collection rows
320
- use `values add-entry` on the live container value; a member's default
321
- container ID may not be an instance's container.
547
+ Write verbs accept a JSON-array batch on stdin or `--file` where supported;
548
+ use one batch for atomic related changes. A `values set` payload is the raw
549
+ value, not `{ "value": ... }`. Static bind/unbind changes the live stored
550
+ binding. These commands do not rewrite local project source. After any
551
+ low-level or web write, run `neo pull` before further source edits or push.
322
552
 
323
- ### Dialogue authoring
324
-
325
- Always run `neo dialogue dryrun [ref]` after editing dialogue. It traverses
326
- option paths from a fresh save and applies the runtime's mutation-ownership
327
- rules. Exit 1 means the authored graph would fail on device.
328
-
329
- `neo dialogue export <ref>` and `neo dialogue apply <spec.json> [--dry-run]`
330
- round-trip a whole dialogue. `neo dialogue compile` compiles condition/action
331
- blocks with their dialogue/node context. Localized node fields hold text IDs;
332
- create/edit those records through `neo loc` with their links.
333
-
334
- Lookup collection mutation is a common trap: mutating a collection through a
335
- lookup may resolve to an authored asset collection and be forbidden. The
336
- dialogue dry run exists to catch this and related save/session ownership bugs.
337
-
338
- ## Branches, releases, and migrations
553
+ ## Branches, releases, and history
339
554
 
340
555
  ```sh
341
556
  neo branch list
342
557
  neo branch create <name> [--from <ref>]
343
558
  neo branch switch <nameOrId>
559
+ neo branch refresh [--dry-run]
344
560
  neo merge <branch> [--dry-run] [--migrate]
345
561
  neo release cut [--bump major|minor|patch] [--dry-run]
346
-
347
- neo migrate new <name> --target <Class>
348
- neo migrate list
349
- neo migrate check
350
- neo migrate run [--dry-run] [--skip-invalid]
562
+ neo history inspect
563
+ neo history log
351
564
  ```
352
565
 
353
- Branches are copy-on-write forks. Releases are immutable snapshots; their bump
354
- floor is derived from transaction history and may only be raised. Release
566
+ Branches are copy-on-write forks. Releases are immutable snapshots; the
567
+ server derives a minimum compatibility bump and it may only be raised. Release
355
568
  operations require the release login profile.
356
569
 
357
- Migrations remain NeoScript action files under `Migrations/`, with stable
358
- headers and pinned compiled IR. The server runner tracks per-branch applied
359
- state; merge may chain pending migrations before validation.
360
-
361
570
  ## Editor and implementation contract
362
571
 
363
- The browser-safe `neoscript-language` service is shared by the compiler, CLI,
364
- web Monaco editor, and VS Code LSP. Do not add language intelligence directly
365
- to an environment adapter.
366
-
367
- Monaco's existing highlighting, comments/interpolation, bracket behavior,
368
- protected scaffolds, context-aware completion/hover, and accurate diagnostics
369
- are a release-blocking compatibility floor. The shared service includes recovery completion,
370
- signature help, C# and script definitions, references, rename, document
371
- symbols, semantic tokens, quick fixes, formatting, richer diagnostics,
372
- contextual ranking, and incremental analysis. Project updates must refresh
373
- context without accumulating stale providers.
374
-
375
- The VS Code extension consumes the same service and grammar/token spec. Its
376
- LSP supports the same diagnostics, completion, hover, signature, navigation,
377
- rename, symbols, semantic tokens, and formatting. The VSIX is built in-repo;
378
- marketplace publication is separate.
379
-
380
- ## Agent implementation notes
381
-
382
- - The Node CLI talks directly to Convex through typed `api.*` calls and uses
383
- the same session-gated CAS commit path as the web app.
384
- - `SchemaManifestV3` is the only C# source/document boundary. It uses `classes`,
385
- `members`, `"class"`, `"member"`, `classId`, `memberId`, and `MemberKind`.
386
- The contract registry classifies authored, derived, and volatile fields;
387
- derived server fields come from the pulled base and absent/null equivalents
388
- normalize.
389
- - The npm package bundles the Roslyn app, dependencies, SDK, analyzer, and
390
- generator under `dist/tooling`; it does not bundle a runtime.
391
- - The schema compiler does static analysis only. Never execute an authored
392
- assembly to obtain settings.
393
- - A change is incomplete until typecheck/tests/builds, package-content and
394
- contract-version checks, Monaco parity/browser-bundle suites, VSIX
395
- packaging, Unity sample tests, live `neowyn` no-op verification, and final
396
- `npm run doctor` succeed.
397
-
398
- Tokens use the macOS Keychain/OS credential store when available, a protected
399
- file only as fallback, and `NEO_COMPOSE_TOKEN` or `--token-stdin` in CI. The
400
- editor profile cannot publish releases; server-enforced scopes are the
401
- security boundary.
572
+ The browser-safe `@neocompose/neoscript-language` service is shared by the
573
+ compiler, CLI, trusted server, web Monaco editor, and VS Code LSP. Do not add
574
+ language intelligence directly to an environment adapter.
575
+
576
+ Monaco and VS Code must share project-aware diagnostics, recovery completion,
577
+ hover, signature help, definitions, references, rename, symbols, semantic
578
+ tokens, code actions, and formatting for `.neo` and `.neoflow`. Project updates
579
+ must refresh context without accumulating stale providers. The VSIX is built
580
+ in-repo; marketplace publication is separate.
581
+
582
+ The Node CLI talks directly to authenticated Convex APIs and commits through
583
+ the session-gated CAS boundary. Tokens use the macOS Keychain/OS credential
584
+ store when available and a protected file only as fallback. Use
585
+ `NEO_COMPOSE_TOKEN` or `--token-stdin` in CI. The editor profile cannot publish
586
+ releases; server-enforced scopes are the security boundary.
587
+
588
+ The npm package bundles the Node orchestrator and shared browser-safe
589
+ compiler/editor assets. It must not contain a `.csproj`, `.cs`, `.dll`, Roslyn
590
+ application, .NET host metadata, or generated C# SDK. Package-content tests
591
+ enforce that boundary.
592
+
593
+ A change is incomplete until focused tests, typecheck, builds, package-content
594
+ and contract checks, Monaco/browser parity, VSIX packaging and interactive
595
+ testing, sample no-op verification, and final `npm run doctor` succeed.