@githolon/dsl 0.1.0 → 0.1.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/dart/.dart_tool/package_config.json +328 -0
- package/dart/.dart_tool/package_graph.json +485 -0
- package/dart/.dart_tool/pub/bin/test/test.dart-3.11.5.snapshot +0 -0
- package/dart/.dart_tool/test/incremental_kernel.Ly9AZGFydD0zLjU= +0 -0
- package/dart/.dart_tool/version +1 -0
- package/dart/FINDINGS.md +147 -0
- package/dart/build/native_assets/macos/native_assets.json +1 -0
- package/dart/build/test_cache/build/89a6598c8854ed031dfc25d83c80860e.cache.dill.track.dill +0 -0
- package/dart/build/unit_test_assets/AssetManifest.bin +0 -0
- package/dart/build/unit_test_assets/FontManifest.json +1 -0
- package/dart/build/unit_test_assets/NOTICES.Z +0 -0
- package/dart/build/unit_test_assets/NativeAssetsManifest.json +1 -0
- package/dart/build/unit_test_assets/shaders/ink_sparkle.frag +0 -0
- package/dart/build/unit_test_assets/shaders/stretch_effect.frag +0 -0
- package/dart/lib/nomos_dsl.dart +43 -0
- package/dart/lib/src/dispatch.dart +87 -0
- package/dart/lib/src/driver.dart +122 -0
- package/dart/lib/src/provider.dart +139 -0
- package/dart/lib/src/schema_validation.dart +44 -0
- package/dart/lib/src/subscriptions.dart +549 -0
- package/dart/lib/src/wire.dart +439 -0
- package/dart/pubspec.lock +421 -0
- package/dart/pubspec.yaml +23 -0
- package/dart/test/schema_validation_test.dart +66 -0
- package/dart/test/wire_test.dart +162 -0
- package/package.json +2 -1
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
{
|
|
2
|
+
"roots": [
|
|
3
|
+
"nomos_dsl"
|
|
4
|
+
],
|
|
5
|
+
"packages": [
|
|
6
|
+
{
|
|
7
|
+
"name": "nomos_dsl",
|
|
8
|
+
"version": "0.0.0",
|
|
9
|
+
"dependencies": [
|
|
10
|
+
"json_schema"
|
|
11
|
+
],
|
|
12
|
+
"devDependencies": [
|
|
13
|
+
"test"
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "test",
|
|
18
|
+
"version": "1.31.1",
|
|
19
|
+
"dependencies": [
|
|
20
|
+
"analyzer",
|
|
21
|
+
"async",
|
|
22
|
+
"boolean_selector",
|
|
23
|
+
"collection",
|
|
24
|
+
"coverage",
|
|
25
|
+
"http_multi_server",
|
|
26
|
+
"io",
|
|
27
|
+
"matcher",
|
|
28
|
+
"node_preamble",
|
|
29
|
+
"package_config",
|
|
30
|
+
"path",
|
|
31
|
+
"pool",
|
|
32
|
+
"shelf",
|
|
33
|
+
"shelf_packages_handler",
|
|
34
|
+
"shelf_static",
|
|
35
|
+
"shelf_web_socket",
|
|
36
|
+
"source_span",
|
|
37
|
+
"stack_trace",
|
|
38
|
+
"stream_channel",
|
|
39
|
+
"test_api",
|
|
40
|
+
"test_core",
|
|
41
|
+
"typed_data",
|
|
42
|
+
"web_socket_channel",
|
|
43
|
+
"webkit_inspection_protocol",
|
|
44
|
+
"yaml"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "json_schema",
|
|
49
|
+
"version": "5.2.2",
|
|
50
|
+
"dependencies": [
|
|
51
|
+
"collection",
|
|
52
|
+
"http",
|
|
53
|
+
"logging",
|
|
54
|
+
"rfc_6901",
|
|
55
|
+
"uri"
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "yaml",
|
|
60
|
+
"version": "3.1.3",
|
|
61
|
+
"dependencies": [
|
|
62
|
+
"collection",
|
|
63
|
+
"source_span",
|
|
64
|
+
"string_scanner"
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "webkit_inspection_protocol",
|
|
69
|
+
"version": "1.2.1",
|
|
70
|
+
"dependencies": [
|
|
71
|
+
"logging"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "web_socket_channel",
|
|
76
|
+
"version": "3.0.3",
|
|
77
|
+
"dependencies": [
|
|
78
|
+
"async",
|
|
79
|
+
"crypto",
|
|
80
|
+
"stream_channel",
|
|
81
|
+
"web",
|
|
82
|
+
"web_socket"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"name": "typed_data",
|
|
87
|
+
"version": "1.4.0",
|
|
88
|
+
"dependencies": [
|
|
89
|
+
"collection"
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "test_core",
|
|
94
|
+
"version": "0.6.18",
|
|
95
|
+
"dependencies": [
|
|
96
|
+
"analyzer",
|
|
97
|
+
"args",
|
|
98
|
+
"async",
|
|
99
|
+
"boolean_selector",
|
|
100
|
+
"collection",
|
|
101
|
+
"coverage",
|
|
102
|
+
"frontend_server_client",
|
|
103
|
+
"glob",
|
|
104
|
+
"io",
|
|
105
|
+
"meta",
|
|
106
|
+
"package_config",
|
|
107
|
+
"path",
|
|
108
|
+
"pool",
|
|
109
|
+
"source_map_stack_trace",
|
|
110
|
+
"source_maps",
|
|
111
|
+
"source_span",
|
|
112
|
+
"stack_trace",
|
|
113
|
+
"stream_channel",
|
|
114
|
+
"test_api",
|
|
115
|
+
"vm_service",
|
|
116
|
+
"yaml"
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"name": "test_api",
|
|
121
|
+
"version": "0.7.12",
|
|
122
|
+
"dependencies": [
|
|
123
|
+
"async",
|
|
124
|
+
"boolean_selector",
|
|
125
|
+
"collection",
|
|
126
|
+
"meta",
|
|
127
|
+
"source_span",
|
|
128
|
+
"stack_trace",
|
|
129
|
+
"stream_channel",
|
|
130
|
+
"string_scanner",
|
|
131
|
+
"term_glyph"
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"name": "stream_channel",
|
|
136
|
+
"version": "2.1.4",
|
|
137
|
+
"dependencies": [
|
|
138
|
+
"async"
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"name": "stack_trace",
|
|
143
|
+
"version": "1.12.1",
|
|
144
|
+
"dependencies": [
|
|
145
|
+
"path"
|
|
146
|
+
]
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"name": "source_span",
|
|
150
|
+
"version": "1.10.2",
|
|
151
|
+
"dependencies": [
|
|
152
|
+
"collection",
|
|
153
|
+
"path",
|
|
154
|
+
"term_glyph"
|
|
155
|
+
]
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "shelf_web_socket",
|
|
159
|
+
"version": "3.0.0",
|
|
160
|
+
"dependencies": [
|
|
161
|
+
"shelf",
|
|
162
|
+
"stream_channel",
|
|
163
|
+
"web_socket_channel"
|
|
164
|
+
]
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"name": "shelf_static",
|
|
168
|
+
"version": "1.1.3",
|
|
169
|
+
"dependencies": [
|
|
170
|
+
"convert",
|
|
171
|
+
"http_parser",
|
|
172
|
+
"mime",
|
|
173
|
+
"path",
|
|
174
|
+
"shelf"
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"name": "shelf_packages_handler",
|
|
179
|
+
"version": "3.0.2",
|
|
180
|
+
"dependencies": [
|
|
181
|
+
"path",
|
|
182
|
+
"shelf",
|
|
183
|
+
"shelf_static"
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"name": "shelf",
|
|
188
|
+
"version": "1.4.2",
|
|
189
|
+
"dependencies": [
|
|
190
|
+
"async",
|
|
191
|
+
"collection",
|
|
192
|
+
"http_parser",
|
|
193
|
+
"path",
|
|
194
|
+
"stack_trace",
|
|
195
|
+
"stream_channel"
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"name": "pool",
|
|
200
|
+
"version": "1.5.2",
|
|
201
|
+
"dependencies": [
|
|
202
|
+
"async",
|
|
203
|
+
"stack_trace"
|
|
204
|
+
]
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"name": "path",
|
|
208
|
+
"version": "1.9.1",
|
|
209
|
+
"dependencies": []
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"name": "package_config",
|
|
213
|
+
"version": "2.2.0",
|
|
214
|
+
"dependencies": [
|
|
215
|
+
"path"
|
|
216
|
+
]
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"name": "node_preamble",
|
|
220
|
+
"version": "2.0.2",
|
|
221
|
+
"dependencies": []
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"name": "matcher",
|
|
225
|
+
"version": "0.12.20",
|
|
226
|
+
"dependencies": [
|
|
227
|
+
"async",
|
|
228
|
+
"meta",
|
|
229
|
+
"stack_trace",
|
|
230
|
+
"term_glyph",
|
|
231
|
+
"test_api"
|
|
232
|
+
]
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"name": "io",
|
|
236
|
+
"version": "1.0.5",
|
|
237
|
+
"dependencies": [
|
|
238
|
+
"meta",
|
|
239
|
+
"path",
|
|
240
|
+
"string_scanner"
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"name": "http_multi_server",
|
|
245
|
+
"version": "3.2.2",
|
|
246
|
+
"dependencies": [
|
|
247
|
+
"async"
|
|
248
|
+
]
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"name": "coverage",
|
|
252
|
+
"version": "1.15.0",
|
|
253
|
+
"dependencies": [
|
|
254
|
+
"args",
|
|
255
|
+
"cli_config",
|
|
256
|
+
"glob",
|
|
257
|
+
"logging",
|
|
258
|
+
"meta",
|
|
259
|
+
"package_config",
|
|
260
|
+
"path",
|
|
261
|
+
"source_maps",
|
|
262
|
+
"stack_trace",
|
|
263
|
+
"vm_service",
|
|
264
|
+
"yaml"
|
|
265
|
+
]
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"name": "collection",
|
|
269
|
+
"version": "1.19.1",
|
|
270
|
+
"dependencies": []
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"name": "boolean_selector",
|
|
274
|
+
"version": "2.1.2",
|
|
275
|
+
"dependencies": [
|
|
276
|
+
"source_span",
|
|
277
|
+
"string_scanner"
|
|
278
|
+
]
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"name": "async",
|
|
282
|
+
"version": "2.13.1",
|
|
283
|
+
"dependencies": [
|
|
284
|
+
"collection",
|
|
285
|
+
"meta"
|
|
286
|
+
]
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
"name": "analyzer",
|
|
290
|
+
"version": "13.0.0",
|
|
291
|
+
"dependencies": [
|
|
292
|
+
"_fe_analyzer_shared",
|
|
293
|
+
"collection",
|
|
294
|
+
"convert",
|
|
295
|
+
"crypto",
|
|
296
|
+
"glob",
|
|
297
|
+
"meta",
|
|
298
|
+
"package_config",
|
|
299
|
+
"path",
|
|
300
|
+
"pub_semver",
|
|
301
|
+
"source_span",
|
|
302
|
+
"watcher",
|
|
303
|
+
"yaml"
|
|
304
|
+
]
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
"name": "uri",
|
|
308
|
+
"version": "1.0.0",
|
|
309
|
+
"dependencies": [
|
|
310
|
+
"matcher",
|
|
311
|
+
"quiver"
|
|
312
|
+
]
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"name": "rfc_6901",
|
|
316
|
+
"version": "0.2.1",
|
|
317
|
+
"dependencies": []
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"name": "logging",
|
|
321
|
+
"version": "1.3.0",
|
|
322
|
+
"dependencies": []
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"name": "http",
|
|
326
|
+
"version": "1.6.0",
|
|
327
|
+
"dependencies": [
|
|
328
|
+
"async",
|
|
329
|
+
"http_parser",
|
|
330
|
+
"meta",
|
|
331
|
+
"web"
|
|
332
|
+
]
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"name": "string_scanner",
|
|
336
|
+
"version": "1.4.1",
|
|
337
|
+
"dependencies": [
|
|
338
|
+
"source_span"
|
|
339
|
+
]
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"name": "web_socket",
|
|
343
|
+
"version": "1.0.1",
|
|
344
|
+
"dependencies": [
|
|
345
|
+
"web"
|
|
346
|
+
]
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
"name": "web",
|
|
350
|
+
"version": "1.1.1",
|
|
351
|
+
"dependencies": []
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"name": "crypto",
|
|
355
|
+
"version": "3.0.7",
|
|
356
|
+
"dependencies": [
|
|
357
|
+
"typed_data"
|
|
358
|
+
]
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
"name": "vm_service",
|
|
362
|
+
"version": "15.2.0",
|
|
363
|
+
"dependencies": []
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"name": "source_maps",
|
|
367
|
+
"version": "0.10.13",
|
|
368
|
+
"dependencies": [
|
|
369
|
+
"source_span"
|
|
370
|
+
]
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"name": "source_map_stack_trace",
|
|
374
|
+
"version": "2.1.2",
|
|
375
|
+
"dependencies": [
|
|
376
|
+
"path",
|
|
377
|
+
"source_maps",
|
|
378
|
+
"stack_trace"
|
|
379
|
+
]
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"name": "meta",
|
|
383
|
+
"version": "1.18.2",
|
|
384
|
+
"dependencies": []
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"name": "glob",
|
|
388
|
+
"version": "2.1.3",
|
|
389
|
+
"dependencies": [
|
|
390
|
+
"async",
|
|
391
|
+
"collection",
|
|
392
|
+
"file",
|
|
393
|
+
"path",
|
|
394
|
+
"string_scanner"
|
|
395
|
+
]
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"name": "frontend_server_client",
|
|
399
|
+
"version": "4.0.0",
|
|
400
|
+
"dependencies": [
|
|
401
|
+
"async",
|
|
402
|
+
"path"
|
|
403
|
+
]
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
"name": "args",
|
|
407
|
+
"version": "2.7.0",
|
|
408
|
+
"dependencies": []
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
"name": "term_glyph",
|
|
412
|
+
"version": "1.2.2",
|
|
413
|
+
"dependencies": []
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
"name": "mime",
|
|
417
|
+
"version": "2.0.0",
|
|
418
|
+
"dependencies": []
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
"name": "http_parser",
|
|
422
|
+
"version": "4.1.2",
|
|
423
|
+
"dependencies": [
|
|
424
|
+
"collection",
|
|
425
|
+
"source_span",
|
|
426
|
+
"string_scanner",
|
|
427
|
+
"typed_data"
|
|
428
|
+
]
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
"name": "convert",
|
|
432
|
+
"version": "3.1.2",
|
|
433
|
+
"dependencies": [
|
|
434
|
+
"typed_data"
|
|
435
|
+
]
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"name": "cli_config",
|
|
439
|
+
"version": "0.2.0",
|
|
440
|
+
"dependencies": [
|
|
441
|
+
"args",
|
|
442
|
+
"yaml"
|
|
443
|
+
]
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"name": "watcher",
|
|
447
|
+
"version": "1.2.1",
|
|
448
|
+
"dependencies": [
|
|
449
|
+
"async",
|
|
450
|
+
"path"
|
|
451
|
+
]
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"name": "pub_semver",
|
|
455
|
+
"version": "2.2.0",
|
|
456
|
+
"dependencies": [
|
|
457
|
+
"collection"
|
|
458
|
+
]
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
"name": "_fe_analyzer_shared",
|
|
462
|
+
"version": "100.0.0",
|
|
463
|
+
"dependencies": [
|
|
464
|
+
"meta",
|
|
465
|
+
"source_span"
|
|
466
|
+
]
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
"name": "quiver",
|
|
470
|
+
"version": "3.2.2",
|
|
471
|
+
"dependencies": [
|
|
472
|
+
"matcher"
|
|
473
|
+
]
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"name": "file",
|
|
477
|
+
"version": "7.0.1",
|
|
478
|
+
"dependencies": [
|
|
479
|
+
"meta",
|
|
480
|
+
"path"
|
|
481
|
+
]
|
|
482
|
+
}
|
|
483
|
+
],
|
|
484
|
+
"configVersion": 1
|
|
485
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.41.9
|
package/dart/FINDINGS.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
NOMOS — Nomos Sovereign: participants act · verify · remember LOCALLY; hosted
|
|
3
|
+
remotes are replaceable custody/transport, not truth. ⇒ ONE Nomos GitHolon
|
|
4
|
+
wasm32-wasip1 artifact {kernel · projection · embedded
|
|
5
|
+
QuickJS engine} on V8 + WASI-shim, byte-identical everywhere. V8 = portability; the one
|
|
6
|
+
wasm = determinism. No native, no wasmtime, no 2nd artifact, no domain-JS on bare V8.
|
|
7
|
+
If a file isn't this / hosting this / authoring for this / proving this — it's gone.
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
# Nomos 2 Dart frontend codegen — findings
|
|
11
|
+
|
|
12
|
+
The Dart types the Flutter frontend needs, (de)serializing the **exact** serde
|
|
13
|
+
JSON the Rust kernel + projection produce/consume. This is decision-6 of the DSL
|
|
14
|
+
design: the schema is the single source of truth → TS (done), proto (later),
|
|
15
|
+
**Dart frontend types (this slice)**.
|
|
16
|
+
|
|
17
|
+
## What was built
|
|
18
|
+
|
|
19
|
+
`nomos2/dsl/dart/` — a Dart package (`nomos_dsl`):
|
|
20
|
+
|
|
21
|
+
| Path | Role | Hand-written / generated |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| `lib/src/wire.dart` | Fixed kernel wire types: `Hlc`, `Value` (sealed: `ValueStr`/`ValueInt`/`ValueSet`/`ValueMap`), `WireField`, `Op` (sealed: `OpSet`/`OpAddToSet`/`OpSetEntry`), `FieldOp`, `Event` (`{aggregate, ops}`, #56), `Intent` (`{hlc, events}`, #56). | hand-written |
|
|
24
|
+
| `lib/src/driver.dart` | `WireDriver` (sealed: `DriverLww`/`DriverAddWins`/`DriverConflict`/`DriverMapOf`) + `Schema`. | hand-written |
|
|
25
|
+
| `lib/src/generated/trackable_asset.dart` | The `trackable_asset` domain: `TrackableAsset` aggregate, `StatusEnum`, and `CreateAssetPayload`/`MoveAssetPayload`/`TagAssetPayload`/`SetCustomFieldPayload`. | **generated** |
|
|
26
|
+
| `lib/nomos_dsl.dart` | Public barrel (exports the three above). | hand-written |
|
|
27
|
+
| `test/wire_test.dart` | Round-trip tests for every wire type + Driver/Schema. | — |
|
|
28
|
+
| `test/trackable_asset_test.dart` | Read-model aggregate deserialization + directive-payload → Event JSON. | — |
|
|
29
|
+
|
|
30
|
+
The **codegen** lives in `nomos2/dsl/` (TS, alongside the existing TS DSL):
|
|
31
|
+
|
|
32
|
+
| Path | Role |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `src/codegen_dart.ts` | The generator: introspects aggregates + directives, emits the Dart per-domain source. |
|
|
35
|
+
| `src/emit_dart.ts` | The driver: wires the `trackable_asset` domain into the generator, writes `dart/lib/src/generated/`. Run `npx tsx src/emit_dart.ts` (or `npm run emit:dart`). |
|
|
36
|
+
|
|
37
|
+
Per the brief: #1 (fixed wire types) is hand-written; **#2 (per-domain types) is
|
|
38
|
+
generated**, so it stays reproducible from the domain definitions, not drifting.
|
|
39
|
+
|
|
40
|
+
## The exact serde JSON shape matched
|
|
41
|
+
|
|
42
|
+
Verified against `nomos2/kernel/src/lib.rs` and the existing emitted fixtures
|
|
43
|
+
(`nomos2/dsl/fixtures/*.json`, the TS side's real-kernel round-trip output):
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
Hlc {"physical":1,"logical":0,"replica":7} replica is a BARE int (newtype-struct transparency), NOT {"ReplicaId":7}
|
|
47
|
+
Value::Str {"Str":"red"}
|
|
48
|
+
Value::Int {"Int":10} i64 in Rust -> Dart int
|
|
49
|
+
Value::Set {"Set":["a","b"]} BTreeSet<String> -> JSON array
|
|
50
|
+
Value::Map {"Map":{"k":{"value":<Value>,"stamp":<Hlc>}}}
|
|
51
|
+
Op::Set {"Set":{"Int":10}} / {"Set":{"Str":"A"}}
|
|
52
|
+
Op::AddToSet {"AddToSet":["x","y"]}
|
|
53
|
+
Op::SetEntry {"SetEntry":{"key":"color","value":{"Str":"red"}}}
|
|
54
|
+
FieldOp {"field":"pos","op":<Op>}
|
|
55
|
+
Event {"aggregate":"asset-1","ops":[<FieldOp>...]} (#56: per-aggregate, the *where*)
|
|
56
|
+
Intent {"hlc":<Hlc>,"events":[<Event>...]} (#56: one commit = intent.json)
|
|
57
|
+
Driver unit "Lww" / "AddWins" / "Conflict" bare strings
|
|
58
|
+
Driver::MapOf {"MapOf":"Lww"} nests
|
|
59
|
+
Schema {"label":"Lww",...,"customFields":{"MapOf":"Lww"}} plain object (BTreeMap)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Read-model aggregate shape (what `TrackableAsset.fromJson` consumes — REALIGNED
|
|
63
|
+
2026-06-01 to the dispatch(intent) read half): the FLAT, already-decoded `data`
|
|
64
|
+
map of a `{type,id,data}` row that the FRB `query()`/`query_by_id()`/`view()`
|
|
65
|
+
emit — e.g. `{ "label":"Pump 2", "pos":10, "status":"active", "tags":["x","y"],
|
|
66
|
+
"customFields":{"size":"L"} }`. NOT the projection-internal `{field:{value,stamp}}`
|
|
67
|
+
`WireField` shape (the Rust `decode_field` has already peeled the kernel `Value`
|
|
68
|
+
back to bare JSON). The generated `fromJson` reads each field via a tolerant
|
|
69
|
+
flat-projection reader in `src/subscriptions.dart` (`readStr`/`readInt`/`readSet`/
|
|
70
|
+
`readStrMap`/`readEnum`/`readJsonStr`).
|
|
71
|
+
|
|
72
|
+
The generated `TrackableAsset` maps each field to a frontend-pleasant Dart type:
|
|
73
|
+
`label: String`, `pos: int`, `status: StatusEnum`, `tags: Set<String>`,
|
|
74
|
+
`customFields: Map<String, String>`. The app subscribes through the generated
|
|
75
|
+
typed read accessors (`watch…`/`read…` over `query()`/`query_by_id()`, threading a
|
|
76
|
+
`NomosReads`) — the READ half of the peer boundary, symmetric with `dispatch`.
|
|
77
|
+
|
|
78
|
+
## How the codegen derives directive ops (no second source of truth)
|
|
79
|
+
|
|
80
|
+
A directive's `plan(payload, ctx)` is arbitrary TS, so the op structure can't be
|
|
81
|
+
read off statically. Instead the generator runs the **same** `plan` with a Proxy
|
|
82
|
+
payload whose property reads return tracking tokens (`{__payloadKey}`). The
|
|
83
|
+
resulting `PlannedOp[]` then tells us, per op, which payload key feeds the value
|
|
84
|
+
/ items / entry-key. That op template is emitted into the Dart payload's
|
|
85
|
+
`toEvent()` — which lowers exactly as the TS `runDirective`/`lowerValue` does
|
|
86
|
+
(int→`ValueInt`, string/enum→`ValueStr`, string[]→`ValueSet`) and threads the
|
|
87
|
+
directive's target aggregate id into the `Event{aggregate, ops}` (#56);
|
|
88
|
+
`toIntent(hlc)` wraps it in a one-event `Intent{hlc, events}`. So the Dart wire
|
|
89
|
+
output is driven by the identical authored plan, not a re-typed copy.
|
|
90
|
+
|
|
91
|
+
## The proof (green via `dart test`)
|
|
92
|
+
|
|
93
|
+
`cd nomos2/dsl/dart && dart test` — **28 tests pass**, `dart analyze` clean:
|
|
94
|
+
|
|
95
|
+
- **Round-trip** (`wire_test.dart`): kernel JSON for `Hlc`, all four `Value`
|
|
96
|
+
variants, all three `Op` variants, an `Event{aggregate, ops}` (Set/AddToSet/
|
|
97
|
+
SetEntry), a multi-aggregate `Intent{hlc, events}` (#56), all `Driver` variants,
|
|
98
|
+
and the lowered `Schema` → `fromJson` → `toJson` structurally equals the input.
|
|
99
|
+
Explicit assertions that `replica` is a bare int and `MapOf` nests.
|
|
100
|
+
- **Read-model aggregate** (`trackable_asset_test.dart`): a `{field:{value,stamp}}`
|
|
101
|
+
JSON (incl. a `Value::Map` for `customFields`) deserializes into the generated
|
|
102
|
+
`TrackableAsset`; enum string → `StatusEnum`; missing field throws.
|
|
103
|
+
- **Directive payload → kernel Intent**: `CreateAssetPayload(...).toIntent(hlc)`
|
|
104
|
+
emits a one-event `Intent` whose event threads `aggregate: 'TrackableAsset'`
|
|
105
|
+
(#56); `toEvent()` exposes the per-aggregate `Event`; `moveAsset`/`tagAsset`/
|
|
106
|
+
`setCustomField` each lower the expected `Set`/`AddToSet`/`SetEntry`; the produced
|
|
107
|
+
`Intent` round-trips back through `Intent.fromJson`.
|
|
108
|
+
|
|
109
|
+
The codegen is **reproducible**: re-running `npx tsx src/emit_dart.ts` produces a
|
|
110
|
+
byte-identical `trackable_asset.dart` (verified). The TS side is unaffected:
|
|
111
|
+
`npx tsc --noEmit` is clean and the existing 13 vitest tests stay green.
|
|
112
|
+
|
|
113
|
+
## Friction / notes (not fixed, by instruction)
|
|
114
|
+
|
|
115
|
+
1. **Aggregate identity (#56) — DONE.** The kernel `Event` is now
|
|
116
|
+
`{aggregate, ops}` and a commit is an `Intent{hlc, events}` (`intent.json`).
|
|
117
|
+
`Event`/`Intent` in `wire.dart` match; each generated payload threads its
|
|
118
|
+
`aggregateId` into `toEvent()` and `toIntent(hlc)` wraps a one-event `Intent`.
|
|
119
|
+
(The generated domain directives are single-aggregate, so each payload's intent
|
|
120
|
+
carries exactly one event; a future multi-aggregate generated directive would
|
|
121
|
+
emit several — same grouping the TS `runDirective` already does.)
|
|
122
|
+
2. **`replica` unsigned.** Rust `ReplicaId(u64)`; Dart has no unsigned int, so
|
|
123
|
+
`WireReplicaId = int`. Fine for realistic replica ids; a far-future >2^63 id
|
|
124
|
+
would need `BigInt` (noted, not handled — out of scope).
|
|
125
|
+
3. **`Value::Set` ordering.** Kernel `BTreeSet` is sorted; Dart `List<String>`
|
|
126
|
+
preserves wire order on round-trip (we don't re-sort), so `toJson` is
|
|
127
|
+
byte-stable against the kernel's already-sorted input. The aggregate field is
|
|
128
|
+
surfaced as a `Set<String>` (order-insensitive) for the frontend.
|
|
129
|
+
4. **Generator scope.** `codegen_dart.ts` handles the field/payload kinds the
|
|
130
|
+
`trackable_asset` domain uses (string/int/enum/set/map, and `json`/`ref` →
|
|
131
|
+
`String` on the aggregate side). Unsupported Zod payload kinds throw loudly
|
|
132
|
+
rather than mis-emit — same fail-closed posture as the TS `lowerDriver`.
|
|
133
|
+
|
|
134
|
+
## How to run
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
cd nomos2/dsl
|
|
138
|
+
npm install
|
|
139
|
+
npx tsx src/emit_dart.ts # (re)generate dart/lib/src/generated/
|
|
140
|
+
npx tsc --noEmit # TS still typechecks
|
|
141
|
+
npx vitest run # existing 13 TS tests
|
|
142
|
+
|
|
143
|
+
cd dart
|
|
144
|
+
dart pub get
|
|
145
|
+
dart analyze # clean
|
|
146
|
+
dart test # 28 tests green
|
|
147
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"format-version":[1,0,0],"native-assets":{}}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[]
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"format-version":[1,0,0],"native-assets":{}}
|
|
Binary file
|
|
Binary file
|