@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,122 +0,0 @@
1
- // SCALE SANITY — DART LEG (task #42). "A device holds dozens of live workspaces" is a TESTED truth here,
2
- // not a slogan: one bridge / one runner / ONE shared engine plane mounts ~20 local-only workspaces, each with
3
- // the SAME tenant law installed offline (one compiled fixture's deploy.json, reused N times — same law, N
4
- // distinct workspaces), then writes + reads each in isolation and asserts `listWorkspaces` surfaces all 20.
5
- //
6
- // This is the colocation architecture the shared engine plane (openRealm) exists for: N workspaces on ONE
7
- // wasm engine, not N engines. The suite is deliberately DOZENS (CI-friendly), not hundreds — enough to pin
8
- // the "many live workspaces per device" claim while completing in sane wall-clock time (asserted below).
9
- @TestOn('vm')
10
- library;
11
-
12
- import 'dart:io';
13
-
14
- import 'package:nomos_client/src/nms_conformance_runtime.dart';
15
- import 'package:nomos_types/nomos_kernel_protocol.dart' as protocol;
16
- import 'package:test/test.dart';
17
-
18
- String get _root => '${Directory.current.path}/../..';
19
- String get _repoEntry => '$_root/cloud/web-client/runner/node-entry.ts';
20
- String get _guestbookDeploy => '$_root/examples/guestbook/build/guestbook.law.usdz';
21
- String get _runtimeDir =>
22
- Platform.environment['NOMOS_DART_RUNTIME'] ??
23
- Platform.environment['NOMOS_OFFLINE_RUNTIME'] ??
24
- '${Platform.environment['HOME'] ?? ''}/.holon/runtime';
25
-
26
- /// How many colocated workspaces to open on the one plane. Dozens (CI-friendly), tunable via env for a
27
- /// heavier local soak (`NOMOS_SCALE_N=100 dart test test/cluster_scale_test.dart`).
28
- int get _n => int.tryParse(Platform.environment['NOMOS_SCALE_N'] ?? '') ?? 20;
29
-
30
- String? _missingPrereq() {
31
- if (!File(_repoEntry).existsSync()) return 'in-repo runner not found at $_repoEntry';
32
- if (!File(_guestbookDeploy).existsSync()) {
33
- return 'compile the guestbook example: cd examples/guestbook && npx nomos-compile — missing $_guestbookDeploy';
34
- }
35
- if (!File('$_runtimeDir/holon-testmint.wasm').existsSync() ||
36
- !File('$_runtimeDir/bootstrap.law.usdz').existsSync() ||
37
- !File('$_runtimeDir/nomos.law.usdz').existsSync()) {
38
- return 'warm ~/.holon/runtime first (run any `githolon` command once)';
39
- }
40
- return null;
41
- }
42
-
43
- void main() {
44
- test('a device holds dozens of live workspaces on ONE engine plane — write + read each, all listed',
45
- () async {
46
- final skip = _missingPrereq();
47
- if (skip != null) {
48
- markTestSkipped(skip);
49
- return;
50
- }
51
-
52
- final names = [for (var i = 0; i < _n; i++) 'ws-${i.toString().padLeft(2, '0')}'];
53
- // Same law (one deploy.json), N distinct workspaces — the exact "one device, many workspaces" shape.
54
- final workspaces = {for (final ws in names) ws: [_guestbookDeploy]};
55
-
56
- final sw = Stopwatch()..start();
57
- final harness = await NomosTestHarness.cluster(
58
- workspaces: workspaces,
59
- nodeEntry: _repoEntry,
60
- runtimeDir: _runtimeDir,
61
- // Installing + mounting N workspaces takes longer than the single-session default; give it headroom.
62
- readyTimeout: const Duration(seconds: 90),
63
- );
64
- final openMs = sw.elapsedMilliseconds;
65
- try {
66
- expect(harness.sessions.toSet(), names.toSet(),
67
- reason: 'all $_n workspaces connected as sessions on the one bridge');
68
-
69
- // WRITE one row into each workspace, keyed by its own name — so a cross-workspace read must come back
70
- // EMPTY (isolation) and the own-workspace read must return exactly the one row (no bleed on the plane).
71
- sw.reset();
72
- for (final ws in names) {
73
- await harness.session(ws).offerDirective(
74
- domain: 'guestbook',
75
- directiveId: 'signGuestbook',
76
- payload: {
77
- 'author': ws,
78
- 'message': 'hello from $ws',
79
- 'mood': 'delighted',
80
- 'signedAt': '2026-07-05T00:00:00Z',
81
- },
82
- actor: ws,
83
- );
84
- }
85
- final writeMs = sw.elapsedMilliseconds;
86
-
87
- // READ each back — the own author returns its single row; a foreign author returns nothing (isolation).
88
- sw.reset();
89
- for (final ws in names) {
90
- final own = await harness.session(ws).query('entriesByAuthor', {'author': ws});
91
- expect(own, hasLength(1), reason: '$ws holds exactly its own 1 row');
92
- expect(own.first['data']?['message'], 'hello from $ws');
93
-
94
- final foreign = names.firstWhere((o) => o != ws);
95
- final cross = await harness.session(ws).query('entriesByAuthor', {'author': foreign});
96
- expect(cross, isEmpty, reason: '$ws does NOT see $foreign\'s data — per-workspace isolation');
97
- }
98
- final readMs = sw.elapsedMilliseconds;
99
-
100
- // listWorkspaces enumerates the whole local plane — every one of the N is present + mounted.
101
- final listed = await harness.bridge.listWorkspaces();
102
- expect(listed.map((workspace) => workspace.session).toSet(), names.toSet(),
103
- reason: 'listWorkspaces surfaces all $_n live workspaces');
104
- expect(listed.every((workspace) => workspace.residency == protocol.WorkspaceResidency.WORKSPACE_RESIDENCY_MOUNTED), isTrue,
105
- reason: 'every listed workspace is mounted');
106
-
107
- // Wall-clock sanity — dozens of live workspaces must open + drive in a CI-sane budget, not minutes.
108
- // Generous ceilings (CI is slow); the point is "seconds per workspace is a bug", not a micro-benchmark.
109
- // ignore: avoid_print
110
- print('[scale] $_n workspaces: open+install ${openMs}ms, '
111
- 'write ${writeMs}ms (${(writeMs / _n).toStringAsFixed(1)}ms/ws), '
112
- 'read ${readMs}ms (${(readMs / _n).toStringAsFixed(1)}ms/ws)');
113
- expect(writeMs, lessThan(_n * 5000),
114
- reason: 'per-workspace write stays well under a 5s/ws ceiling (got ${(writeMs / _n).round()}ms/ws)');
115
- expect(readMs, lessThan(_n * 5000),
116
- reason: 'per-workspace read stays well under a 5s/ws ceiling (got ${(readMs / _n).round()}ms/ws)');
117
- } finally {
118
- await harness.dispose();
119
- }
120
- // The whole suite (open + install + write + read + teardown of N workspaces) completes in sane time.
121
- }, timeout: const Timeout(Duration(minutes: 10)));
122
- }
@@ -1,61 +0,0 @@
1
- // COMPAT SUPERPOWER (#72b) — the Dart mirror of `holon.compat`. NomosCompat.fromJson round-trips
2
- // the bridge's plain verdict snapshot; has() is the dark-launch feature flag over the per-member map.
3
- import 'package:nomos_client/src/nms_generated_runtime.dart';
4
- import 'package:test/test.dart';
5
-
6
- Map<String, Object?> verdict({
7
- required String v,
8
- required Map<String, Object?> members,
9
- String phase = 'Active',
10
- String? supersededBy,
11
- }) =>
12
- {
13
- 'generatedFor': 'a' * 64,
14
- 'workspaceRuns': ['b' * 64],
15
- 'matches': false,
16
- 'offerKnown': true,
17
- 'structurallyCompatible': v != 'incompatible',
18
- 'verdict': v,
19
- 'members': members,
20
- 'install': {'phase': phase, if (supersededBy != null) 'supersededBy': supersededBy},
21
- };
22
-
23
- void main() {
24
- test('fromJson parses the three-state verdict + per-member map + install phase', () {
25
- final c = NomosCompat.fromJson(verdict(
26
- v: 'degraded',
27
- members: {
28
- 'writeNote': {'ok': true},
29
- 'Note': {'ok': true},
30
- },
31
- phase: 'Superseded',
32
- supersededBy: 'c' * 64,
33
- ))!;
34
- expect(c.verdict, 'degraded');
35
- expect(c.offerKnown, isTrue);
36
- expect(c.structurallyCompatible, isTrue);
37
- expect(c.installPhase, 'Superseded');
38
- expect(c.supersededBy, 'c' * 64);
39
- expect(c.members.keys, containsAll(['writeNote', 'Note']));
40
- });
41
-
42
- test('has() is the feature flag — true for a compatible member, false otherwise', () {
43
- final c = NomosCompat.fromJson(verdict(
44
- v: 'incompatible',
45
- members: {
46
- 'writeNote': {'ok': false, 'reason': "workspace requires field 'sig' the client does not always send"},
47
- 'Note': {'ok': true},
48
- },
49
- ))!;
50
- // the served + compatible member lights up; the broken one + an unknown one stay dark
51
- expect(c.has('Note'), isTrue);
52
- expect(c.has('writeNote'), isFalse);
53
- expect(c.has('somethingElse'), isFalse);
54
- // the broken member still carries its reason (for the app to surface)
55
- expect(c.members['writeNote']!.reason, contains('sig'));
56
- });
57
-
58
- test('fromJson(null) is null (compat-less / pre-#72e)', () {
59
- expect(NomosCompat.fromJson(null), isNull);
60
- });
61
- }
@@ -1,222 +0,0 @@
1
- // THE DEAD-LETTER QUEUE FROM THE DART SESSION SURFACE (task #86 gap 7). The DLQ promise —
2
- // "refused-but-legitimate work is NEVER lost" — driven end-to-end through the Dart bridge:
3
- // real authored work (its full intent bytes, read back via the production `salvage` lane) is
4
- // parked as a dead letter on a workspace whose law cannot merge it (the exact shape a domain
5
- // rejection parks — same `deadLetter()` path the converge/recover lanes use), then:
6
- // deadLetters() surfaces it with provenance → retry REFUSES while the law is absent (the
7
- // entry stays, error refreshed) → the law fix ships (nomos/installDomain) → retry ADMITS and
8
- // the work lands, readable → a second entry is explicitly DISCARDED → the queue drains.
9
- // Fully offline (local-only sessions) — which is itself a regression: retryDeadLetter/
10
- // absorbSalvage used to throw "no remote main" on a local-only holon (fixed with this test).
11
- @TestOn('vm')
12
- library;
13
-
14
- import 'dart:async';
15
- import 'dart:convert';
16
- import 'dart:io';
17
-
18
- import 'package:nomos_client/src/nms_conformance_runtime.dart';
19
- import 'package:test/test.dart';
20
-
21
- String get _root => '${Directory.current.path}/../..';
22
- String get _repoEntry => '$_root/cloud/web-client/runner/node-entry.ts';
23
- String get _geoDeploy =>
24
- '$_root/bench/scale/fixtures/estate-geo/build/estate-geo.law.usdz';
25
- String get _docsDeploy =>
26
- '$_root/bench/scale/fixtures/surfaced/build/surfaced.law.usdz';
27
- String get _runtimeDir =>
28
- Platform.environment['NOMOS_DART_RUNTIME'] ??
29
- Platform.environment['NOMOS_OFFLINE_RUNTIME'] ??
30
- '${Platform.environment['HOME'] ?? ''}/.holon/runtime';
31
-
32
- String? _missingPrereq() {
33
- if (!File(_repoEntry).existsSync())
34
- return 'in-repo runner not found at $_repoEntry';
35
- for (final e in {
36
- _geoDeploy: 'bench/scale/fixtures/estate-geo',
37
- _docsDeploy: 'bench/scale/fixtures/surfaced',
38
- }.entries) {
39
- if (!File(e.key).existsSync()) {
40
- return 'missing fixture ${e.key} — compile it: (cd ${e.value} && node ../../../../dsl/compile_package.mjs)';
41
- }
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
- Future<T> _leg<T>(String name, Future<T> Function() body) async {
52
- final sw = Stopwatch()..start();
53
- // ignore: avoid_print
54
- print('▶ DLQ $name …');
55
- try {
56
- final r = await body();
57
- // ignore: avoid_print
58
- print('✔ DLQ $name (${sw.elapsedMilliseconds}ms)');
59
- return r;
60
- } catch (e, st) {
61
- throw TestFailure(
62
- 'DLQ $name FAILED after ${sw.elapsedMilliseconds}ms:\n$e\n$st');
63
- }
64
- }
65
-
66
- void main() {
67
- test(
68
- 'DLQ: park → surface → refused retry → law fix → retry admits → discard drains',
69
- () async {
70
- final missing = _missingPrereq();
71
- if (missing != null) {
72
- markTestSkipped(missing);
73
- return;
74
- }
75
- final harness = await NomosTestHarness.cluster(
76
- workspaces: {
77
- 'writer': [
78
- _geoDeploy
79
- ], // holds the estate law — where the work is authored
80
- 'app': [_docsDeploy], // the jammed workspace — NO estate law yet
81
- },
82
- nodeEntry: _repoEntry,
83
- runtimeDir: _runtimeDir,
84
- phaseTimeout: const Duration(seconds: 120),
85
- );
86
- try {
87
- final writer = harness.session('writer');
88
- final app = harness.session('app');
89
- final geoHash = harness.lawHashes('writer').first;
90
-
91
- // ── LEG 1: author REAL work under the estate law, and read its full intent bytes back
92
- // through the production salvage lane. ──
93
- final work = await _leg(
94
- 'leg 1: author two writes + salvage their intent bytes', () async {
95
- Future<void> place(String name) => writer.offerOutcome(
96
- domain: 'estate',
97
- directiveId: 'placeSite',
98
- payload: {
99
- 'name': name,
100
- 'point': {
101
- 'type': 'Point',
102
- 'coordinates': [-2.24, 53.48]
103
- },
104
- },
105
- actor: 'user:marta',
106
- domainHash: geoHash,
107
- );
108
- await place('a day of work I refuse to lose');
109
- await place('the second day');
110
- final s = await writer.salvage();
111
- final pending = ((s['pendingWrites'] as List?) ?? const [])
112
- .whereType<Map>()
113
- .map((m) => m.cast<String, Object?>())
114
- .where((w) {
115
- try {
116
- final doc =
117
- jsonDecode(utf8.decode(base64Decode(w['changeB64'].toString())))
118
- as Map;
119
- return (doc['payload'] as Map?)?['domain'] == 'estate';
120
- } catch (_) {
121
- return false;
122
- }
123
- }).toList();
124
- expect(pending, hasLength(2),
125
- reason:
126
- 'salvage() returns the authored estate intents with their full bytes');
127
- expect(pending.every((w) => (w['id'] ?? '').toString().isNotEmpty),
128
- isTrue);
129
- return pending;
130
- });
131
-
132
- // ── LEG 2: park both on the jammed workspace (the shape a domain rejection parks) and
133
- // assert deadLetters() surfaces them with full provenance. ──
134
- await _leg(
135
- 'leg 2: park as dead letters → deadLetters() surfaces provenance',
136
- () async {
137
- final r = await app.absorbSalvage(deadLetters: [
138
- for (final w in work)
139
- {
140
- 'id': w['id'],
141
- 'oid': w[
142
- 'id'], // provenance slot; the entry is deduped/looked up by id
143
- 'changeB64': w['changeB64'],
144
- 'source': 'local',
145
- 'error': "no active installed law declares domain 'estate'",
146
- }
147
- ]);
148
- expect(r['requeuedDeadLetters'], 2);
149
- final dead = await app.deadLetters();
150
- expect(dead, hasLength(2));
151
- final entry = dead.first;
152
- expect(entry.domain, 'estate',
153
- reason:
154
- 'the DLQ decodes domain/directiveId provenance from the parked bytes');
155
- expect(entry.directive, 'placeSite');
156
- expect(entry.source, 'local');
157
- });
158
-
159
- // ── LEG 3: retry while the law is still absent — a REFUSAL, not a loss (and, regression:
160
- // not a "no remote main" throw on this local-only session). ──
161
- final firstId = work.first['id'].toString();
162
- await _leg(
163
- 'leg 3: retry refuses while the law is absent; the entry stays',
164
- () async {
165
- final r = await app.retryDeadLetter(firstId);
166
- expect(r.retried, isFalse, reason: 'the law still cannot merge it: $r');
167
- final dead = await app.deadLetters();
168
- expect(dead, hasLength(2),
169
- reason: 'a refused retry NEVER drops the work');
170
- expect(dead.firstWhere((d) => d.hasId() && d.id == firstId).message,
171
- isNotEmpty,
172
- reason: 'the entry carries the fresh refusal');
173
- });
174
-
175
- // ── LEG 4: the domain dev ships the law fix; retry UNJAMS and the work lands, readable. ──
176
- await _leg(
177
- 'leg 4: law fix (installDomain) → retry admits → the work is on the ledger',
178
- () async {
179
- final usda = (jsonDecode(File(_geoDeploy).readAsStringSync())
180
- as Map)['packageUsda']
181
- .toString();
182
- await app.offerOutcome(
183
- domain: 'nomos',
184
- directiveId: 'installDomain',
185
- payload: {
186
- 'domainHash': geoHash,
187
- 'packageUsda': usda,
188
- 'installedBy': 'dlq-test-law-fix',
189
- 'dependencies': <Object?>[],
190
- 'finalizers': <Object?>[],
191
- },
192
- domainHash: harness.frameworkHash,
193
- );
194
- final r = await app.retryDeadLetter(firstId);
195
- expect(r.retried, isTrue, reason: 'the unjam after the law fix: $r');
196
- final dead = await app.deadLetters();
197
- expect(dead, hasLength(1),
198
- reason: 'the retried entry resolved out of the queue');
199
- final rows = await app
200
- .query('sitesByName', {'name': 'a day of work I refuse to lose'});
201
- expect(rows, hasLength(1),
202
- reason: "the user's work landed and reads back");
203
- });
204
-
205
- // ── LEG 5: discard is the app's explicit drop; the queue drains; a re-retry of a gone id
206
- // answers a typed refusal. ──
207
- await _leg('leg 5: discard drains; retry of a gone id refuses by name',
208
- () async {
209
- final secondId = work[1]['id'].toString();
210
- final d = await app.discardDeadLetter(secondId);
211
- expect(d.removed, 1);
212
- expect(await app.deadLetters(), isEmpty);
213
- final gone = await app.retryDeadLetter(secondId);
214
- expect(gone.retried, isFalse);
215
- expect(gone.message, contains('no dead letter'));
216
- });
217
- } finally {
218
- await harness.dispose().timeout(const Duration(seconds: 30),
219
- onTimeout: () => throw StateError('harness disposal hung'));
220
- }
221
- }, timeout: const Timeout(Duration(minutes: 6)));
222
- }