@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
@@ -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
- }