@githolon/dsl 0.108.7 → 0.110.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.
Files changed (308) 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 +80 -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 +214 -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 +268 -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 +23950 -15776
  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 +550 -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_event_desk_close_test.dart +16 -0
  74. package/dart/test/reception_span_trace_test.dart +23 -0
  75. package/dart/test/replica_readiness_test.dart +156 -0
  76. package/dart/test/runtime_projections_test.dart +92 -0
  77. package/dart/test/runtime_v2_gateway_test.dart +131 -0
  78. package/dart/test/signing_identity_kernel_test.dart +75 -0
  79. package/dart/test/sync_status_preparation_report_test.dart +29 -0
  80. package/dart/test/sync_status_reducer_test.dart +419 -0
  81. package/dart/test/test_harness_test.dart +71 -95
  82. package/dart/test/typed_query_watch_test.dart +170 -0
  83. package/dart/test/typed_watch_registry_test.dart +249 -0
  84. package/dart_lints/README.md +18 -0
  85. package/dart_lints/lib/nomos_lints.dart +70 -0
  86. package/dart_lints/pubspec.lock +580 -0
  87. package/dart_lints/pubspec.yaml +12 -0
  88. package/dart_lints/test/reference_identity_test.dart +75 -0
  89. package/dart_types/CHANGELOG.md +18 -0
  90. package/dart_types/lib/nomos_kernel_protocol.dart +21 -1
  91. package/dart_types/lib/nomos_types.dart +9 -1
  92. package/dart_types/lib/src/admission_decision.dart +37 -0
  93. package/dart_types/lib/src/aggregate_meta.dart +1 -1
  94. package/dart_types/lib/src/approved_model.dart +65 -0
  95. package/dart_types/lib/src/custody.dart +10 -18
  96. package/dart_types/lib/src/error_info.dart +4 -4
  97. package/dart_types/lib/src/errors.dart +29 -29
  98. package/dart_types/lib/src/foreign_ref.dart +62 -33
  99. package/dart_types/lib/src/local_work_rejected.dart +3 -3
  100. package/dart_types/lib/src/nomos_ref.dart +3 -1
  101. package/dart_types/lib/src/principal.dart +2 -2
  102. package/dart_types/lib/src/proto/google/protobuf/any.pb.dart +163 -0
  103. package/dart_types/lib/src/proto/google/protobuf/any.pbenum.dart +11 -0
  104. package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pb.dart +137 -0
  105. package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pbenum.dart +11 -0
  106. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +20721 -10433
  107. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +555 -27
  108. package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pb.dart +387 -0
  109. package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pbenum.dart +46 -0
  110. package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pb.dart +295 -0
  111. package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pbenum.dart +139 -0
  112. package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pb.dart +269 -0
  113. package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pbenum.dart +103 -0
  114. package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pb.dart +417 -0
  115. package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pbenum.dart +62 -0
  116. package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pb.dart +9968 -0
  117. package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pbenum.dart +133 -0
  118. package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pb.dart +204 -0
  119. package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pbenum.dart +54 -0
  120. package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pb.dart +1550 -0
  121. package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pbenum.dart +11 -0
  122. package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pb.dart +710 -0
  123. package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pbenum.dart +11 -0
  124. package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pb.dart +845 -0
  125. package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pbenum.dart +11 -0
  126. package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pb.dart +198 -0
  127. package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pbenum.dart +11 -0
  128. package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pb.dart +369 -0
  129. package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pbenum.dart +11 -0
  130. package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pb.dart +609 -0
  131. package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pbenum.dart +65 -0
  132. package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pb.dart +358 -0
  133. package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pbenum.dart +100 -0
  134. package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pb.dart +2231 -0
  135. package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pbenum.dart +271 -0
  136. package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pb.dart +1286 -0
  137. package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pbenum.dart +11 -0
  138. package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pb.dart +636 -0
  139. package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pbenum.dart +116 -0
  140. package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pb.dart +1637 -0
  141. package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pbenum.dart +175 -0
  142. package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pb.dart +1269 -0
  143. package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pbenum.dart +129 -0
  144. package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pb.dart +2782 -0
  145. package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pbenum.dart +97 -0
  146. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +2232 -8627
  147. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +0 -358
  148. package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pb.dart +1639 -0
  149. package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pbenum.dart +46 -0
  150. package/dart_types/lib/src/runtime_outcome.dart +133 -0
  151. package/dart_types/lib/src/subscriptions.dart +116 -23
  152. package/dart_types/pubspec.yaml +1 -1
  153. package/dart_types/test/extremum_subscriptions_test.dart +40 -0
  154. package/dart_types/test/foreign_ref_resolution_test.dart +75 -0
  155. package/dart_types/test/nomos_ref_address_test.dart +25 -0
  156. package/dart_types/test/ordered_subscriptions_test.dart +34 -0
  157. package/operation_contract_check.mjs +24 -0
  158. package/package.json +11 -6
  159. package/src/aggregate.ts +70 -10
  160. package/src/application_topology.ts +18 -11
  161. package/src/attested.ts +3 -0
  162. package/src/attested_core.ts +46 -3
  163. package/src/birth_meter_ensure.ts +19 -7
  164. package/src/births.ts +29 -4
  165. package/src/build_package.ts +140 -13
  166. package/src/business_birth.ts +181 -4
  167. package/src/codegen_call_proto.ts +1276 -0
  168. package/src/codegen_call_usda.ts +49 -6
  169. package/src/codegen_dart.ts +83 -44
  170. package/src/codegen_dart_client.ts +458 -800
  171. package/src/{codegen_dart_application.ts → codegen_dart_facade.ts} +331 -582
  172. package/src/codegen_dart_framework_calls.ts +320 -37
  173. package/src/codegen_dart_indexed_variant.ts +159 -0
  174. package/src/codegen_dart_scenario.ts +42 -13
  175. package/src/codegen_proof.ts +3 -3
  176. package/src/codegen_provider_dart.ts +5 -0
  177. package/src/codegen_query_proto.ts +158 -0
  178. package/src/codegen_refusal.ts +189 -0
  179. package/src/codegen_result_proto.ts +931 -0
  180. package/src/codegen_result_usda.ts +4 -0
  181. package/src/codegen_ts.ts +464 -616
  182. package/src/codegen_workspace_access.ts +105 -0
  183. package/src/compatibility_graph.ts +759 -0
  184. package/src/compatibility_usda.ts +264 -0
  185. package/src/compile_package_main.ts +2017 -1195
  186. package/src/custody_placement.ts +156 -0
  187. package/src/custody_placement_usda.ts +91 -0
  188. package/src/decl_shapes.ts +21 -2
  189. package/src/describe_model.ts +1 -0
  190. package/src/directive.ts +59 -2
  191. package/src/drivers.ts +51 -0
  192. package/src/engine_entry.ts +52 -8
  193. package/src/evolve_preview.ts +11 -4
  194. package/src/exists.ts +2 -0
  195. package/src/fields.ts +75 -11
  196. package/src/flow_gate.ts +2 -1
  197. package/src/framework/application_home.ts +170 -18
  198. package/src/framework/attested_receipts.ts +8 -3
  199. package/src/framework/auth_provider_law.ts +169 -9
  200. package/src/framework/birth_certificate_law.ts +4 -0
  201. package/src/framework/capability.ts +34 -3
  202. package/src/framework/child_authentication.ts +346 -0
  203. package/src/framework/console_governance.ts +295 -0
  204. package/src/framework/delegated_roles.ts +301 -0
  205. package/src/framework/domain_lifecycle.ts +26 -13
  206. package/src/framework/founding_genesis.ts +193 -0
  207. package/src/framework/framework_aggregates.ts +1 -1
  208. package/src/framework/genesis.ts +6 -1
  209. package/src/framework/governance_relations.ts +19 -0
  210. package/src/framework/home.ts +5 -734
  211. package/src/framework/legacy/child_auth_provider_epoch.ts +73 -0
  212. package/src/framework/model_authority_repair.ts +116 -0
  213. package/src/framework/model_authority_seed.ts +185 -0
  214. package/src/framework/model_transition.ts +211 -0
  215. package/src/framework/owned_custody.ts +1 -1
  216. package/src/framework/principal_enrollment.ts +302 -0
  217. package/src/framework/receiving_group.ts +857 -0
  218. package/src/framework/receiving_group_recovery.ts +314 -0
  219. package/src/framework/relations.ts +4 -8
  220. package/src/framework/signing_identity.ts +242 -95
  221. package/src/framework/source_roster.ts +11 -5
  222. package/src/framework/workspace_access.ts +149 -0
  223. package/src/framework/workspace_invariant.ts +73 -52
  224. package/src/framework/workspaces.ts +407 -40
  225. package/src/framework_call_definitions.ts +32 -3
  226. package/src/generated_client_bundle_boundary.ts +97 -0
  227. package/src/generated_client_names.ts +1 -0
  228. package/src/identity_usda.ts +27 -0
  229. package/src/index.ts +183 -12
  230. package/src/indexed_variant.ts +83 -0
  231. package/src/intent.ts +173 -45
  232. package/src/law_check.ts +8 -5
  233. package/src/law_dependency_index.ts +231 -0
  234. package/src/law_graph.ts +508 -71
  235. package/src/law_graph_usda.ts +170 -24
  236. package/src/law_identity.ts +119 -81
  237. package/src/law_source_map.ts +4 -1
  238. package/src/law_units.ts +498 -0
  239. package/src/law_value_type.ts +7 -3
  240. package/src/member_authentication.ts +302 -0
  241. package/src/null_meta.ts +1 -1
  242. package/src/openusd_compiled_layer.ts +132 -0
  243. package/src/operation_contract_check.ts +31 -0
  244. package/src/ordered_read.ts +2 -1
  245. package/src/package_config.ts +33 -12
  246. package/src/package_dependencies.ts +1 -0
  247. package/src/plan_source_slice.ts +30 -1
  248. package/src/protobuf_field_number.ts +36 -0
  249. package/src/provenance_wire.ts +6 -0
  250. package/src/query.ts +2 -1
  251. package/src/read.ts +50 -0
  252. package/src/relation.ts +4 -1
  253. package/src/relation_schema.ts +15 -2
  254. package/src/report.ts +2 -2
  255. package/src/sqlite_computation_bundle.ts +78 -0
  256. package/src/sqlite_computed.ts +102 -0
  257. package/src/sqlite_counts.ts +154 -0
  258. package/src/sqlite_layout.ts +823 -0
  259. package/src/sqlite_reads.ts +275 -0
  260. package/src/sqlite_samples.ts +185 -0
  261. package/src/stable_id_identity_bridge.ts +1 -1
  262. package/src/stable_ids_for_module.ts +16 -4
  263. package/src/test_call_usda.ts +6 -6
  264. package/src/usda_relationship_integrity.ts +20 -3
  265. package/src/usda_text.ts +21 -1
  266. package/src/value_object.ts +81 -11
  267. package/src/wire.ts +22 -0
  268. package/src/wire_encode.ts +227 -20
  269. package/src/workspace_sharding.ts +15 -6
  270. package/src/workspace_sharing.ts +51 -49
  271. package/src/zod_introspection.ts +2 -0
  272. package/compat_package.mjs +0 -46
  273. package/dart/lib/src/home.dart +0 -15
  274. package/dart/lib/src/runner/offline-install.mjs +0 -15367
  275. package/dart/lib/src/source_trust.dart +0 -51
  276. package/dart/lib/src/webview_bridge.dart +0 -6540
  277. package/dart/lib/src/workspace_name.dart +0 -30
  278. package/dart/test/acquire_session_credentials_test.dart +0 -150
  279. package/dart/test/acquire_session_test.dart +0 -534
  280. package/dart/test/adv_realm_interference_test.dart +0 -600
  281. package/dart/test/cloud_bound_topology_test.dart +0 -168
  282. package/dart/test/cluster_births_test.dart +0 -202
  283. package/dart/test/cluster_device_keyed_acceptance_test.dart +0 -105
  284. package/dart/test/cluster_local_autosync_test.dart +0 -123
  285. package/dart/test/cluster_scale_test.dart +0 -122
  286. package/dart/test/compat_test.dart +0 -61
  287. package/dart/test/dlq_session_surface_test.dart +0 -222
  288. package/dart/test/first_app_gauntlet_test.dart +0 -386
  289. package/dart/test/fixtures/wedge/fake-install.mjs +0 -11
  290. package/dart/test/four_layer_nested_topology_test.dart +0 -290
  291. package/dart/test/home_parity_test.dart +0 -13
  292. package/dart/test/local_sync_inert_test.dart +0 -107
  293. package/dart/test/node_runner_transport_test.dart +0 -78
  294. package/dart/test/parent_signer_recovery_test.dart +0 -155
  295. package/dart/test/residency_refusal_test.dart +0 -49
  296. package/dart/test/sealing_client_test.dart +0 -181
  297. package/dart/test/session_bound_test.dart +0 -285
  298. package/dart/test/stale_bundle_test.dart +0 -80
  299. package/dart/test/vo_read_typing_test.dart +0 -131
  300. package/dart/test/watch_after_offer_stall_test.dart +0 -100
  301. package/dart/test/webview_bridge_test.dart +0 -1930
  302. package/dart/test/workspace_name_test.dart +0 -24
  303. package/runtime/generated-application-host.js +0 -22860
  304. package/src/codegen_query_usda.ts +0 -214
  305. package/src/compat_manifest.ts +0 -26
  306. package/src/compat_package_main.ts +0 -224
  307. package/src/shape_compat.ts +0 -352
  308. 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
+ }