@githolon/dsl 0.108.6 → 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 +2083 -1248
  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,168 +0,0 @@
1
- // THE CLOUD-BOUND TOPOLOGY ACCEPTANCE (co2's exact 10-step ask) — the real-app shape end-to-end:
2
- //
3
- // 1. the remote platform births the home (the ONE control-plane contact — the authenticated ceremony);
4
- // 2. the app mounts the home locally (a normal cloud-bound NomosSession; co2-platform is never cloned);
5
- // 3. the network PARTITIONS (NomosTestCloud.setOnline(false));
6
- // 4. the home births the estate LOCALLY (`birthEstateWorkspace` — a `.births()` offer on this device);
7
- // 5. the estate opens as a sibling session and ACCEPTS LOCAL WRITES while offline;
8
- // 6. UI-facing queries return those writes immediately (no sync awaited, ever);
9
- // 7. the network HEALS;
10
- // 8. `harness.converge()` establishes remote custody PARENT-FIRST (the home's synced chain folds the
11
- // birth offer-effect remotely, creating the estate's custody; then the estate converges against it);
12
- // 9. a FRESH observer (the dev cloud's own remote projection) sees the estate writes;
13
- // 10. custody is REAL on both: remote heads born with commits (the dev cloud adopted the chains through
14
- // the same gate everything else uses — replay IS validation).
15
- //
16
- // Entirely inside the test cloud's trust universe: nothing here touches production K_root or custody.
17
- import 'dart:convert';
18
- import 'dart:io';
19
-
20
- import 'package:nomos_client/src/nms_conformance_runtime.dart';
21
- import 'package:test/test.dart';
22
-
23
- String get _root => '${Directory.current.path}/../..';
24
- String get _repoEntry => '$_root/cloud/web-client/runner/node-entry.ts';
25
- String get _devServer => '$_root/cloud/dev-server/server.ts';
26
- String get _deploy =>
27
- '$_root/bench/scale/fixtures/cloud-topology/build/cloud-topology.law.usdz';
28
- const _subject = 'user:topology-test';
29
-
30
- String? _missingPrereq() {
31
- if (!File(_repoEntry).existsSync())
32
- return 'in-repo runner not found at $_repoEntry';
33
- if (!File(_devServer).existsSync())
34
- return 'in-repo dev server not found at $_devServer';
35
- if (!File(_deploy).existsSync()) {
36
- return 'compile the fixture: cd bench/scale/fixtures/cloud-topology && node ../../../../dsl/compile_package.mjs — missing $_deploy';
37
- }
38
- return null;
39
- }
40
-
41
- void main() {
42
- test(
43
- 'the co2 topology: remote home ceremony → local estate birth offline → converge → remote custody',
44
- () async {
45
- final skip = _missingPrereq();
46
- if (skip != null) {
47
- markTestSkipped(skip);
48
- return;
49
- }
50
- final diag = Platform.environment['NOMOS_HARNESS_DIAG'] == '1'
51
- ? (String l) => stderr.writeln(l)
52
- : null;
53
- final cloud = await NomosTestCloud.start(
54
- serverEntry: _devServer,
55
- platform: 'topology-platform',
56
- lawUsdzPath: _deploy,
57
- applicationMaxChildWorkspacesPerUser: 8,
58
- onDiagnostic: diag);
59
- NomosTestHarness? harness;
60
- try {
61
- // 1+2 — the remote ceremony + the local mount, in one constructor (the app's boot path).
62
- harness = await NomosTestHarness.cloudBound(
63
- cloud: cloud,
64
- lawUsdzPaths: [_deploy],
65
- platformWorkspace: 'topology-platform',
66
- subject: _subject,
67
- nodeEntry: _repoEntry,
68
- onDiagnostic: diag,
69
- );
70
- final home = harness.homeSession;
71
- expect(home.workspace, isNotEmpty,
72
- reason:
73
- 'the generated ceremony resolved the receiving group without exposing its naming scheme');
74
- final remoteHome = await cloud.remoteHead(home.workspace);
75
- expect(remoteHome.initialized, isTrue,
76
- reason:
77
- 'the home was born REMOTELY (custody exists before the app ever mounted it)');
78
-
79
- // 3 — PARTITION.
80
- cloud.setOnline(false);
81
-
82
- // 4 — the home births the estate LOCALLY (the app lane never needs the network). The business
83
- // payload contains business facts only; law selection, signer seating and child addressing are
84
- // private consequences of the compiled birth declaration.
85
- final outcome = await harness.bridge.session(home.workspace).offerCreates(
86
- domain: 'home',
87
- directiveId: 'birthEstateWorkspace',
88
- payload: {
89
- 'owner': _subject,
90
- 'establishedAt': '2026-07-14T00:00:00Z',
91
- 'principal': _subject,
92
- 'bornAt': '2026-07-14T00:00:00Z',
93
- },
94
- actor: _subject,
95
- );
96
- expect(outcome.born, isNotEmpty,
97
- reason: 'the local .births() offer spawned the estate');
98
- final estateWs = outcome.born.single;
99
- expect(estateWs, startsWith('estate-'));
100
-
101
- // 5 — the estate opens as a sibling session and accepts a LOCAL WRITE while offline.
102
- final estate = await home.acquireSession(estateWs,
103
- authorSecret: harness.deviceSecret(home.workspace));
104
- final estateWrite = await estate.offerCreates(
105
- domain: 'estate',
106
- directiveId: 'writeEstateNote',
107
- payload: {
108
- 'author': _subject,
109
- 'body': 'written offline',
110
- 'writtenAt': '2026-07-14T00:00:01Z'
111
- },
112
- actor: _subject,
113
- );
114
-
115
- // 6 — the UI-facing query returns the write IMMEDIATELY (local projection; nothing awaited sync).
116
- final localRows =
117
- await estate.query('notesByAuthor', {'author': _subject});
118
- expect(localRows, hasLength(1));
119
- expect((localRows.single['data'] as Map)['body'], 'written offline');
120
-
121
- // …and the estate has NO remote custody yet — the partition is real.
122
- final remoteEstateOffline = await cloud.remoteHead(estateWs);
123
- expect(remoteEstateOffline.initialized, isFalse,
124
- reason:
125
- 'while partitioned, the locally-born estate must have NO remote custody');
126
-
127
- // 7+8 — HEAL. The generated runtime owns reconnect and parent/child custody ordering. Await the two
128
- // exact operation receipts; the test never calls sync(), names an endpoint or infers convergence.
129
- cloud.setOnline(true);
130
- await Future.wait([
131
- outcome.receipt.converged,
132
- estateWrite.receipt.converged,
133
- ]).timeout(const Duration(seconds: 180));
134
-
135
- // 9 — a FRESH observer: the dev cloud's own remote projection serves the estate write.
136
- final http = HttpClient();
137
- try {
138
- final req = await http.getUrl(Uri.parse(
139
- '${cloud.origin}/v2/workspaces/$estateWs/notesByAuthor?author=${Uri.encodeQueryComponent(_subject)}'));
140
- final resp = await req.close();
141
- final body = jsonDecode(await resp.transform(utf8.decoder).join());
142
- final rows = ((body as Map)['rows'] as List?) ?? const [];
143
- expect(rows, hasLength(1),
144
- reason:
145
- 'the remote projection (a fresh observer) serves the offline-written note after converge');
146
- expect(
147
- ((rows.single as Map)['data'] as Map)['body'], 'written offline');
148
- } finally {
149
- http.close(force: true);
150
- }
151
-
152
- // 10 — custody is REAL on both (the dev cloud adopted the chains through the one gate).
153
- final remoteHome2 = await cloud.remoteHead(home.workspace);
154
- final remoteEstate2 = await cloud.remoteHead(estateWs);
155
- expect(remoteHome2.initialized, isTrue);
156
- expect(remoteHome2.commits, greaterThan(0));
157
- expect(remoteEstate2.initialized, isTrue,
158
- reason:
159
- 'converge established the estate\'s remote custody (parent birth folded remotely)');
160
- expect(remoteEstate2.commits, greaterThan(0));
161
- } finally {
162
- try {
163
- await harness?.dispose();
164
- } catch (_) {}
165
- await cloud.stop();
166
- }
167
- }, timeout: const Timeout(Duration(minutes: 6)));
168
- }
@@ -1,202 +0,0 @@
1
- // LOCAL BIRTHS — DART LEG. An offline `.births()` directive dispatch: the estate-birth `home` law's
2
- // `birthEstateWorkspace` OFFERS a birth on THIS device's local plane — no cloud. Three things are proven:
3
- //
4
- // 1. THE DART API PATH: the offer surfaces the typed birth verdict — `born` (the child workspace name) +
5
- // `birthOutcomes` (the per-child fate) — off NomosOfferOutcome. A birth is observable from Dart.
6
- // 2. THE OFFLINE BIRTH SUCCEEDS (status=born): the child genesis (installDomain×2 + seed) folds through the
7
- // CHILD's own gate, fully offline. This needed a lane fix — the client holon's wasm provider now stages
8
- // the stage-0 bootstrap package at the preopen root (`/work/domain.package.usda`), the SAME file the
9
- // adapter engine stages, which `run_birth_effect` reads as the genesis-lane executor for the child's
10
- // step-0 `bootstrap/installDomain`. Without it the birth failed with "bare JavaScript is not a domain
11
- // package" (see cloud/web-client/src/kernel_provider_wasm.mjs boot).
12
- // 3. A FAILED birth carries a TYPED reason to Dart (deliberate bad framework hash) — never a silent drop.
13
- // 4. THE LOOP CLOSES (task #42): the born child OPENS as a sibling session on the SAME bridge and a typed
14
- // query INSIDE it returns the genesis-seeded row. This is the whole point — a local birth is not just
15
- // observable, it is USABLE: the child custody born in the parent session is resident in the shared
16
- // engine plane, so `bridge.connect(session: born)` mounts it IN-PLACE (no re-clone) and reads its seed.
17
- //
18
- // (HISTORICAL: this leg was once a NAMED GAP — before the runner ran openRealm, each session was its own
19
- // single-workspace engine, so a sibling session could not see custody born in another. The shared engine
20
- // plane closed it; the JS twin of this proof is cloud/web-client/test/realm.e2e.mjs T2.)
21
- @TestOn('vm')
22
- library;
23
-
24
- import 'dart:io';
25
-
26
- import 'package:nomos_client/src/nms_conformance_runtime.dart';
27
- import 'package:test/test.dart';
28
-
29
- String get _root => '${Directory.current.path}/../..';
30
- String get _repoEntry => '$_root/cloud/web-client/runner/node-entry.ts';
31
- String get _birthDeploy =>
32
- '$_root/bench/scale/fixtures/estate-birth/build/estate-birth.law.usdz';
33
- String get _runtimeDir =>
34
- Platform.environment['NOMOS_DART_RUNTIME'] ??
35
- Platform.environment['NOMOS_OFFLINE_RUNTIME'] ??
36
- '${Platform.environment['HOME'] ?? ''}/.holon/runtime';
37
-
38
- String? _missingPrereq() {
39
- if (!File(_repoEntry).existsSync()) return 'in-repo runner not found at $_repoEntry';
40
- if (!File(_birthDeploy).existsSync()) {
41
- return 'compile the fixture: cd bench/scale/fixtures/estate-birth && node ../../../../dsl/compile_package.mjs — missing $_birthDeploy';
42
- }
43
- if (!File('$_runtimeDir/holon-testmint.wasm').existsSync() ||
44
- !File('$_runtimeDir/bootstrap.law.usdz').existsSync() ||
45
- !File('$_runtimeDir/nomos.law.usdz').existsSync()) {
46
- return 'warm ~/.holon/runtime first (run any `githolon` command once)';
47
- }
48
- return null;
49
- }
50
-
51
- const _owner = 'sample-owner';
52
-
53
- /// Set up a single-session plane over the estate-birth law + OFFER `birthEstateWorkspace` on it. Returns the
54
- /// harness (for teardown) + the offer outcome (born / birthOutcomes surfaced). [frameworkHash] overrides the
55
- /// real framework hash (pass a bogus one to force a genesis failure).
56
- Future<(NomosTestHarness, NomosOfferOutcome)> _birth(
57
- {String? frameworkHash, void Function(NomosTestHarness)? onHarness}) async {
58
- final harness = await NomosTestHarness.ephemeral(
59
- lawUsdzPaths: [_birthDeploy],
60
- nodeEntry: _repoEntry,
61
- runtimeDir: _runtimeDir,
62
- workspace: 'estate-birth',
63
- );
64
- onHarness?.call(harness);
65
- // The genesis recipe installs the framework + child law BY HASH — the harness surfaces both (frameworkHash
66
- // is not derivable client-side; lawHash is this package's own domainHash).
67
- final fw = frameworkHash ?? harness.frameworkHash;
68
- final lawHash = harness.lawHashes('estate-birth').first;
69
- final outcome = await harness.bridge.offerCreates(
70
- domain: 'home',
71
- directiveId: 'birthEstateWorkspace',
72
- payload: {
73
- 'owner': _owner,
74
- 'frameworkHash': fw,
75
- 'lawHash': lawHash,
76
- 'bornAt': '2026-07-05T00:00:00Z',
77
- },
78
- actor: _owner,
79
- );
80
- return (harness, outcome);
81
- }
82
-
83
- void main() {
84
- test('offline .births() dispatch surfaces born + birthOutcomes TYPED to Dart', () async {
85
- final skip = _missingPrereq();
86
- if (skip != null) {
87
- markTestSkipped(skip);
88
- return;
89
- }
90
- final (harness, outcome) = await _birth();
91
- try {
92
- expect(outcome.head, isNotEmpty,
93
- reason: 'the birth offer admitted on the local plane');
94
- // THE API PATH (co2's ask): the birth verdict is typed back to Dart.
95
- expect(outcome.born, isNotEmpty,
96
- reason: 'the offer-effect allocated the estate child workspace on the local plane');
97
- expect(outcome.born.single, startsWith('estate-'),
98
- reason: 'the born workspace is estate-<sha256(owner)>');
99
- expect(outcome.birthOutcomes, isNotEmpty,
100
- reason: 'the typed birth verdict rides beside born');
101
- expect(outcome.birthOutcomes.first.workspace, outcome.born.single);
102
- expect(outcome.birthOutcomes.first.hasStatus(), isTrue);
103
-
104
- // The child handle is addressable on the plane (the loop that OPENS + reads it is the dedicated test
105
- // below — 'born child OPENS as a sibling session ...').
106
- expect(harness.bridge.session(outcome.born.single).workspace, outcome.born.single);
107
- } finally {
108
- await harness.dispose();
109
- }
110
- }, timeout: const Timeout(Duration(minutes: 3)));
111
-
112
- test('offline birth genesis SUCCEEDS (status=born) — the child is folded through its own gate', () async {
113
- final skip = _missingPrereq();
114
- if (skip != null) {
115
- markTestSkipped(skip);
116
- return;
117
- }
118
- final (harness, outcome) = await _birth();
119
- try {
120
- // The lane is fixed (the provider stages the stage-0 bootstrap package at the preopen root), so the
121
- // child genesis folds clean and the born verdict is `born` — hard-asserted, no skip.
122
- expect(outcome.born, hasLength(1));
123
- expect(outcome.birthOutcomes, hasLength(1));
124
- expect(outcome.birthOutcomes.first.status,
125
- NomosBirthOutcomeStatus.BIRTH_OUTCOME_STATUS_BORN,
126
- reason: 'the child genesis (installDomain×2 + seed) folded through the child\'s own gate offline');
127
- expect(outcome.birthOutcomes.first.workspace, outcome.born.single);
128
- } finally {
129
- await harness.dispose();
130
- }
131
- }, timeout: const Timeout(Duration(minutes: 3)));
132
-
133
- test('born child OPENS as a sibling session on the SAME bridge → typed query returns the seeded row (THE LOOP)',
134
- () async {
135
- final skip = _missingPrereq();
136
- if (skip != null) {
137
- markTestSkipped(skip);
138
- return;
139
- }
140
- final (harness, outcome) = await _birth();
141
- try {
142
- expect(outcome.birthOutcomes.first.status,
143
- NomosBirthOutcomeStatus.BIRTH_OUTCOME_STATUS_BORN,
144
- reason: 'precondition: the child is born on the local plane');
145
- final child = outcome.born.single;
146
-
147
- // THE LOOP CLOSES: open the born child as its OWN session on the SAME bridge. No `restoreFrom` — the
148
- // child custody is ALREADY resident in the shared engine plane (born in the parent session), so the
149
- // runner mounts it IN-PLACE (openRealm.workspace(child)), no re-clone. This is exactly realm.e2e T2.
150
- await harness.bridge.connect(workspace: child, session: child);
151
-
152
- // A typed query INSIDE the born child returns its genesis-seeded row — the estate the child's genesis
153
- // chain seeded via estate/seedEstateWorkspace, keyed on the owner (`estate-<sha256(owner)>` self-bound).
154
- final rows = await harness.bridge.session(child).query('estatesByOwner', {'owner': _owner});
155
- expect(rows, hasLength(1),
156
- reason: 'the born child\'s genesis seed reads back through its OWN session (the loop is closed)');
157
- expect(rows.first['data']?['owner'], _owner,
158
- reason: 'the seeded EstateOwner belongs to the birth\'s owner');
159
- expect(rows.first['data']?['estateName'], child,
160
- reason: 'the estate self-committed its own workspace name (estate-<sha256(owner)>)');
161
-
162
- // listWorkspaces now enumerates BOTH the parent and the newly-opened born child on the one plane.
163
- final listed = await harness.bridge.listWorkspaces();
164
- final sessions = listed.map((workspace) => workspace.session).toSet();
165
- expect(sessions, contains(child),
166
- reason: 'listWorkspaces surfaces the born child as a live session');
167
- expect(sessions, contains('estate-birth'),
168
- reason: 'the parent workspace is still listed alongside its born child');
169
- } finally {
170
- await harness.dispose();
171
- }
172
- }, timeout: const Timeout(Duration(minutes: 3)));
173
-
174
- test('birth FAILURE carries a typed reason to Dart (deliberate bad framework hash)', () async {
175
- final skip = _missingPrereq();
176
- if (skip != null) {
177
- markTestSkipped(skip);
178
- return;
179
- }
180
- // A well-formed but WRONG framework hash the parent does not fold → the child's step-0 install can't be
181
- // satisfied → the genesis fold refuses. The offer still admits on the parent (the birth ORDER is valid);
182
- // the child's fate FAILS FAST as the TYPED [BirthIncomplete] (both the JS holon and the bridge throw it
183
- // by design — a silent partial birth would strand the app polling head:null), carrying the per-child
184
- // typed outcome entries (workspace, status, code, reason) — never a stringly error or a silent drop.
185
- final badHash = 'deadbeef' * 8; // 64 hex chars, not a package the parent holds
186
- NomosTestHarness? harness;
187
- try {
188
- await _birth(frameworkHash: badHash, onHarness: (h) => harness = h);
189
- fail('an unresolvable framework hash must fail the birth (BirthIncomplete expected)');
190
- } on BirthIncomplete catch (e) {
191
- expect(e.failedBirths, isNotEmpty,
192
- reason: 'a failed birth still reports its typed per-child verdicts');
193
- expect(e.failedBirths.first.status,
194
- isNot(NomosBirthOutcomeStatus.BIRTH_OUTCOME_STATUS_BORN),
195
- reason: 'an unresolvable framework hash cannot yield a born child');
196
- expect(e.failedBirths.first.reason, isNotEmpty,
197
- reason: 'the failure carries a human-legible reason (never a silent drop)');
198
- } finally {
199
- await harness?.dispose();
200
- }
201
- }, timeout: const Timeout(Duration(minutes: 3)));
202
- }
@@ -1,105 +0,0 @@
1
- // CO2'S ACCEPTANCE (verbatim, 2026-07): `NomosTestHarness.cluster(deviceKeyed: …)` re-opens the keyed
2
- // session (keygen → keyed reconnect) and MUST NEVER hang — the reported wedge was phase 3b, the second
3
- // `connect` on an already-open session. Acceptance:
4
- // 1. cluster(..., deviceKeyed: {workspace}) completes (co2's exact shape: 4 sessions, one
5
- // deviceKeyed, colon-namespaced workspace names)
6
- // 2. devicePublicKey(workspace) is populated
7
- // 3. the keyed workspace remains readable and writable after the re-open
8
- // 4. harness disposal completes without being killed
9
- // Phase diagnostics (their ask 5) are asserted too: 3b logs enter/exit for keygen + keyed reconnect.
10
- @TestOn('vm')
11
- @Timeout(Duration(minutes: 3))
12
- library;
13
-
14
- import 'dart:io';
15
-
16
- import 'package:nomos_client/src/nms_conformance_runtime.dart';
17
- import 'package:test/test.dart';
18
-
19
- String get _root => '${Directory.current.path}/../..';
20
- String get _repoEntry => '$_root/cloud/web-client/runner/node-entry.ts';
21
- String get _catDeploy => '$_root/bench/scale/fixtures/catalogue-src/build/cat.law.usdz';
22
- String get _estateDeploy => '$_root/bench/scale/fixtures/catalogue-reader/build/estate.law.usdz';
23
- String get _runtimeDir =>
24
- Platform.environment['NOMOS_DART_RUNTIME'] ??
25
- Platform.environment['NOMOS_OFFLINE_RUNTIME'] ??
26
- '${Platform.environment['HOME'] ?? ''}/.holon/runtime';
27
-
28
- String? _missingPrereq() {
29
- if (!File(_repoEntry).existsSync()) return 'in-repo runner not found at $_repoEntry';
30
- for (final p in [_catDeploy, _estateDeploy]) {
31
- if (!File(p).existsSync()) return 'missing fixture $p (compile bench/scale/fixtures first)';
32
- }
33
- if (!File('$_runtimeDir/holon-testmint.wasm').existsSync() ||
34
- !File('$_runtimeDir/bootstrap.law.usdz').existsSync() ||
35
- !File('$_runtimeDir/nomos.law.usdz').existsSync()) {
36
- return 'warm ~/.holon/runtime first (run any `githolon` command once)';
37
- }
38
- return null;
39
- }
40
-
41
- void main() {
42
- test('cluster(deviceKeyed) completes: keyed re-open, device key populated, ordinary read/write, disposal',
43
- () async {
44
- final skip = _missingPrereq();
45
- if (skip != null) {
46
- markTestSkipped(skip);
47
- return;
48
- }
49
-
50
- const keyed = 'catalogue:test-catalogue';
51
- final log = <String>[];
52
- // 1. cluster construction with a deviceKeyed workspace COMPLETES (the reported hang was here).
53
- final harness = await NomosTestHarness.cluster(
54
- workspaces: {
55
- keyed: [_catDeploy],
56
- 'estate:a': [_estateDeploy],
57
- 'estate:b': [_estateDeploy],
58
- 'estate:c': [_estateDeploy],
59
- },
60
- deviceKeyed: {keyed},
61
- nodeEntry: _repoEntry,
62
- runtimeDir: _runtimeDir,
63
- onDiagnostic: log.add,
64
- );
65
- try {
66
- expect(harness.sessions.toSet(),
67
- {keyed, 'estate:a', 'estate:b', 'estate:c'});
68
-
69
- // 2. devicePublicKey is populated for the keyed session.
70
- final public = harness.devicePublicKey(keyed);
71
- expect(public, isNotNull);
72
- expect(public, isNotEmpty,
73
- reason: 'the 3b keygen public half must be recorded on the harness');
74
-
75
- // ask 5 — phase diagnostics: 3b logs enter AND exit for keygen + keyed reconnect.
76
- expect(log.any((l) => l.contains('3b: device keygen')), isTrue,
77
- reason: 'phase 3b keygen must log');
78
- expect(log.any((l) => l.contains("3b: keyed reconnect of '$keyed'") && l.contains('…')),
79
- isTrue, reason: 'phase 3b reconnect must log its enter line');
80
- expect(log.any((l) => l.contains("3b: keyed reconnect of '$keyed'") && l.contains('done')),
81
- isTrue, reason: 'phase 3b reconnect must log its exit line');
82
-
83
- // 3. The keyed re-open did not strand the session: its ordinary offer and read both work.
84
- final cat = harness.session(keyed);
85
- final seeded = await cat.offerCreates(
86
- domain: 'cat',
87
- directiveId: 'listCatalogue',
88
- payload: {
89
- 'listingId': 'L-1',
90
- 'title': 'Walnut desk',
91
- 'priceGbp': '900',
92
- 'listedAt': '2026-07-11T00:00:00Z',
93
- },
94
- actor: 'user:seller',
95
- );
96
- expect(seeded.head, isNotEmpty);
97
- final rows = await cat.query('listingById', {'listingId': 'L-1'});
98
- expect(rows, hasLength(1));
99
- expect(rows.single['id'], isNotEmpty);
100
- } finally {
101
- // 4. disposal completes (the harness deadline guarantees it can never wedge the test runner).
102
- await harness.dispose();
103
- }
104
- });
105
- }
@@ -1,123 +0,0 @@
1
- // CO2 ACCEPTANCE — local-only autoSync must not block the multi-workspace plane (their report, verbatim):
2
- // - Open multiple local-only sessions with NomosTestHarness.cluster.
3
- // - await homeSession.autoSync() completes promptly.
4
- // - await bridge.listWorkspaces() and a query on a sibling estate session still complete.
5
- // - stopAutoSync() and harness disposal complete.
6
- // - No local://.../intent-offers fetch attempts occur.
7
- // autoSync() REGISTERS background behavior and returns immediately; for a local-only (local://) session it
8
- // performs NO network work and must not monopolize the runner request dispatcher.
9
- @TestOn('vm')
10
- library;
11
-
12
- import 'dart:io';
13
-
14
- import 'package:nomos_client/src/nms_conformance_runtime.dart';
15
- import 'package:test/test.dart';
16
-
17
- String get _root => '${Directory.current.path}/../..';
18
- String get _repoEntry => '$_root/cloud/web-client/runner/node-entry.ts';
19
- String get _guestbookDeploy => '$_root/examples/guestbook/build/guestbook.law.usdz';
20
- String get _runtimeDir =>
21
- Platform.environment['NOMOS_DART_RUNTIME'] ??
22
- Platform.environment['NOMOS_OFFLINE_RUNTIME'] ??
23
- '${Platform.environment['HOME'] ?? ''}/.holon/runtime';
24
-
25
- String? _missingPrereq() {
26
- if (!File(_repoEntry).existsSync()) return 'in-repo runner not found at $_repoEntry';
27
- if (!File(_guestbookDeploy).existsSync()) {
28
- return 'compile the guestbook example: cd examples/guestbook && npx nomos-compile — missing $_guestbookDeploy';
29
- }
30
- if (!File('$_runtimeDir/holon-testmint.wasm').existsSync() ||
31
- !File('$_runtimeDir/bootstrap.law.usdz').existsSync() ||
32
- !File('$_runtimeDir/nomos.law.usdz').existsSync()) {
33
- return 'warm ~/.holon/runtime first (run any `githolon` command once)';
34
- }
35
- return null;
36
- }
37
-
38
- void main() {
39
- test(
40
- 'local-only autoSync() returns promptly, never fetches, and does not block the plane (co2 acceptance)',
41
- () async {
42
- final skip = _missingPrereq();
43
- if (skip != null) {
44
- markTestSkipped(skip);
45
- return;
46
- }
47
-
48
- // 1. Open multiple local-only sessions with NomosTestHarness.cluster (four, one bridge).
49
- final names = ['home', 'estate-a', 'estate-b', 'estate-c'];
50
- final diagnostics = <String>[];
51
- final harness = await NomosTestHarness.cluster(
52
- workspaces: {for (final ws in names) ws: [_guestbookDeploy]},
53
- nodeEntry: _repoEntry,
54
- runtimeDir: _runtimeDir,
55
- onDiagnostic: diagnostics.add,
56
- );
57
- try {
58
- final home = harness.session('home');
59
-
60
- // A realistic home holds local writes (ahead of any base) — this is what drives the up-leg machinery.
61
- await home.offerDirective(
62
- domain: 'guestbook',
63
- directiveId: 'signGuestbook',
64
- payload: {
65
- 'author': 'ada',
66
- 'message': 'offline write before autoSync',
67
- 'mood': 'delighted',
68
- 'signedAt': '2026-07-11T00:00:00Z',
69
- },
70
- actor: 'ada',
71
- );
72
-
73
- // 2. await homeSession.autoSync() completes promptly.
74
- await home.autoSync().timeout(const Duration(seconds: 10),
75
- onTimeout: () => throw StateError(
76
- 'autoSync() on a local-only session did not complete within 10s (the reported deadlock)'));
77
-
78
- // 3. await bridge.listWorkspaces() and a query on a sibling estate session still complete.
79
- final listed = await harness.bridge.listWorkspaces().timeout(
80
- const Duration(seconds: 10),
81
- onTimeout: () => throw StateError(
82
- 'listWorkspaces() hung after a local-only autoSync (dispatcher monopolized)'));
83
- expect(listed.map((workspace) => workspace.session).toSet(),
84
- containsAll(names.toSet()));
85
- final sibling = await harness
86
- .session('estate-a')
87
- .query('entriesByAuthor', {'author': 'nobody'}).timeout(
88
- const Duration(seconds: 10),
89
- onTimeout: () => throw StateError(
90
- 'a sibling estate query hung after a local-only autoSync'));
91
- expect(sibling, isEmpty);
92
-
93
- // Give any wrongly-registered background sync machinery time to fire so its fetch attempts would show.
94
- await Future<void>.delayed(const Duration(seconds: 2));
95
-
96
- // 4. stopAutoSync() and harness disposal complete (disposal asserted in finally / teardown).
97
- await home.stopAutoSync().timeout(const Duration(seconds: 10),
98
- onTimeout: () =>
99
- throw StateError('stopAutoSync() hung on a local-only session'));
100
-
101
- // Bonus (live-runner leg of the acquireSession DX ask): a mounted local workspace is acquired
102
- // WITHOUT credentials, and yields the same cached session handle.
103
- final acquired = await harness.bridge.acquireSession('estate-b',
104
- ifAbsentCredentials: () async =>
105
- fail('estate-b is mounted on the plane — credentials must not be requested'));
106
- expect(identical(acquired, harness.session('estate-b')), isTrue);
107
-
108
- // 5. No local://.../intent-offers fetch attempts occur (attempted-and-refused still counts as attempted).
109
- final offending = diagnostics
110
- .where((l) => l.contains('intent-offers') || l.contains('refusing network fetch'))
111
- .toList();
112
- expect(offending, isEmpty,
113
- reason:
114
- 'a local-only session must perform NO network work — saw:\n${offending.join('\n')}');
115
- } finally {
116
- await harness
117
- .dispose()
118
- .timeout(const Duration(seconds: 20), onTimeout: () {
119
- throw StateError('harness disposal hung (the reported teardown hang)');
120
- });
121
- }
122
- }, timeout: const Timeout(Duration(minutes: 3)));
123
- }