@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
@@ -1,534 +0,0 @@
1
- // acquireSession — the ATOMIC session-open (co2 DX ask): reuses a mounted session, opens a plane-resident
2
- // (parked / resident-custody) workspace locally, JOINS an in-flight open (single-flight per workspace), and
3
- // invokes the credentials callback ONLY when a cloud open is genuinely required. Proven hermetically over a
4
- // fake transport (the same style as webview_bridge_test.dart) — the live-runner leg rides
5
- // cluster_local_autosync_test.dart.
6
- import 'dart:async';
7
-
8
- import 'package:nomos_client/src/nms_generated_runtime.dart';
9
- import 'package:nomos_types/nomos_kernel_protocol.dart' as protocol;
10
- import 'package:test/test.dart';
11
-
12
- /// A fake runner: answers connect (after a real async gap, so concurrency is observable) and
13
- /// listWorkspaces (from [resident]); records every request.
14
- class FakeRunner implements BridgeTransport {
15
- final _incoming = StreamController<Map<String, Object?>>.broadcast();
16
- final List<Map<String, Object?>> sent = [];
17
- final List<protocol.RuntimeRequest> runtimeRequests = [];
18
- final List<String>
19
- resident; // workspaces the plane already holds (realm.list())
20
-
21
- FakeRunner({this.resident = const []}) {
22
- scheduleMicrotask(() => _incoming.add({
23
- 'v': kWebviewBridgeVersion,
24
- 'event': 'ready',
25
- 'bundleVersion': 'unbundled-dev'
26
- }));
27
- }
28
-
29
- int get connectCount => sent.where((m) => m['op'] == 'connect').length;
30
- int autoSyncCount(String workspace) => runtimeRequests
31
- .where((request) =>
32
- request.whichCommand() ==
33
- protocol.RuntimeRequest_Command.startAutoSync &&
34
- request.startAutoSync.session == workspace)
35
- .length;
36
- Map<String, Object?> connectArgs(int i) =>
37
- (sent.where((m) => m['op'] == 'connect').elementAt(i)['args'] as Map)
38
- .cast<String, Object?>();
39
-
40
- @override
41
- Stream<Map<String, Object?>> get messages => _incoming.stream;
42
-
43
- @override
44
- Future<protocol.RuntimeResponse> invokeRuntime(
45
- protocol.RuntimeRequest request,
46
- ) async {
47
- runtimeRequests.add(request.deepCopy());
48
- final response = protocol.RuntimeResponse(
49
- protocolVersion: 2,
50
- requestId: request.requestId,
51
- );
52
- switch (request.whichCommand()) {
53
- case protocol.RuntimeRequest_Command.listWorkspaces:
54
- final connected = sent
55
- .where((message) => message['op'] == 'connect')
56
- .map(
57
- (message) => ((message['args'] as Map)['workspace']).toString())
58
- .toSet();
59
- response.workspaceList = protocol.WorkspaceList(
60
- workspaces: [
61
- for (final workspace in {...resident, ...connected})
62
- protocol.WorkspaceSummary(
63
- session: workspace,
64
- workspace: workspace,
65
- residency: connected.contains(workspace)
66
- ? protocol.WorkspaceResidency.WORKSPACE_RESIDENCY_MOUNTED
67
- : protocol.WorkspaceResidency.WORKSPACE_RESIDENCY_PARKED,
68
- syncPosture: protocol
69
- .WorkspaceSyncPosture.WORKSPACE_SYNC_POSTURE_LOCAL_ONLY,
70
- ),
71
- ],
72
- );
73
- break;
74
- case protocol.RuntimeRequest_Command.startAutoSync:
75
- response.autoSyncStarted =
76
- protocol.AutoSyncStarted(session: request.startAutoSync.session);
77
- break;
78
- case protocol.RuntimeRequest_Command.stopAutoSync:
79
- response.autoSyncStopped =
80
- protocol.AutoSyncStopped(session: request.stopAutoSync.session);
81
- break;
82
- case protocol.RuntimeRequest_Command.closeRealm:
83
- response.realmClosed = protocol.RealmClosed();
84
- break;
85
- default:
86
- throw StateError(
87
- 'FakeRunner does not implement ${request.whichCommand().name}',
88
- );
89
- }
90
- return response;
91
- }
92
-
93
- @override
94
- void send(Map<String, Object?> message) {
95
- sent.add(message);
96
- final id = message['id'] as int;
97
- final op = message['op'] as String;
98
- final args = (message['args'] as Map).cast<String, Object?>();
99
- Future<void>.delayed(const Duration(milliseconds: 5), () {
100
- Object? result;
101
- switch (op) {
102
- case 'connect':
103
- result = {'workspace': args['workspace']};
104
- break;
105
- case 'listWorkspaces':
106
- // Realm truth: a CONNECTED workspace is mounted (holon live); a resident-but-unconnected one is
107
- // parked custody. Reflect connects so the derived lifecycle `state` is observable in both postures.
108
- final connected = sent
109
- .where((m) => m['op'] == 'connect')
110
- .map((m) => ((m['args'] as Map)['workspace']).toString())
111
- .toSet();
112
- final all = {...resident, ...connected};
113
- result = {
114
- 'workspaces': [
115
- for (final ws in all)
116
- {
117
- 'session': ws,
118
- 'workspace': ws,
119
- 'mounted': connected.contains(ws),
120
- 'parked': !connected.contains(ws) && resident.contains(ws),
121
- 'syncPosture': 'local-only'
122
- }
123
- ]
124
- };
125
- break;
126
- case 'snapshotWorkspace':
127
- result = {
128
- 'workspace': args['workspace'],
129
- 'head': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
130
- if (args['ifHead'] == 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
131
- 'unchanged': true
132
- else
133
- 'snapshot': 'resident-snapshot-b64',
134
- };
135
- break;
136
- default:
137
- result = {};
138
- }
139
- _incoming.add(
140
- {'v': kWebviewBridgeVersion, 'id': id, 'ok': true, 'result': result});
141
- });
142
- }
143
- }
144
-
145
- void main() {
146
- test(
147
- 'an already-connected session is reused — credentials NEVER invoked, no second connect',
148
- () async {
149
- final runner = FakeRunner();
150
- final bridge = NomosBridge(runner);
151
- await bridge.ready;
152
- await bridge.connect(workspace: 'home', session: 'home');
153
- expect(runner.connectCount, 1);
154
-
155
- final s = await bridge.acquireSession('home',
156
- ifAbsentCredentials: () async =>
157
- fail('credentials must not be requested for a mounted session'));
158
- expect(identical(s, bridge.session('home')), isTrue);
159
- expect(runner.connectCount, 1, reason: 'no re-connect for a live session');
160
- expect(runner.autoSyncCount('home'), 1,
161
- reason: 'an acquired application workspace continuously syncs');
162
- await bridge.dispose();
163
- });
164
-
165
- test(
166
- 'a plane-resident workspace binds retained cloud credentials so background sync owns it',
167
- () async {
168
- final runner = FakeRunner(resident: ['estate']);
169
- final bridge = NomosBridge(runner);
170
- await bridge.ready;
171
-
172
- var asked = false;
173
- final s =
174
- await bridge.acquireSession('estate', ifAbsentCredentials: () async {
175
- asked = true;
176
- return const NomosSessionCredentials(cloud: 'https://never.invalid');
177
- });
178
- expect(asked, isTrue,
179
- reason:
180
- 'a generated resident child must acquire its continuous cloud posture');
181
- expect(s.workspace, 'estate');
182
- expect(runner.connectCount, 1);
183
- expect(runner.connectArgs(0)['cloud'], 'https://never.invalid');
184
- await bridge.dispose();
185
- });
186
-
187
- test(
188
- 'concurrent acquisition SINGLE-FLIGHTS: one open, one credentials call, the same session',
189
- () async {
190
- final runner = FakeRunner();
191
- final bridge = NomosBridge(runner);
192
- await bridge.ready;
193
-
194
- var credentialCalls = 0;
195
- Future<NomosSessionCredentials> creds() async {
196
- credentialCalls++;
197
- await Future<void>.delayed(const Duration(milliseconds: 10));
198
- return const NomosSessionCredentials(
199
- cloud: 'https://cloud.example', authToken: 'tok', allowUnborn: true);
200
- }
201
-
202
- final results = await Future.wait([
203
- bridge.acquireSession('cloudy', ifAbsentCredentials: creds),
204
- bridge.acquireSession('cloudy', ifAbsentCredentials: creds),
205
- bridge.acquireSession('cloudy', ifAbsentCredentials: creds),
206
- ]);
207
- expect(credentialCalls, 1,
208
- reason: 'the credentials callback fires exactly once');
209
- expect(runner.connectCount, 1,
210
- reason: 'ONE connect for three concurrent acquires');
211
- expect(identical(results[0], results[1]), isTrue);
212
- expect(identical(results[1], results[2]), isTrue);
213
- expect(runner.autoSyncCount('cloudy'), 1,
214
- reason: 'the workspace lifecycle is single-flight too');
215
- final args = runner.connectArgs(0);
216
- expect(args['cloud'], 'https://cloud.example');
217
- expect(args['authToken'], 'tok');
218
- expect(args['allowUnborn'], isTrue);
219
- await bridge.dispose();
220
- });
221
-
222
- test(
223
- 'genuinely absent + no credentials callback → a named StateError (never a silent cloudless mount)',
224
- () async {
225
- final runner = FakeRunner();
226
- final bridge = NomosBridge(runner);
227
- await bridge.ready;
228
- await expectLater(bridge.acquireSession('nowhere'), throwsStateError);
229
- expect(runner.connectCount, 0);
230
- await bridge.dispose();
231
- });
232
-
233
- test(
234
- 'an absent generated child restores opaque local custody before cloud convergence',
235
- () async {
236
- final runner = FakeRunner();
237
- final bridge = NomosBridge(runner);
238
- await bridge.ready;
239
- var loads = 0;
240
- bridge.nomosInternalRetainLocalCustodyLoader((workspace) async {
241
- loads++;
242
- expect(workspace, 'catalogue');
243
- return 'opaque-kernel-snapshot';
244
- });
245
-
246
- final child = await bridge.acquireSession(
247
- 'catalogue',
248
- ifAbsentCredentials: () async => const NomosSessionCredentials(
249
- cloud: 'https://cloud.example',
250
- authToken: 'token',
251
- ),
252
- );
253
-
254
- expect(child.workspace, 'catalogue');
255
- expect(loads, 1);
256
- expect(runner.connectCount, 1);
257
- expect(runner.connectArgs(0)['restoreFrom'], 'opaque-kernel-snapshot');
258
- expect(runner.connectArgs(0)['cloud'], 'https://cloud.example');
259
- await bridge.dispose();
260
- });
261
-
262
- test('opaque local custody can open without inventing cloud authority',
263
- () async {
264
- final runner = FakeRunner();
265
- final bridge = NomosBridge(runner);
266
- await bridge.ready;
267
- bridge.nomosInternalRetainLocalCustodyLoader(
268
- (_) async => 'opaque-kernel-snapshot',
269
- );
270
-
271
- final child = await bridge.acquireSession('offline-child');
272
-
273
- expect(child.workspace, 'offline-child');
274
- expect(runner.connectCount, 1);
275
- final args = runner.connectArgs(0);
276
- expect(args['restoreFrom'], 'opaque-kernel-snapshot');
277
- expect(args.containsKey('cloud'), isFalse);
278
- await bridge.dispose();
279
- });
280
-
281
- test(
282
- 'a NomosSession delegates acquireSession to the parent plane (one registry)',
283
- () async {
284
- final runner = FakeRunner();
285
- final bridge = NomosBridge(runner);
286
- await bridge.ready;
287
- await bridge.connect(workspace: 'home', session: 'home');
288
- await bridge.connect(workspace: 'estate', session: 'estate');
289
-
290
- final viaSession = await bridge.session('home').acquireSession('estate',
291
- ifAbsentCredentials: () async =>
292
- fail('estate is already mounted — no credentials'));
293
- expect(identical(viaSession, bridge.session('estate')), isTrue);
294
- await bridge.dispose();
295
- });
296
-
297
- test('a resident child inherits its opening session identity', () async {
298
- final runner = FakeRunner(resident: ['child']);
299
- final bridge = NomosBridge(runner);
300
- await bridge.ready;
301
- await bridge.connect(
302
- workspace: 'home',
303
- session: 'home',
304
- authToken: 'header.eyJzdWIiOiJhZGEifQ.signature',
305
- );
306
-
307
- final child = await bridge.session('home').acquireSession('child');
308
-
309
- expect(child.principal, 'user:ada');
310
- await bridge.dispose();
311
- });
312
-
313
- test('an in-place signing-key refresh is inherited by later sibling opens',
314
- () async {
315
- final runner = FakeRunner(resident: ['catalogue', 'estate']);
316
- final bridge = NomosBridge(runner);
317
- await bridge.ready;
318
- await bridge.connect(workspace: 'home', session: 'home');
319
-
320
- await bridge
321
- .session('home')
322
- .refreshCredentials(authorSecret: 'newly-enrolled-device-key');
323
- await bridge.session('home').acquireSession('catalogue');
324
-
325
- expect(runner.connectCount, 2);
326
- expect(runner.connectArgs(1)['authorSecret'], 'newly-enrolled-device-key',
327
- reason:
328
- 'refreshing the resident holon must also advance the plane credential inherited by siblings');
329
-
330
- await bridge.session('home').refreshCredentials(authorSecret: '');
331
- await bridge.session('home').acquireSession('estate');
332
- expect(runner.connectArgs(2).containsKey('authorSecret'), isFalse,
333
- reason:
334
- 'clearing a resident signing key must not leak it into later sibling opens');
335
- await bridge.dispose();
336
- });
337
-
338
- test(
339
- 'generated child inherits typed model decisions and stages opaque USDZ privately',
340
- () async {
341
- final runner = FakeRunner(resident: ['child']);
342
- final bridge = NomosBridge(runner);
343
- await bridge.ready;
344
- await bridge.connect(
345
- workspace: 'home',
346
- session: 'home',
347
- authToken: 'header.eyJzdWIiOiJhZGEifQ.signature',
348
- );
349
- var handled = false;
350
- final home = bridge.session('home');
351
- home.nomosInternalRetainModelChangeHandler((change) async {
352
- handled = change.expectedDomainHash == 'candidate';
353
- });
354
- final child = await home.acquireSession('child');
355
- await home.nomosInternalEnsureGeneratedModelInChild(
356
- childWorkspace: 'child',
357
- domain: 'catalogue',
358
- candidateHash: 'candidate',
359
- lawUsdz: const [1, 2, 3],
360
- );
361
- await child.nomosInternalHandleModelChange(
362
- const DomainClientModelAdoptionRequired(
363
- expectedDomainKey: 'catalogue',
364
- expectedDomainHash: 'candidate',
365
- status: 'needs-decision',
366
- summary: 'review',
367
- review: DomainModelReview(
368
- checkedActions: 1,
369
- candidateActions: 1,
370
- sameOutcome: true,
371
- differences: [],
372
- ),
373
- ),
374
- );
375
- expect(handled, isTrue);
376
- final stage = runner.sent.singleWhere(
377
- (message) => message['op'] == 'stageGeneratedModelFromParent',
378
- );
379
- expect((stage['args'] as Map)['sourceSession'], 'home');
380
- expect((stage['args'] as Map)['session'], 'child');
381
- expect((stage['args'] as Map)['lawUsdz'], 'AQID');
382
- await home.nomosInternalStageGeneratedModel(
383
- domain: 'catalogue',
384
- candidateHash: 'candidate',
385
- lawUsdz: const [4, 5, 6],
386
- );
387
- final rootStage = runner.sent.singleWhere(
388
- (message) => message['op'] == 'stageGeneratedModel',
389
- );
390
- expect((rootStage['args'] as Map)['session'], 'home');
391
- expect((rootStage['args'] as Map)['lawUsdz'], 'BAUG');
392
- await bridge.dispose();
393
- });
394
-
395
- test(
396
- 'a generated application session privately refreshes cloud access for an absent referenced workspace',
397
- () async {
398
- final runner = FakeRunner();
399
- final bridge = NomosBridge(runner);
400
- await bridge.ready;
401
- await bridge.connect(
402
- cloud: 'https://cloud.example',
403
- workspace: 'home',
404
- session: 'home',
405
- authToken: 'header.eyJzdWIiOiJhZGEifQ.signature',
406
- authorSecret: 'device-secret',
407
- );
408
- var refreshes = 0;
409
- bridge.session('home').nomosInternalRetainCloudAccess(
410
- cloud: 'https://cloud.example',
411
- signIn: () async {
412
- refreshes += 1;
413
- return 'fresh-token-$refreshes';
414
- },
415
- );
416
-
417
- final target = await bridge.session('home').acquireSession('shared-home');
418
- expect(target.workspace, 'shared-home');
419
- expect(refreshes, 1);
420
- expect(runner.connectArgs(1)['cloud'], 'https://cloud.example');
421
- expect(runner.connectArgs(1)['authToken'], 'fresh-token-1');
422
- expect(runner.connectArgs(1)['authorSecret'], 'device-secret');
423
- expect(target.principal, 'user:ada');
424
-
425
- // The retained posture follows the opened handle, so navigation can continue without a public lane.
426
- final child = await target.acquireSession('shared-child');
427
- expect(child.workspace, 'shared-child');
428
- expect(refreshes, 2);
429
- expect(runner.connectArgs(2)['authToken'], 'fresh-token-2');
430
- await bridge.dispose();
431
- });
432
-
433
- // ── SESSION-STATE DX cluster (co2): explicit lifecycle state + fail-at-bind + openable refs ──
434
-
435
- test(
436
- 'listWorkspaces() reports explicit state: resident/parked before open, connected after',
437
- () async {
438
- final runner = FakeRunner(
439
- resident: ['estate']); // realm returns mounted:false, parked:true
440
- final bridge = NomosBridge(runner);
441
- await bridge.ready;
442
-
443
- // Before any connect: the plane-resident (parked) workspace surfaces with an explicit non-connected state.
444
- var list = await bridge.listWorkspaces();
445
- final before =
446
- list.firstWhere((workspace) => workspace.workspace == 'estate');
447
- expect(before.residency,
448
- protocol.WorkspaceResidency.WORKSPACE_RESIDENCY_PARKED,
449
- reason:
450
- 'parked custody is not connected — the app must acquire it first');
451
-
452
- // After connecting it, the SAME workspace reports connected.
453
- await bridge.connect(workspace: 'estate', session: 'estate');
454
- list = await bridge.listWorkspaces();
455
- final after =
456
- list.firstWhere((workspace) => workspace.workspace == 'estate');
457
- expect(after.residency,
458
- protocol.WorkspaceResidency.WORKSPACE_RESIDENCY_MOUNTED);
459
- await bridge.dispose();
460
- });
461
-
462
- test(
463
- 'plane snapshot exports resident custody without manufacturing a Dart session',
464
- () async {
465
- final runner = FakeRunner(resident: ['born-child']);
466
- final bridge = NomosBridge(runner);
467
- await bridge.ready;
468
-
469
- final saved = await bridge.nomosInternalSnapshotWorkspace('born-child');
470
- expect(saved.workspace, 'born-child');
471
- expect(saved.head, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
472
- expect(saved.snapshot, 'resident-snapshot-b64');
473
- expect(saved.unchanged, isFalse);
474
- expect(runner.connectCount, 0,
475
- reason:
476
- 'save-all must not acquire an unopened child or invent host authority');
477
-
478
- final unchanged = await bridge.nomosInternalSnapshotWorkspace('born-child',
479
- ifHead: saved.head);
480
- expect(unchanged.unchanged, isTrue);
481
- expect(unchanged.snapshot, isNull);
482
- expect(runner.connectCount, 0);
483
- await bridge.dispose();
484
- });
485
-
486
- test(
487
- 'NomosSession.isConnected + assertConnected: fail at BIND, not on first query',
488
- () async {
489
- final runner = FakeRunner();
490
- final bridge = NomosBridge(runner);
491
- await bridge.ready;
492
-
493
- // A held-but-unopened handle is valid to construct but not connected — assertConnected throws NOW.
494
- final lazy = bridge.session('estate');
495
- expect(lazy.isConnected, isFalse);
496
- expect(lazy.assertConnected, throwsStateError);
497
-
498
- await bridge.connect(workspace: 'estate', session: 'estate');
499
- final live = bridge.session('estate');
500
- expect(live.isConnected, isTrue);
501
- expect(live.assertConnected, returnsNormally);
502
- await bridge.dispose();
503
- });
504
-
505
- test(
506
- 'NomosRef.acquire(bridge) opens a born/resident ref directly → a live session',
507
- () async {
508
- final runner = FakeRunner(resident: ['estate-42']);
509
- final bridge = NomosBridge(runner);
510
- await bridge.ready;
511
-
512
- // The shape a `.births()` outcome yields: outcome.bornRefs.single is a NomosRef on the born workspace.
513
- final ref = NmsInternalNomosRefs.create<Object?>(
514
- workspace: 'estate-42', type: 'nomos.Workspace', id: 'estate-42');
515
- final session =
516
- await ref.acquire(bridge); // no credentials — resident opens local-only
517
- expect(session.workspace, 'estate-42');
518
- expect(session.isConnected, isTrue);
519
- expect(identical(session, bridge.session('estate-42')), isTrue);
520
- await bridge.dispose();
521
- });
522
-
523
- test(
524
- 'NomosRef.acquire refuses a workspace-less ref (a bad locator fails HERE, not later)',
525
- () async {
526
- final runner = FakeRunner();
527
- final bridge = NomosBridge(runner);
528
- await bridge.ready;
529
- final bad = NmsInternalNomosRefs.create<Object?>(
530
- workspace: '', type: 'nomos.Workspace', id: 'x');
531
- expect(() => bad.acquire(bridge), throwsArgumentError);
532
- await bridge.dispose();
533
- });
534
- }