@githolon/dsl 0.108.7 → 0.110.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 (307) hide show
  1. package/assets/operation-contract.wasm +0 -0
  2. package/check_package.mjs +12 -15
  3. package/compile_package.mjs +17 -18
  4. package/compile_proof.mjs +16 -1
  5. package/dart/CHANGELOG.md +76 -1
  6. package/dart/README.md +25 -2
  7. package/dart/lib/src/admission_decision.dart +41 -0
  8. package/dart/lib/src/application_framework_calls.dart +52 -2
  9. package/dart/lib/src/application_model_adoption.dart +187 -0
  10. package/dart/lib/src/application_status.dart +73 -0
  11. package/dart/lib/src/console_enrolment.dart +271 -0
  12. package/dart/lib/src/console_http_io.dart +26 -0
  13. package/dart/lib/src/console_http_stub.dart +7 -0
  14. package/dart/lib/src/dev_cloud.dart +69 -22
  15. package/dart/lib/src/generated_call.dart +83 -23
  16. package/dart/lib/src/kernel_primitives.dart +119 -0
  17. package/dart/lib/src/nms_conformance_runtime.dart +1 -1
  18. package/dart/lib/src/nms_generated_runtime.dart +32 -10
  19. package/dart/lib/src/nms_test_environment.dart +1 -1
  20. package/dart/lib/src/node_runner_transport.dart +41 -46
  21. package/dart/lib/src/observed_session_directory.dart +70 -0
  22. package/dart/lib/src/operation_receipts.dart +112 -0
  23. package/dart/lib/src/peer_application_streams.dart +103 -0
  24. package/dart/lib/src/reception/dart_reception.dart +4280 -0
  25. package/dart/lib/src/reception/event_desk.dart +211 -0
  26. package/dart/lib/src/reception/extremum_read.dart +46 -0
  27. package/dart/lib/src/reception/local_copies.dart +371 -0
  28. package/dart/lib/src/reception/peer_office_connection.dart +11 -0
  29. package/dart/lib/src/reception/progress_desk.dart +267 -0
  30. package/dart/lib/src/reception/reception_contract.dart +11 -0
  31. package/dart/lib/src/reception/reception_session.dart +284 -0
  32. package/dart/lib/src/reception/sync_diagnostics.dart +26 -0
  33. package/dart/lib/src/reception/workspace_preparation_report.dart +126 -0
  34. package/dart/lib/src/replica_readiness.dart +123 -0
  35. package/dart/lib/src/runner/node-entry.mjs +23905 -15774
  36. package/dart/lib/src/runtime_v2_gateway.dart +56 -3
  37. package/dart/lib/src/runtime_v2_transport.dart +544 -3
  38. package/dart/lib/src/session_bound.dart +200 -311
  39. package/dart/lib/src/signing_identity_kernel.dart +84 -0
  40. package/dart/lib/src/sync_status_projection.dart +548 -0
  41. package/dart/lib/src/sync_status_reducer.dart +170 -0
  42. package/dart/lib/src/test_harness.dart +809 -1153
  43. package/dart/lib/src/testing/test_custody.dart +66 -0
  44. package/dart/lib/src/testing/test_peer.dart +328 -0
  45. package/dart/lib/src/typed_watch_registry.dart +169 -0
  46. package/dart/lib/src/workspace_open_progress.dart +27 -0
  47. package/dart/pubspec.lock +24 -1
  48. package/dart/pubspec.yaml +7 -2
  49. package/dart/pubspec_overrides.yaml +2 -0
  50. package/dart/test/admission_decision_test.dart +48 -0
  51. package/dart/test/background_model_adoption_test.dart +228 -0
  52. package/dart/test/bundle_version_pairing_test.dart +4 -4
  53. package/dart/test/child_authentication_repair_test.dart +359 -0
  54. package/dart/test/cloud_bound_local_shell_test.dart +119 -0
  55. package/dart/test/console_enrolment_refusal_test.dart +52 -0
  56. package/dart/test/console_enrolment_test.dart +227 -0
  57. package/dart/test/errors_test.dart +5 -5
  58. package/dart/test/event_plane_seam_test.dart +50 -164
  59. package/dart/test/extremum_read_test.dart +58 -0
  60. package/dart/test/fixtures/wedge/wedge-entry.mjs +3 -21
  61. package/dart/test/generated_query_test.dart +32 -0
  62. package/dart/test/harness_phase_timeout_test.dart +18 -23
  63. package/dart/test/kernel_author_after_read_test.dart +242 -0
  64. package/dart/test/kernel_fence_test.dart +137 -0
  65. package/dart/test/local_copies_test.dart +222 -0
  66. package/dart/test/model_adoption_test.dart +198 -0
  67. package/dart/test/node_peer_local_custody_test.dart +153 -0
  68. package/dart/test/offer_authentication_proof_test.dart +352 -52
  69. package/dart/test/operation_compatibility_test.dart +151 -0
  70. package/dart/test/platform_credential_effect_test.dart +386 -0
  71. package/dart/test/receiving_group_open_test.dart +213 -0
  72. package/dart/test/reception/workspace_preparation_report_test.dart +103 -0
  73. package/dart/test/reception_span_trace_test.dart +23 -0
  74. package/dart/test/replica_readiness_test.dart +156 -0
  75. package/dart/test/runtime_projections_test.dart +92 -0
  76. package/dart/test/runtime_v2_gateway_test.dart +131 -0
  77. package/dart/test/signing_identity_kernel_test.dart +75 -0
  78. package/dart/test/sync_status_preparation_report_test.dart +29 -0
  79. package/dart/test/sync_status_reducer_test.dart +419 -0
  80. package/dart/test/test_harness_test.dart +71 -95
  81. package/dart/test/typed_query_watch_test.dart +170 -0
  82. package/dart/test/typed_watch_registry_test.dart +249 -0
  83. package/dart_lints/README.md +18 -0
  84. package/dart_lints/lib/nomos_lints.dart +70 -0
  85. package/dart_lints/pubspec.lock +580 -0
  86. package/dart_lints/pubspec.yaml +12 -0
  87. package/dart_lints/test/reference_identity_test.dart +75 -0
  88. package/dart_types/CHANGELOG.md +18 -0
  89. package/dart_types/lib/nomos_kernel_protocol.dart +21 -1
  90. package/dart_types/lib/nomos_types.dart +9 -1
  91. package/dart_types/lib/src/admission_decision.dart +37 -0
  92. package/dart_types/lib/src/aggregate_meta.dart +1 -1
  93. package/dart_types/lib/src/approved_model.dart +65 -0
  94. package/dart_types/lib/src/custody.dart +10 -18
  95. package/dart_types/lib/src/error_info.dart +4 -4
  96. package/dart_types/lib/src/errors.dart +29 -29
  97. package/dart_types/lib/src/foreign_ref.dart +62 -33
  98. package/dart_types/lib/src/local_work_rejected.dart +3 -3
  99. package/dart_types/lib/src/nomos_ref.dart +3 -1
  100. package/dart_types/lib/src/principal.dart +2 -2
  101. package/dart_types/lib/src/proto/google/protobuf/any.pb.dart +163 -0
  102. package/dart_types/lib/src/proto/google/protobuf/any.pbenum.dart +11 -0
  103. package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pb.dart +137 -0
  104. package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pbenum.dart +11 -0
  105. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +20721 -10433
  106. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +555 -27
  107. package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pb.dart +387 -0
  108. package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pbenum.dart +46 -0
  109. package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pb.dart +295 -0
  110. package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pbenum.dart +139 -0
  111. package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pb.dart +269 -0
  112. package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pbenum.dart +103 -0
  113. package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pb.dart +417 -0
  114. package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pbenum.dart +62 -0
  115. package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pb.dart +9968 -0
  116. package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pbenum.dart +133 -0
  117. package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pb.dart +204 -0
  118. package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pbenum.dart +54 -0
  119. package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pb.dart +1550 -0
  120. package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pbenum.dart +11 -0
  121. package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pb.dart +710 -0
  122. package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pbenum.dart +11 -0
  123. package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pb.dart +845 -0
  124. package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pbenum.dart +11 -0
  125. package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pb.dart +198 -0
  126. package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pbenum.dart +11 -0
  127. package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pb.dart +369 -0
  128. package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pbenum.dart +11 -0
  129. package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pb.dart +609 -0
  130. package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pbenum.dart +65 -0
  131. package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pb.dart +358 -0
  132. package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pbenum.dart +100 -0
  133. package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pb.dart +2231 -0
  134. package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pbenum.dart +271 -0
  135. package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pb.dart +1286 -0
  136. package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pbenum.dart +11 -0
  137. package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pb.dart +636 -0
  138. package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pbenum.dart +116 -0
  139. package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pb.dart +1637 -0
  140. package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pbenum.dart +175 -0
  141. package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pb.dart +1269 -0
  142. package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pbenum.dart +129 -0
  143. package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pb.dart +2782 -0
  144. package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pbenum.dart +97 -0
  145. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +2232 -8627
  146. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +0 -358
  147. package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pb.dart +1639 -0
  148. package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pbenum.dart +46 -0
  149. package/dart_types/lib/src/runtime_outcome.dart +133 -0
  150. package/dart_types/lib/src/subscriptions.dart +116 -23
  151. package/dart_types/pubspec.yaml +1 -1
  152. package/dart_types/test/extremum_subscriptions_test.dart +40 -0
  153. package/dart_types/test/foreign_ref_resolution_test.dart +75 -0
  154. package/dart_types/test/nomos_ref_address_test.dart +25 -0
  155. package/dart_types/test/ordered_subscriptions_test.dart +34 -0
  156. package/operation_contract_check.mjs +24 -0
  157. package/package.json +11 -6
  158. package/src/aggregate.ts +70 -10
  159. package/src/application_topology.ts +18 -11
  160. package/src/attested.ts +3 -0
  161. package/src/attested_core.ts +46 -3
  162. package/src/birth_meter_ensure.ts +19 -7
  163. package/src/births.ts +29 -4
  164. package/src/build_package.ts +140 -13
  165. package/src/business_birth.ts +181 -4
  166. package/src/codegen_call_proto.ts +1274 -0
  167. package/src/codegen_call_usda.ts +49 -6
  168. package/src/codegen_dart.ts +79 -44
  169. package/src/codegen_dart_client.ts +458 -800
  170. package/src/{codegen_dart_application.ts → codegen_dart_facade.ts} +331 -582
  171. package/src/codegen_dart_framework_calls.ts +320 -37
  172. package/src/codegen_dart_indexed_variant.ts +159 -0
  173. package/src/codegen_dart_scenario.ts +42 -13
  174. package/src/codegen_proof.ts +3 -3
  175. package/src/codegen_provider_dart.ts +5 -0
  176. package/src/codegen_query_proto.ts +158 -0
  177. package/src/codegen_refusal.ts +189 -0
  178. package/src/codegen_result_proto.ts +931 -0
  179. package/src/codegen_result_usda.ts +4 -0
  180. package/src/codegen_ts.ts +464 -616
  181. package/src/codegen_workspace_access.ts +105 -0
  182. package/src/compatibility_graph.ts +759 -0
  183. package/src/compatibility_usda.ts +264 -0
  184. package/src/compile_package_main.ts +1994 -1189
  185. package/src/custody_placement.ts +156 -0
  186. package/src/custody_placement_usda.ts +91 -0
  187. package/src/decl_shapes.ts +21 -2
  188. package/src/describe_model.ts +1 -0
  189. package/src/directive.ts +59 -2
  190. package/src/drivers.ts +51 -0
  191. package/src/engine_entry.ts +52 -8
  192. package/src/evolve_preview.ts +11 -4
  193. package/src/exists.ts +2 -0
  194. package/src/fields.ts +75 -11
  195. package/src/flow_gate.ts +2 -1
  196. package/src/framework/application_home.ts +170 -18
  197. package/src/framework/attested_receipts.ts +8 -3
  198. package/src/framework/auth_provider_law.ts +169 -9
  199. package/src/framework/birth_certificate_law.ts +4 -0
  200. package/src/framework/capability.ts +34 -3
  201. package/src/framework/child_authentication.ts +346 -0
  202. package/src/framework/console_governance.ts +295 -0
  203. package/src/framework/delegated_roles.ts +301 -0
  204. package/src/framework/domain_lifecycle.ts +26 -13
  205. package/src/framework/founding_genesis.ts +193 -0
  206. package/src/framework/framework_aggregates.ts +1 -1
  207. package/src/framework/genesis.ts +6 -1
  208. package/src/framework/governance_relations.ts +19 -0
  209. package/src/framework/home.ts +5 -734
  210. package/src/framework/legacy/child_auth_provider_epoch.ts +73 -0
  211. package/src/framework/model_authority_repair.ts +116 -0
  212. package/src/framework/model_authority_seed.ts +185 -0
  213. package/src/framework/model_transition.ts +211 -0
  214. package/src/framework/owned_custody.ts +1 -1
  215. package/src/framework/principal_enrollment.ts +302 -0
  216. package/src/framework/receiving_group.ts +857 -0
  217. package/src/framework/receiving_group_recovery.ts +314 -0
  218. package/src/framework/relations.ts +4 -8
  219. package/src/framework/signing_identity.ts +242 -95
  220. package/src/framework/source_roster.ts +11 -5
  221. package/src/framework/workspace_access.ts +149 -0
  222. package/src/framework/workspace_invariant.ts +73 -52
  223. package/src/framework/workspaces.ts +407 -40
  224. package/src/framework_call_definitions.ts +32 -3
  225. package/src/generated_client_bundle_boundary.ts +97 -0
  226. package/src/generated_client_names.ts +1 -0
  227. package/src/identity_usda.ts +27 -0
  228. package/src/index.ts +183 -12
  229. package/src/indexed_variant.ts +83 -0
  230. package/src/intent.ts +173 -45
  231. package/src/law_check.ts +8 -5
  232. package/src/law_dependency_index.ts +231 -0
  233. package/src/law_graph.ts +508 -71
  234. package/src/law_graph_usda.ts +170 -24
  235. package/src/law_identity.ts +119 -81
  236. package/src/law_source_map.ts +4 -1
  237. package/src/law_units.ts +498 -0
  238. package/src/law_value_type.ts +7 -3
  239. package/src/member_authentication.ts +302 -0
  240. package/src/null_meta.ts +1 -1
  241. package/src/openusd_compiled_layer.ts +132 -0
  242. package/src/operation_contract_check.ts +31 -0
  243. package/src/ordered_read.ts +2 -1
  244. package/src/package_config.ts +33 -12
  245. package/src/package_dependencies.ts +1 -0
  246. package/src/plan_source_slice.ts +30 -1
  247. package/src/protobuf_field_number.ts +36 -0
  248. package/src/provenance_wire.ts +6 -0
  249. package/src/query.ts +2 -1
  250. package/src/read.ts +50 -0
  251. package/src/relation.ts +4 -1
  252. package/src/relation_schema.ts +15 -2
  253. package/src/report.ts +2 -2
  254. package/src/sqlite_computation_bundle.ts +78 -0
  255. package/src/sqlite_computed.ts +102 -0
  256. package/src/sqlite_counts.ts +154 -0
  257. package/src/sqlite_layout.ts +823 -0
  258. package/src/sqlite_reads.ts +275 -0
  259. package/src/sqlite_samples.ts +185 -0
  260. package/src/stable_id_identity_bridge.ts +1 -1
  261. package/src/stable_ids_for_module.ts +16 -4
  262. package/src/test_call_usda.ts +6 -6
  263. package/src/usda_relationship_integrity.ts +20 -3
  264. package/src/usda_text.ts +21 -1
  265. package/src/value_object.ts +81 -11
  266. package/src/wire.ts +22 -0
  267. package/src/wire_encode.ts +227 -20
  268. package/src/workspace_sharding.ts +15 -6
  269. package/src/workspace_sharing.ts +51 -49
  270. package/src/zod_introspection.ts +2 -0
  271. package/compat_package.mjs +0 -46
  272. package/dart/lib/src/home.dart +0 -15
  273. package/dart/lib/src/runner/offline-install.mjs +0 -15367
  274. package/dart/lib/src/source_trust.dart +0 -51
  275. package/dart/lib/src/webview_bridge.dart +0 -6540
  276. package/dart/lib/src/workspace_name.dart +0 -30
  277. package/dart/test/acquire_session_credentials_test.dart +0 -150
  278. package/dart/test/acquire_session_test.dart +0 -534
  279. package/dart/test/adv_realm_interference_test.dart +0 -600
  280. package/dart/test/cloud_bound_topology_test.dart +0 -168
  281. package/dart/test/cluster_births_test.dart +0 -202
  282. package/dart/test/cluster_device_keyed_acceptance_test.dart +0 -105
  283. package/dart/test/cluster_local_autosync_test.dart +0 -123
  284. package/dart/test/cluster_scale_test.dart +0 -122
  285. package/dart/test/compat_test.dart +0 -61
  286. package/dart/test/dlq_session_surface_test.dart +0 -222
  287. package/dart/test/first_app_gauntlet_test.dart +0 -386
  288. package/dart/test/fixtures/wedge/fake-install.mjs +0 -11
  289. package/dart/test/four_layer_nested_topology_test.dart +0 -290
  290. package/dart/test/home_parity_test.dart +0 -13
  291. package/dart/test/local_sync_inert_test.dart +0 -107
  292. package/dart/test/node_runner_transport_test.dart +0 -78
  293. package/dart/test/parent_signer_recovery_test.dart +0 -155
  294. package/dart/test/residency_refusal_test.dart +0 -49
  295. package/dart/test/sealing_client_test.dart +0 -181
  296. package/dart/test/session_bound_test.dart +0 -285
  297. package/dart/test/stale_bundle_test.dart +0 -80
  298. package/dart/test/vo_read_typing_test.dart +0 -131
  299. package/dart/test/watch_after_offer_stall_test.dart +0 -100
  300. package/dart/test/webview_bridge_test.dart +0 -1930
  301. package/dart/test/workspace_name_test.dart +0 -24
  302. package/runtime/generated-application-host.js +0 -22860
  303. package/src/codegen_query_usda.ts +0 -214
  304. package/src/compat_manifest.ts +0 -26
  305. package/src/compat_package_main.ts +0 -224
  306. package/src/shape_compat.ts +0 -352
  307. package/src/usd_state.ts +0 -505
@@ -0,0 +1,198 @@
1
+ // THE DART SIDE OF THE MODEL-ADOPTION DESK.
2
+ //
3
+ // The office decides whether a workspace is current, needs the approved
4
+ // package, or must defer; Dart supplies the approved model once, answers the
5
+ // runtime's law-package effect with exactly the package for that identity, and
6
+ // projects the desk's typed observations. Nothing here stages or promotes.
7
+ import 'dart:typed_data';
8
+
9
+ import 'package:fixnum/fixnum.dart';
10
+ import 'package:nomos_client/src/application_model_adoption.dart';
11
+ import 'package:nomos_client/src/runtime_v2_transport.dart';
12
+ import 'package:nomos_client/src/sync_status_projection.dart';
13
+ import 'package:nomos_types/nomos_kernel_protocol.dart' as p;
14
+ import 'package:test/test.dart';
15
+
16
+ const lawSha = '5efef545fdadae764e29ba678833073e0245b1b76e315d3a5fe71c6a65240a45';
17
+ const otherSha =
18
+ '48f3b1810000000000000000000000000000000000000000000000000000abcd';
19
+
20
+ class _Platform
21
+ with NmsPlatformCredentialProviderHost
22
+ implements NomosRuntimeV2Transport {
23
+ int sequence = 40;
24
+ @override
25
+ int nextRuntimeRequestId() => ++sequence;
26
+ @override
27
+ Future<p.RuntimeResponse> invokeRuntime(p.RuntimeRequest request) async =>
28
+ p.RuntimeResponse(protocolVersion: 2, requestId: request.requestId);
29
+ }
30
+
31
+ NomosApprovedModel model({List<String> keys = const ['home']}) =>
32
+ NomosApprovedModel(
33
+ lawSha256: lawSha,
34
+ reason: '2026-09-11: retire the value fields; decided by Jack',
35
+ domainKeys: keys,
36
+ loadPackage: () async => Uint8List.fromList([80, 75, 3, 4, 7]),
37
+ );
38
+
39
+ p.PeerLawPackageEffect effect([String sha = lawSha]) =>
40
+ p.PeerLawPackageEffect(effectId: 'law:1', lawSha256: sha);
41
+
42
+ void main() {
43
+ group('NomosApprovedModel is the contract', () {
44
+ test('every field is required and checked at construction', () {
45
+ expect(model().domainKeys, ['home']);
46
+ expect(
47
+ () => NomosApprovedModel(
48
+ lawSha256: 'not-a-hash',
49
+ reason: 'r',
50
+ domainKeys: const ['home'],
51
+ loadPackage: () async => Uint8List(0)),
52
+ throwsArgumentError);
53
+ expect(
54
+ () => NomosApprovedModel(
55
+ lawSha256: lawSha,
56
+ reason: ' ',
57
+ domainKeys: const ['home'],
58
+ loadPackage: () async => Uint8List(0)),
59
+ throwsArgumentError);
60
+ expect(
61
+ () => NomosApprovedModel(
62
+ lawSha256: lawSha,
63
+ reason: 'r',
64
+ domainKeys: const [],
65
+ loadPackage: () async => Uint8List(0)),
66
+ throwsArgumentError);
67
+ expect(
68
+ () => NomosApprovedModel(
69
+ lawSha256: lawSha,
70
+ reason: 'r',
71
+ domainKeys: const ['home', ' '],
72
+ loadPackage: () async => Uint8List(0)),
73
+ throwsArgumentError);
74
+ });
75
+
76
+ test('its package source answers only the identity it was released with',
77
+ () async {
78
+ final source = NmsApprovedModelLawPackageSource(model());
79
+ expect(await source.load(lawSha), [80, 75, 3, 4, 7]);
80
+ expect(await source.load(otherSha), isNull);
81
+ });
82
+ });
83
+
84
+ group('the shell answers the law-package effect', () {
85
+ test('with the bytes for the named identity', () async {
86
+ final platform = _Platform()
87
+ ..registerLawPackageSource(NmsApprovedModelLawPackageSource(model()));
88
+ final receipt = await platform.performLawPackageEffect(effect());
89
+ expect(receipt.effectId, 'law:1');
90
+ expect(receipt.hasLawPackage(), isTrue);
91
+ expect(receipt.lawPackage.lawUsdz, [80, 75, 3, 4, 7]);
92
+ });
93
+
94
+ test('typed refusals: no source, another identity, an unreadable package',
95
+ () async {
96
+ final none = await _Platform().performLawPackageEffect(effect());
97
+ expect(none.hasFailure(), isTrue);
98
+ expect(none.failure.message, contains('supplies no application law packages'));
99
+
100
+ final platform = _Platform()
101
+ ..registerLawPackageSource(NmsApprovedModelLawPackageSource(model()));
102
+ final other = await platform.performLawPackageEffect(effect(otherSha));
103
+ expect(other.hasFailure(), isTrue);
104
+ expect(other.failure.message, contains('holds no law package with identity $otherSha'));
105
+
106
+ final malformed = await platform.performLawPackageEffect(effect('nope'));
107
+ expect(malformed.failure.message, contains('names no package identity'));
108
+
109
+ final broken = _Platform()
110
+ ..registerLawPackageSource(NmsApprovedModelLawPackageSource(
111
+ NomosApprovedModel(
112
+ lawSha256: lawSha,
113
+ reason: 'r',
114
+ domainKeys: const ['home'],
115
+ loadPackage: () async => throw StateError('asset missing'))));
116
+ final unreadable = await broken.performLawPackageEffect(effect());
117
+ expect(unreadable.hasFailure(), isTrue);
118
+ expect(unreadable.failure.message, contains('could not be read'));
119
+ });
120
+
121
+ test('the effect loop carries the receipt back on the same request',
122
+ () async {
123
+ final platform = _Platform()
124
+ ..registerLawPackageSource(NmsApprovedModelLawPackageSource(model()));
125
+ var frames = 0;
126
+ final response = await platform.driveCredentialEffects(
127
+ p.RuntimeRequest(
128
+ protocolVersion: 2,
129
+ requestId: Int64(9),
130
+ adoptApplicationModel: p.AdoptApplicationModelRequest(
131
+ session: 'home', lawSha256: lawSha)), (request) async {
132
+ frames++;
133
+ if (frames == 1) {
134
+ return p.RuntimeResponse(
135
+ protocolVersion: 2,
136
+ requestId: request.requestId,
137
+ correspondencePending: p.CorrespondencePending(
138
+ workId: 'model-adoption-1', lawPackage: effect()));
139
+ }
140
+ expect(request.hasContinueCorrespondence(), isTrue);
141
+ expect(request.continueCorrespondence.workId, 'model-adoption-1');
142
+ expect(request.continueCorrespondence.receipt.lawPackage.lawUsdz,
143
+ [80, 75, 3, 4, 7]);
144
+ return p.RuntimeResponse(
145
+ protocolVersion: 2,
146
+ requestId: request.requestId,
147
+ applicationModelAdopted: p.ApplicationModelAdopted(
148
+ workspace: 'nomos-rg-ada',
149
+ outcome: p.ModelAdoptionOutcome.MODEL_ADOPTION_OUTCOME_ADOPTED,
150
+ currentLawSha256: lawSha));
151
+ });
152
+ expect(frames, 2);
153
+ expect(response.hasApplicationModelAdopted(), isTrue);
154
+ final adoption =
155
+ NomosModelAdoption.fromRuntime(response.applicationModelAdopted);
156
+ expect(adoption.outcome, NomosModelAdoptionOutcome.adopted);
157
+ expect(adoption.currentLawSha256, lawSha);
158
+ expect(adoption.deferred, isNull);
159
+ });
160
+ });
161
+
162
+ group('the desk\'s observations project onto the sync-status surface', () {
163
+ test('a deferred progress is the typed condition the app renders', () {
164
+ final progress = NomosModelAdoptionProgress.fromRuntime(
165
+ p.ModelAdoptionProgress(
166
+ workspace: 'nomos-rg-ada',
167
+ phase: p.ModelAdoptionPhase.MODEL_ADOPTION_PHASE_PROMOTE,
168
+ outcome: p.ModelAdoptionOutcome.MODEL_ADOPTION_OUTCOME_DEFERRED,
169
+ detail: 'remote offer preparation key is not an active signer',
170
+ currentLawSha256: otherSha));
171
+ expect(progress.isTerminal, isTrue);
172
+ final deferred = progress.deferred;
173
+ expect(deferred, isNotNull);
174
+ expect(deferred!.workspace, 'nomos-rg-ada');
175
+ expect(deferred.phase, NomosModelAdoptionPhase.promote);
176
+ expect(deferred.detail, contains('not an active signer'));
177
+ expect(deferred.currentLawSha256, otherSha);
178
+ final status = const SyncStatus().copyWith(modelAdoption: progress);
179
+ expect(status.modelAdoption, same(progress));
180
+ expect(status.copyWith(phase: SyncPhase.idle).modelAdoption, same(progress));
181
+ });
182
+
183
+ test('progress and the non-deferred outcomes map one to one', () {
184
+ NomosModelAdoptionProgress of(p.ModelAdoptionOutcome outcome) =>
185
+ NomosModelAdoptionProgress.fromRuntime(p.ModelAdoptionProgress(
186
+ workspace: 'w',
187
+ phase: p.ModelAdoptionPhase.MODEL_ADOPTION_PHASE_STAGE,
188
+ outcome: outcome));
189
+ expect(of(p.ModelAdoptionOutcome.MODEL_ADOPTION_OUTCOME_IN_PROGRESS).isTerminal, isFalse);
190
+ expect(of(p.ModelAdoptionOutcome.MODEL_ADOPTION_OUTCOME_CURRENT).outcome, NomosModelAdoptionOutcome.current);
191
+ expect(of(p.ModelAdoptionOutcome.MODEL_ADOPTION_OUTCOME_ADOPTED).outcome, NomosModelAdoptionOutcome.adopted);
192
+ expect(of(p.ModelAdoptionOutcome.MODEL_ADOPTION_OUTCOME_PREVIEWED).outcome, NomosModelAdoptionOutcome.previewed);
193
+ expect(of(p.ModelAdoptionOutcome.MODEL_ADOPTION_OUTCOME_UNSPECIFIED).outcome, NomosModelAdoptionOutcome.inProgress);
194
+ expect(of(p.ModelAdoptionOutcome.MODEL_ADOPTION_OUTCOME_CURRENT).phase, NomosModelAdoptionPhase.stage);
195
+ expect(of(p.ModelAdoptionOutcome.MODEL_ADOPTION_OUTCOME_CURRENT).deferred, isNull);
196
+ });
197
+ });
198
+ }
@@ -0,0 +1,153 @@
1
+ // LOCAL-FIRST RESTART on the node peer: a workspace this peer ACQUIRED from a custodian is sealed into
2
+ // the peer's own Git custody after every frame, so a fresh process over the same custody reopens it
3
+ // with no custodian at all. This is the restart lane every device has; the reinstall lane
4
+ // (`reinstall()`) is the other one — empty custody, everything re-acquired from the custodian.
5
+ @TestOn('vm')
6
+ library;
7
+
8
+ import 'dart:io';
9
+
10
+ import 'package:nomos_client/src/nms_conformance_runtime.dart';
11
+ import 'package:test/test.dart';
12
+
13
+ import '../../../examples/co2-birth/build/application/co2_application/lib/src/generated/application.framework_calls.dart'
14
+ show nomosInternalApplicationFrameworkCalls;
15
+
16
+ String get _repoRoot => Directory.current.parent.parent.path;
17
+ String get _serverEntry =>
18
+ '$_repoRoot/platform-shells/node/local-development/server.ts';
19
+ String get _peerEntry => '$_repoRoot/platform-shells/node/stdio/entry.ts';
20
+ String get _co2LawUsdz => '$_repoRoot/examples/co2-birth/build/co2.law.usdz';
21
+ String get _runtimeDir =>
22
+ Platform.environment['NOMOS_CANDIDATE_RUNTIME'] ??
23
+ Platform.environment['NOMOS_DART_RUNTIME'] ??
24
+ Platform.environment['NOMOS_OFFLINE_RUNTIME'] ??
25
+ '${Platform.environment['HOME'] ?? ''}/.holon/runtime';
26
+
27
+ String? _missingPrereq() {
28
+ if (!File(_serverEntry).existsSync() || !File(_peerEntry).existsSync()) {
29
+ return 'the node shells are not in this checkout';
30
+ }
31
+ if (!File(_co2LawUsdz).existsSync()) {
32
+ return 'compile the fixture first: cd examples/co2-birth && npx nomos-compile';
33
+ }
34
+ for (final artifact in const [
35
+ 'holon.wasm',
36
+ 'kernel.repository.xml',
37
+ 'bootstrap.law.usdz',
38
+ 'nomos.law.usdz',
39
+ ]) {
40
+ if (!File('$_runtimeDir/$artifact').existsSync()) {
41
+ return 'point NOMOS_CANDIDATE_RUNTIME at a complete runtime bundle (missing $artifact)';
42
+ }
43
+ }
44
+ return null;
45
+ }
46
+
47
+ void main() {
48
+ test(
49
+ 'LOCAL-FIRST: an acquired Home survives the node peer restarting on its own custody, offline',
50
+ () async {
51
+ final skip = _missingPrereq();
52
+ if (skip != null) {
53
+ markTestSkipped(skip);
54
+ return;
55
+ }
56
+ final diagnostics = <String>[];
57
+ void log(String line) {
58
+ diagnostics.add(line);
59
+ printOnFailure(line);
60
+ }
61
+
62
+ final custody =
63
+ await Directory.systemTemp.createTemp('nomos-node-peer-custody-');
64
+ addTearDown(() => custody.delete(recursive: true));
65
+
66
+ final cloud = await NomosTestCloud.start(
67
+ serverEntry: _serverEntry,
68
+ platform: 'restart-platform',
69
+ lawUsdzPaths: [_co2LawUsdz],
70
+ applicationMaxChildWorkspacesPerUser: 5,
71
+ runtimeDirectory: _runtimeDir,
72
+ mintTrustRoot: true,
73
+ testIdentityProvider: true,
74
+ readyTimeout: const Duration(minutes: 4),
75
+ onDiagnostic: log,
76
+ );
77
+ addTearDown(cloud.stop);
78
+
79
+ final harness = await NomosTestHarness.cloudBound(
80
+ cloud: cloud,
81
+ lawUsdzPaths: [_co2LawUsdz],
82
+ platformWorkspace: 'restart-platform',
83
+ subject: 'user:restart-owner',
84
+ applicationFrameworkCalls: nomosInternalApplicationFrameworkCalls,
85
+ nodeEntry: _peerEntry,
86
+ nodePeerCustody: custody.path,
87
+ registerTearDown: addTearDown,
88
+ phaseTimeout: const Duration(minutes: 4),
89
+ onDiagnostic: log,
90
+ );
91
+ final home = harness.homeWorkspace!;
92
+ final headBeforeRestart = await harness.reception.head();
93
+ expect(headBeforeRestart, hasLength(40));
94
+ // Mounting proves readable residency. Retention is an asynchronous runtime
95
+ // effect: observe its durable Git frontier before simulating process loss.
96
+ // A repository directory alone can exist before any objects were saved.
97
+ final repository = '${custody.path}/custody/holon-$home.git';
98
+ final deadline = DateTime.now().add(const Duration(seconds: 30));
99
+ String retainedHead = '';
100
+ do {
101
+ final retained = await Process.run(
102
+ 'git',
103
+ ['--git-dir=$repository', 'rev-parse', '--verify', 'refs/heads/main'],
104
+ );
105
+ retainedHead =
106
+ retained.exitCode == 0 ? '${retained.stdout}'.trim() : '';
107
+ if (retainedHead == headBeforeRestart) break;
108
+ await Future<void>.delayed(const Duration(milliseconds: 50));
109
+ } while (DateTime.now().isBefore(deadline));
110
+ expect(retainedHead, headBeforeRestart,
111
+ reason:
112
+ 'the runtime must retain the acquired Home without a client save or sync call');
113
+
114
+ // The process ends; the custodian is not consulted again.
115
+ await harness.dispose();
116
+ await cloud.stop();
117
+
118
+ final restarted = await NodeRunnerTransport.start(
119
+ entry: _peerEntry,
120
+ arguments: [
121
+ '--runtime-bundle=$_runtimeDir',
122
+ if (cloud.testKRootPublic case final root?)
123
+ '--trust-root-public-key=$root',
124
+ '--custody=${custody.path}',
125
+ ],
126
+ onDiagnostic: log,
127
+ );
128
+ addTearDown(restarted.dispose);
129
+ final peer = DartReception(restarted);
130
+ await peer.ready.timeout(const Duration(seconds: 30));
131
+ await peer.bindSession(
132
+ workspace: home,
133
+ session: home,
134
+ );
135
+ // Binding names the interaction; its first local operation attaches retained
136
+ // custody. With the cloud stopped, verification cannot borrow remote state.
137
+ // A head-only (lazy history) Home verifies what is present and says its
138
+ // history is still materialising; it is never called broken.
139
+ final verdict = await peer.session(home).verifyChain();
140
+ expect(
141
+ verdict.valid ||
142
+ (verdict.hasHistory() && verdict.history.state == 'materialising'),
143
+ isTrue,
144
+ reason: 'verifyChain: valid=${verdict.valid} error=${verdict.error} '
145
+ 'history=${verdict.hasHistory() ? verdict.history.state : 'none'}',
146
+ );
147
+ expect(await peer.session(home).head(), equals(headBeforeRestart),
148
+ reason:
149
+ 'the Home reopens from local custody at the exact head it was sealed at');
150
+ },
151
+ timeout: const Timeout(Duration(minutes: 10)),
152
+ );
153
+ }