@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
@@ -82,7 +82,10 @@ export class DomainSourceMap {
82
82
  private readonly texts = new Map<string, string | null>();
83
83
 
84
84
  /** `files` — the ORDERED module paths composing the domain (config order; first is the fallback anchor). */
85
- constructor(private readonly files: readonly string[]) {}
85
+ private readonly files: readonly string[];
86
+ constructor(files: readonly string[]) {
87
+ this.files = files;
88
+ }
86
89
 
87
90
  private text(file: string): string | null {
88
91
  if (!this.texts.has(file)) {
@@ -0,0 +1,498 @@
1
+ // D21c — per-domain law units, authored by the compiler.
2
+ //
3
+ // D21 (architecture/identity_target_model.md): law is installed per domain and composed by the
4
+ // kernel. The unit of law is one domain — its layer, its routes and the plans those routes name —
5
+ // content-addressed. The compiler only AUTHORS units. It may preview a composition (the coverage
6
+ // check below), but the composed stage and its projections are the kernel's to derive.
7
+ //
8
+ // Units are split from the package the compiler already emits, so today's package bytes and closure
9
+ // identity do not move, and the split is the one the kernel's `DomainLawUnit::split`
10
+ // (kernel/src/law_units.rs) makes from the same package, so both hash identically. The format is
11
+ // specified in architecture/law_units_format.md.
12
+
13
+ import { createHash } from "node:crypto";
14
+
15
+ /** One authenticated file of a law closure, at its package logical path. */
16
+ export interface LawUnitInputAsset {
17
+ readonly logicalPath: string;
18
+ readonly sha256: string;
19
+ readonly bytes: Uint8Array;
20
+ }
21
+
22
+ /** One route of the package route table: an execution selector naming one plan by hash. */
23
+ export interface LawUnitRoute {
24
+ readonly selector: string;
25
+ readonly planSha256: string;
26
+ }
27
+
28
+ export type LawUnitKind = "domain" | "framework" | "composition";
29
+
30
+ export interface LawUnitAsset {
31
+ readonly logicalPath: string;
32
+ readonly sha256: string;
33
+ readonly bytes: Uint8Array;
34
+ }
35
+
36
+ export interface LawUnit {
37
+ /** `framework`, `composition` or `domain:<d>` — kind-qualified, because a domain may itself be
38
+ * named like a reserved word or begin with `__`. */
39
+ readonly key: string;
40
+ readonly kind: LawUnitKind;
41
+ /** The domain, for a domain unit. */
42
+ readonly domain?: string;
43
+ /** sha256 over the unit's tagged, sorted inventory and route pairs (see `lawUnitHash`). */
44
+ readonly hash: string;
45
+ /** The unit's own routes, byte-ordered by selector. Typed pairs, not a file: the kernel's composer
46
+ * synthesizes the one `runtime/routes.usda` from the union of every installed unit's routes. */
47
+ readonly routes: readonly LawUnitRoute[];
48
+ /** Every file of the unit at its package logical path, byte-ordered. */
49
+ readonly assets: readonly LawUnitAsset[];
50
+ /** `unit.usda`: the unit's manifest (key, hash, inventory, routes). A carrier, never itself hashed. */
51
+ readonly manifest: Uint8Array;
52
+ }
53
+
54
+ export const FRAMEWORK_UNIT = "framework";
55
+ export const COMPOSITION_UNIT = "composition";
56
+ export const domainUnitKey = (domain: string): string => `domain:${domain}`;
57
+
58
+ export const LAW_UNIT_HASH_TAG = "nomos-law-unit-v1";
59
+ export const LAW_UNIT_FORMAT = "nomos.law-unit.v1";
60
+ export const LAW_UNIT_MANIFEST = "unit.usda";
61
+
62
+ /** Files of the package that the kernel synthesizes or derives from the installed units. */
63
+ const DERIVED_LOGICAL_PATHS = new Set([
64
+ "root.usda",
65
+ "runtime/routes.usda",
66
+ "runtime/composed-law.usdc",
67
+ "runtime/read-projection.usda",
68
+ "runtime/read-projection.usdc",
69
+ "runtime/command-projection.usda",
70
+ "runtime/command-projection.usdc",
71
+ ]);
72
+
73
+ /** Byte order on ASCII strings — the order Rust's `BTreeMap<String, _>` gives. */
74
+ const byteOrder = (left: string, right: string): number =>
75
+ left < right ? -1 : left > right ? 1 : 0;
76
+
77
+ const sha256Hex = (bytes: Uint8Array | string): string =>
78
+ createHash("sha256").update(bytes).digest("hex");
79
+
80
+ const utf8 = (text: string): Uint8Array => new TextEncoder().encode(text);
81
+
82
+ const DOMAIN_LAYER = /^domains\/([^/]+)\.usda$/;
83
+ const PLAN_FILE = /^runtime\/plans\/([0-9a-f]{64})\.(mjs|usda)$/;
84
+ const BASE_FILE = /^runtime\/bases\/([0-9a-f]{64})\.(mjs|usda)$/;
85
+
86
+ export const isDerivedLawPath = (logicalPath: string): boolean =>
87
+ DERIVED_LOGICAL_PATHS.has(logicalPath);
88
+
89
+ /** What a domain layer declares, for route ownership: its aggregates' `nomos:wireType` and
90
+ * `nomos:label` (prims `/Nomos/Domains/<d>/Aggregates/<a>`) and its invariants' `nomos:label`
91
+ * (prims `/Nomos/Domains/<d>/Invariants/<n>`) — the same prims the kernel's split reads. */
92
+ export interface DomainDeclarations {
93
+ readonly aggregateWireTypes: ReadonlySet<string>;
94
+ readonly aggregateLabels: ReadonlySet<string>;
95
+ readonly invariantLabels: ReadonlySet<string>;
96
+ }
97
+
98
+ /** Scan a compiler-authored domain layer for the declarations route ownership reads. The layer is
99
+ * emitted one opinion per line with each prim's braces on their own lines; a line ending `= {`
100
+ * opens a dictionary value (closed by its own `}`), which is not a prim. */
101
+ export function scanDomainDeclarations(usda: string): DomainDeclarations {
102
+ const aggregateWireTypes = new Set<string>();
103
+ const aggregateLabels = new Set<string>();
104
+ const invariantLabels = new Set<string>();
105
+ const frames: Array<string | null> = [];
106
+ let pendingPrim: string | null = null;
107
+ let body = false;
108
+ for (const raw of usda.split("\n")) {
109
+ const line = raw.trim();
110
+ const prim = /^(?:def|over|class)\b[^=]*?"([^"]+)"\s*(?:\(\s*)?$/.exec(line);
111
+ if (!body) {
112
+ // Skip the layer header `( ... )`: the body starts at the first prim.
113
+ if (prim === null) continue;
114
+ body = true;
115
+ }
116
+ if (prim !== null) {
117
+ pendingPrim = prim[1]!;
118
+ continue;
119
+ }
120
+ if (line === "{") {
121
+ frames.push(pendingPrim);
122
+ pendingPrim = null;
123
+ continue;
124
+ }
125
+ if (line === "}") {
126
+ frames.pop();
127
+ continue;
128
+ }
129
+ if (line.endsWith("= {")) {
130
+ frames.push(null);
131
+ continue;
132
+ }
133
+ const property = /\bnomos:(wireType|label) = ("(?:[^"\\]|\\.)*")$/.exec(line);
134
+ if (property === null) continue;
135
+ if (frames.includes(null)) continue;
136
+ const at = frames as string[];
137
+ if (at.length !== 5 || at[0] !== "Nomos" || at[1] !== "Domains") continue;
138
+ const value = JSON.parse(property[2]!) as string;
139
+ if (at[3] === "Aggregates") {
140
+ (property[1] === "wireType" ? aggregateWireTypes : aggregateLabels).add(value);
141
+ } else if (at[3] === "Invariants" && property[1] === "label") {
142
+ invariantLabels.add(value);
143
+ }
144
+ }
145
+ return { aggregateWireTypes, aggregateLabels, invariantLabels };
146
+ }
147
+
148
+ /** The unit key that owns a route. A domain's own plan and offers belong to it. A report on one
149
+ * subject belongs to the one domain that declares that subject: an aggregate (by `nomos:wireType`,
150
+ * else by `nomos:label`) for `aggregateInvariant` / `combine` / `derive`, an invariant (by
151
+ * `nomos:label`) for `workspaceInvariant` / `workspaceInvariantReads`. Everything else — `describe`,
152
+ * `report:report:*`, `report:invariant:*`, and any subject declared by no domain or by several —
153
+ * spans the composed set and belongs to the composition. */
154
+ export function routeOwner(
155
+ selector: string,
156
+ declarations: ReadonlyMap<string, DomainDeclarations>
157
+ ): string {
158
+ // Exactly the kernel's `selector_domain`: everything after `plan:domain:`, or the text between
159
+ // `plan:offer:` and the next `:`.
160
+ const domainPlan = /^plan:domain:(.*)$/s.exec(selector);
161
+ if (domainPlan !== null) return domainUnitKey(domainPlan[1]!);
162
+ const offer = /^plan:offer:([^:]*):/.exec(selector);
163
+ if (offer !== null) return domainUnitKey(offer[1]!);
164
+ const declaring = (
165
+ pick: (d: DomainDeclarations) => ReadonlySet<string>,
166
+ subject: string
167
+ ): string[] =>
168
+ [...declarations].filter(([, d]) => pick(d).has(subject)).map(([domain]) => domain);
169
+ const aggregate = /^report:(?:aggregateInvariant|combine|derive):(.*)$/s.exec(selector);
170
+ if (aggregate !== null) {
171
+ const subject = aggregate[1]!;
172
+ let owners = declaring((d) => d.aggregateWireTypes, subject);
173
+ if (owners.length === 0) owners = declaring((d) => d.aggregateLabels, subject);
174
+ return owners.length === 1 ? domainUnitKey(owners[0]!) : COMPOSITION_UNIT;
175
+ }
176
+ const invariant = /^report:(?:workspaceInvariant|workspaceInvariantReads):(.*)$/s.exec(selector);
177
+ if (invariant !== null) {
178
+ const owners = declaring((d) => d.invariantLabels, invariant[1]!);
179
+ return owners.length === 1 ? domainUnitKey(owners[0]!) : COMPOSITION_UNIT;
180
+ }
181
+ return COMPOSITION_UNIT;
182
+ }
183
+
184
+ /** The directory a unit is written to: its key with `:` made path-portable, then its hash. */
185
+ export const lawUnitDirectoryName = (unit: Pick<LawUnit, "key" | "hash">): string =>
186
+ `${unit.key.replace(":", "-")}-${unit.hash}`;
187
+
188
+ /** The package's `runtime/routes.usda`: every route, one prim each, in selector collation order. Also
189
+ * rebuilt from the emitted law units by their coverage preview below, which proves the units
190
+ * carry exactly the package's routes. */
191
+ export function packageRoutesLayerUsda(routes: readonly LawUnitRoute[]): string {
192
+ const routeOpinions: string[] = [
193
+ "#usda 1.0",
194
+ "(",
195
+ " customLayerData = {",
196
+ ' string "nomos:format" = "nomos.law-layer.v3"',
197
+ ' string "nomos:logicalPath" = "runtime/routes"',
198
+ " }",
199
+ ")",
200
+ "",
201
+ 'def Scope "__NomosRuntime_7e9c"',
202
+ "{",
203
+ ' custom string nomos:kind = "runtime"',
204
+ ' custom string nomos:format = "nomos.openusd-plan-metadata.v3"',
205
+ "",
206
+ ' def Scope "Routes"',
207
+ " {",
208
+ ];
209
+ [...routes]
210
+ .sort((left, right) => left.selector.localeCompare(right.selector))
211
+ .forEach((route, index) => {
212
+ routeOpinions.push(
213
+ ` def Scope "r${String(index).padStart(6, "0")}"`,
214
+ " {",
215
+ ` custom string nomos:selector = ${JSON.stringify(
216
+ route.selector
217
+ )}`,
218
+ ` custom string nomos:plan = "${route.planSha256}"`,
219
+ " }",
220
+ ""
221
+ );
222
+ });
223
+ if (routeOpinions[routeOpinions.length - 1] === "") routeOpinions.pop();
224
+ routeOpinions.push(" }", "}", "");
225
+ return routeOpinions.join("\n");
226
+ }
227
+
228
+ /** Unit identity — agreed with the kernel's `DomainLawUnit` (kernel/src/law_units.rs):
229
+ * sha256("nomos-law-unit-v1\0" key "\0" "assets\0" (logicalPath "\0" sha256 "\0")*
230
+ * "routes\0" (selector "\0" planSha256 "\0")*), assets by logical path and routes by
231
+ * selector, each in byte order, digests lowercase hex. */
232
+ export function lawUnitHash(
233
+ key: string,
234
+ inventory: readonly { readonly logicalPath: string; readonly sha256: string }[],
235
+ routes: readonly LawUnitRoute[]
236
+ ): string {
237
+ const hash = createHash("sha256");
238
+ hash.update(`${LAW_UNIT_HASH_TAG}\0`);
239
+ hash.update(key);
240
+ hash.update("\0");
241
+ hash.update("assets\0");
242
+ for (const asset of [...inventory].sort((l, r) => byteOrder(l.logicalPath, r.logicalPath))) {
243
+ hash.update(asset.logicalPath);
244
+ hash.update("\0");
245
+ hash.update(asset.sha256);
246
+ hash.update("\0");
247
+ }
248
+ hash.update("routes\0");
249
+ for (const route of [...routes].sort((l, r) => byteOrder(l.selector, r.selector))) {
250
+ hash.update(route.selector);
251
+ hash.update("\0");
252
+ hash.update(route.planSha256);
253
+ hash.update("\0");
254
+ }
255
+ return hash.digest("hex");
256
+ }
257
+
258
+ function unitManifestUsda(unit: Omit<LawUnit, "manifest">): string {
259
+ return [
260
+ "#usda 1.0",
261
+ "(",
262
+ ' defaultPrim = "__NomosLawUnit_7e9c"',
263
+ " customLayerData = {",
264
+ ` string "nomos:format" = "${LAW_UNIT_FORMAT}"`,
265
+ " }",
266
+ ")",
267
+ "",
268
+ 'def NomosLawUnit "__NomosLawUnit_7e9c"',
269
+ "{",
270
+ ` custom string nomos:unit = ${JSON.stringify(unit.key)}`,
271
+ ` custom token nomos:unitKind = "${unit.kind}"`,
272
+ ...(unit.domain === undefined
273
+ ? []
274
+ : [` custom string nomos:domain = ${JSON.stringify(unit.domain)}`]),
275
+ ` custom string nomos:unitHash = "${unit.hash}"`,
276
+ "",
277
+ ' def Scope "Assets"',
278
+ " {",
279
+ ...unit.assets.flatMap((asset) => [
280
+ ` def NomosLawAsset "a_${sha256Hex(asset.logicalPath)}"`,
281
+ " {",
282
+ ` custom string nomos:logicalPath = ${JSON.stringify(asset.logicalPath)}`,
283
+ ` custom string nomos:sha256 = "${asset.sha256}"`,
284
+ " }",
285
+ ]),
286
+ " }",
287
+ "",
288
+ ' def Scope "Routes"',
289
+ " {",
290
+ ...unit.routes.flatMap((route) => [
291
+ ` def NomosLawRoute "s_${sha256Hex(route.selector)}"`,
292
+ " {",
293
+ ` custom string nomos:selector = ${JSON.stringify(route.selector)}`,
294
+ ` custom string nomos:plan = "${route.planSha256}"`,
295
+ " }",
296
+ ]),
297
+ " }",
298
+ "}",
299
+ "",
300
+ ].join("\n");
301
+ }
302
+
303
+ /** Split an emitted package into its law units: one per domain layer, the framework unit
304
+ * (`framework.usda`, byte-identical in every package) and the composition unit (`package.usda`, the
305
+ * package-specific runtime bases, and the routes that span domains). A plan travels in every unit
306
+ * whose routes name it: units are content-addressed, so a shared plan is one blob in git. */
307
+ export function splitLawUnits(
308
+ closureAssets: readonly LawUnitInputAsset[],
309
+ routes: readonly LawUnitRoute[]
310
+ ): LawUnit[] {
311
+ const fail = (message: string): never => {
312
+ throw new Error(`law units: ${message}`);
313
+ };
314
+ const byPath = new Map<string, LawUnitInputAsset>();
315
+ for (const asset of closureAssets) {
316
+ if (byPath.has(asset.logicalPath)) fail(`duplicate package path '${asset.logicalPath}'`);
317
+ if (sha256Hex(asset.bytes) !== asset.sha256) {
318
+ fail(`'${asset.logicalPath}' bytes do not match its declared sha256`);
319
+ }
320
+ byPath.set(asset.logicalPath, asset);
321
+ }
322
+ interface Member {
323
+ kind: LawUnitKind;
324
+ domain?: string;
325
+ paths: Set<string>;
326
+ routes: LawUnitRoute[];
327
+ }
328
+ const members = new Map<string, Member>();
329
+ const unit = (key: string, kind: LawUnitKind, domain?: string): Member => {
330
+ let entry = members.get(key);
331
+ if (entry === undefined) {
332
+ entry = { kind, ...(domain === undefined ? {} : { domain }), paths: new Set(), routes: [] };
333
+ members.set(key, entry);
334
+ }
335
+ return entry;
336
+ };
337
+ unit(FRAMEWORK_UNIT, "framework");
338
+ unit(COMPOSITION_UNIT, "composition");
339
+ const declarations = new Map<string, DomainDeclarations>();
340
+ const planHashes = new Set<string>();
341
+ for (const [logicalPath, asset] of byPath) {
342
+ if (DERIVED_LOGICAL_PATHS.has(logicalPath)) continue;
343
+ const domain = DOMAIN_LAYER.exec(logicalPath);
344
+ if (domain !== null) {
345
+ const name = domain[1]!;
346
+ unit(domainUnitKey(name), "domain", name).paths.add(logicalPath);
347
+ declarations.set(name, scanDomainDeclarations(new TextDecoder().decode(asset.bytes)));
348
+ continue;
349
+ }
350
+ const plan = PLAN_FILE.exec(logicalPath);
351
+ if (plan !== null) {
352
+ planHashes.add(plan[1]!);
353
+ continue;
354
+ }
355
+ if (logicalPath === "framework.usda") {
356
+ unit(FRAMEWORK_UNIT, "framework").paths.add(logicalPath);
357
+ continue;
358
+ }
359
+ if (logicalPath === "package.usda" || BASE_FILE.test(logicalPath)) {
360
+ unit(COMPOSITION_UNIT, "composition").paths.add(logicalPath);
361
+ continue;
362
+ }
363
+ fail(`package file '${logicalPath}' is neither unit law nor a known derived projection`);
364
+ }
365
+ const seenSelectors = new Set<string>();
366
+ const referencedPlans = new Set<string>();
367
+ for (const route of routes) {
368
+ if (seenSelectors.has(route.selector)) fail(`selector '${route.selector}' is routed twice`);
369
+ seenSelectors.add(route.selector);
370
+ const owner = routeOwner(route.selector, declarations);
371
+ const entry = members.get(owner);
372
+ if (entry === undefined) {
373
+ return fail(`route '${route.selector}' names '${owner}', which has no domain layer`);
374
+ }
375
+ for (const extension of ["mjs", "usda"]) {
376
+ const planPath = `runtime/plans/${route.planSha256}.${extension}`;
377
+ if (!byPath.has(planPath)) fail(`route '${route.selector}' names missing '${planPath}'`);
378
+ entry.paths.add(planPath);
379
+ }
380
+ entry.routes.push(route);
381
+ referencedPlans.add(route.planSha256);
382
+ }
383
+ for (const plan of planHashes) {
384
+ if (!referencedPlans.has(plan)) fail(`plan '${plan}' is in the package but no route names it`);
385
+ }
386
+ return [...members]
387
+ .sort(([left], [right]) => byteOrder(left, right))
388
+ .map(([key, entry]) => {
389
+ const unitRoutes = [...entry.routes].sort((l, r) => byteOrder(l.selector, r.selector));
390
+ const assets: LawUnitAsset[] = [...entry.paths].sort(byteOrder).map((logicalPath) => {
391
+ const asset = byPath.get(logicalPath)!;
392
+ return { logicalPath, sha256: asset.sha256, bytes: asset.bytes };
393
+ });
394
+ const withoutManifest = {
395
+ key,
396
+ kind: entry.kind,
397
+ ...(entry.domain === undefined ? {} : { domain: entry.domain }),
398
+ hash: lawUnitHash(key, assets, unitRoutes),
399
+ routes: unitRoutes,
400
+ assets,
401
+ };
402
+ return { ...withoutManifest, manifest: utf8(unitManifestUsda(withoutManifest)) };
403
+ });
404
+ }
405
+
406
+ /** The compiler's composition PREVIEW: prove that the units cover exactly the package's non-derived
407
+ * law. Every domain layer, framework layer, base and plan of the package is in some unit and nothing
408
+ * else is; a path held by two units is a plan, byte-identical in both; every route is held by exactly
409
+ * one unit, its owner, and names a plan that unit carries; every plan a unit carries is named by one
410
+ * of its routes; and the union of unit routes rebuilds the package's own `runtime/routes.usda` byte
411
+ * for byte. Throws on the first discrepancy. A check only — never a shipped composition. */
412
+ export function assertLawUnitsCoverPackage(
413
+ units: readonly LawUnit[],
414
+ closureAssets: readonly LawUnitInputAsset[],
415
+ routes: readonly LawUnitRoute[]
416
+ ): void {
417
+ const fail = (message: string): never => {
418
+ throw new Error(`law unit coverage: ${message}`);
419
+ };
420
+ const declarations = new Map<string, DomainDeclarations>();
421
+ for (const asset of closureAssets) {
422
+ const domain = DOMAIN_LAYER.exec(asset.logicalPath);
423
+ if (domain !== null) {
424
+ declarations.set(domain[1]!, scanDomainDeclarations(new TextDecoder().decode(asset.bytes)));
425
+ }
426
+ }
427
+ const keys = new Set<string>();
428
+ const union = new Map<string, string>();
429
+ const unionRoutes = new Map<string, string>();
430
+ for (const unit of units) {
431
+ if (keys.has(unit.key)) fail(`unit '${unit.key}' appears twice`);
432
+ keys.add(unit.key);
433
+ if (lawUnitHash(unit.key, unit.assets, unit.routes) !== unit.hash) {
434
+ fail(`unit '${unit.key}' hash does not match its inventory and routes`);
435
+ }
436
+ const own = new Map(unit.assets.map((asset) => [asset.logicalPath, asset] as const));
437
+ if (own.size !== unit.assets.length) fail(`unit '${unit.key}' lists a path twice`);
438
+ const namedPlans = new Set<string>();
439
+ for (const route of unit.routes) {
440
+ if (unionRoutes.has(route.selector)) fail(`selector '${route.selector}' is held by two units`);
441
+ if (routeOwner(route.selector, declarations) !== unit.key) {
442
+ fail(`unit '${unit.key}' holds route '${route.selector}', which it does not own`);
443
+ }
444
+ unionRoutes.set(route.selector, route.planSha256);
445
+ for (const extension of ["mjs", "usda"]) {
446
+ if (!own.has(`runtime/plans/${route.planSha256}.${extension}`)) {
447
+ fail(`unit '${unit.key}' route '${route.selector}' names a plan the unit does not carry`);
448
+ }
449
+ }
450
+ namedPlans.add(route.planSha256);
451
+ }
452
+ for (const asset of unit.assets) {
453
+ if (sha256Hex(asset.bytes) !== asset.sha256) {
454
+ fail(`unit '${unit.key}' '${asset.logicalPath}' bytes do not match`);
455
+ }
456
+ const plan = PLAN_FILE.exec(asset.logicalPath);
457
+ if (plan !== null && !namedPlans.has(plan[1]!)) {
458
+ fail(`unit '${unit.key}' carries plan '${plan[1]}' that none of its routes name`);
459
+ }
460
+ const prior = union.get(asset.logicalPath);
461
+ if (prior !== undefined && prior !== asset.sha256) fail(`'${asset.logicalPath}' differs between units`);
462
+ if (prior !== undefined && plan === null) {
463
+ fail(`'${asset.logicalPath}' is held by two units (only plans may be shared)`);
464
+ }
465
+ union.set(asset.logicalPath, asset.sha256);
466
+ }
467
+ }
468
+ const expected = new Map(
469
+ closureAssets
470
+ .filter((asset) => !DERIVED_LOGICAL_PATHS.has(asset.logicalPath))
471
+ .map((asset) => [asset.logicalPath, asset.sha256] as const)
472
+ );
473
+ for (const [logicalPath, sha256] of expected) {
474
+ const held = union.get(logicalPath);
475
+ if (held === undefined) fail(`package file '${logicalPath}' is in no unit`);
476
+ if (held !== sha256) fail(`package file '${logicalPath}' differs in its unit`);
477
+ }
478
+ for (const logicalPath of union.keys()) {
479
+ if (!expected.has(logicalPath)) fail(`unit file '${logicalPath}' is not package law`);
480
+ }
481
+ if (unionRoutes.size !== routes.length) {
482
+ fail(`units hold ${unionRoutes.size} routes; the package has ${routes.length}`);
483
+ }
484
+ for (const route of routes) {
485
+ if (unionRoutes.get(route.selector) !== route.planSha256) {
486
+ fail(`route '${route.selector}' is not held as the package routes it`);
487
+ }
488
+ }
489
+ const packageRoutes = closureAssets.find((asset) => asset.logicalPath === "runtime/routes.usda");
490
+ if (packageRoutes !== undefined) {
491
+ const rebuilt = packageRoutesLayerUsda(
492
+ [...unionRoutes].map(([selector, planSha256]) => ({ selector, planSha256 }))
493
+ );
494
+ if (sha256Hex(rebuilt) !== packageRoutes.sha256) {
495
+ fail("the units' routes do not rebuild the package's runtime/routes.usda");
496
+ }
497
+ }
498
+ }
@@ -1,6 +1,6 @@
1
1
  import type { z } from "zod";
2
2
  import { enumTypeNameOf } from "./enum_type.js";
3
- import { isGitObjectIdSchema, isSha256DigestSchema } from "./fields.js";
3
+ import { isGitObjectIdSchema, isSha256DigestSchema, type GeometryKind } from "./fields.js";
4
4
  import { recipientMetaOf } from "./recipient.js";
5
5
  import {
6
6
  NOMOS_UNIT_BRAND,
@@ -45,7 +45,8 @@ export interface LawValueMember {
45
45
  */
46
46
  export type LawValueSemantic =
47
47
  | { readonly kind: "sha256-digest" | "git-object-id" }
48
- | { readonly kind: "branded-id" | "unit" | "value-object"; readonly name: string }
48
+ | { readonly kind: "branded-id" | "unit"; readonly name: string }
49
+ | { readonly kind: "value-object"; readonly name: string; readonly geometry?: GeometryKind }
49
50
  | { readonly kind: "recipient"; readonly subject: "User" }
50
51
  | {
51
52
  readonly kind: "id-reference" | "address-reference";
@@ -234,7 +235,10 @@ function semanticOf(schema: z.ZodTypeAny): LawValueSemantic | undefined {
234
235
  const unit = (schema as unknown as Record<symbol, unknown>)[NOMOS_UNIT_BRAND];
235
236
  if (typeof unit === "string") return { kind: "unit", name: unit };
236
237
  const valueObject = voMetaOf(schema);
237
- if (valueObject !== undefined) return { kind: "value-object", name: valueObject.name };
238
+ if (valueObject !== undefined) return {
239
+ kind: "value-object", name: valueObject.name,
240
+ ...(valueObject.geometry === undefined ? {} : { geometry: valueObject.geometry }),
241
+ };
238
242
  return undefined;
239
243
  }
240
244