@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
@@ -0,0 +1,275 @@
1
+ /** Coverage of declared reads, not authorization or production-read readiness.
2
+ * The input is the complete composed LawGraph, never tenant source-name switches.
3
+ */
4
+ import type { LawGraph, LawReadNode, LawFieldPathRef } from "./law_graph.js";
5
+ import type { SqliteLayout, SqliteSlot, SqliteValue } from "./sqlite_layout.js";
6
+ type Nodes = ReadonlyMap<string, LawGraph["nodes"][number]>;
7
+ export interface SqliteQueryPlan {
8
+ sid: string;
9
+ name: string;
10
+ keys: { path: string[]; kind: "string" | "integer" | "boolean" }[];
11
+ index: string;
12
+ ddl: string;
13
+ sql: string;
14
+ }
15
+ const literal = (s: string) => `'${s.replaceAll("'", "''")}'`;
16
+ type Scalar = { sql: string; kind: "string" | "integer" | "boolean" };
17
+ // Expressions are made only from generated column ordinals and quoted literals.
18
+ // SQLite maintains expression indexes transactionally; no second key store.
19
+ export function scalarSlot(slot: SqliteSlot, tail: readonly string[]): Scalar {
20
+ if (slot.surfaced)
21
+ throw Error("Surfaced query keys need observed-value indexing");
22
+ const result = scalarValue(slot.value, tail);
23
+ return {
24
+ ...result,
25
+ sql: `CASE WHEN c${slot.presence}=2 THEN ${result.sql} END`,
26
+ };
27
+ }
28
+ function scalarValue(value: SqliteValue, tail: readonly string[]): Scalar {
29
+ if (value.kind === "object" && tail.length) {
30
+ const member = value.members?.find((m) => m.name === tail[0]);
31
+ if (!member) throw Error(`missing nested member ${tail[0]}`);
32
+ return scalarSlot(member, tail.slice(1));
33
+ }
34
+ if (value.kind === "union" && tail.length) {
35
+ const arms = value.variants!.flatMap((arm, i) => {
36
+ // The nominal sum encoder puts its tag in `type`; SQL stores the ordinal.
37
+ if (tail.length === 1 && tail[0] === "type")
38
+ return [{ i, sql: literal(arm.label), kind: "string" as const }];
39
+ if (!arm.value.members?.some((m) => m.name === tail[0])) {
40
+ if (
41
+ arm.value.members
42
+ ?.find((m) => m.name === "value")
43
+ ?.value.members?.some((m) => m.name === tail[0])
44
+ )
45
+ throw Error(
46
+ "named sum payload path differs from authored path; typed-path resolution required"
47
+ );
48
+ return [];
49
+ }
50
+ return [{ i, ...scalarValue(arm.value, tail) }];
51
+ });
52
+ if (!arms.length) throw Error(`no sum arm has ${tail.join(".")}`);
53
+ if (arms.some((a) => a.kind !== arms[0]!.kind))
54
+ throw Error("query path has incompatible sum-arm scalar kinds");
55
+ return {
56
+ kind: arms[0]!.kind,
57
+ sql: `CASE c${value.column} ${arms
58
+ .map((a) => `WHEN ${a.i} THEN ${a.sql}`)
59
+ .join(" ")} END`,
60
+ };
61
+ }
62
+ if (tail.length)
63
+ throw Error(`indexed traversal through ${value.kind} is not implemented`);
64
+ if (
65
+ !["string", "integer", "boolean"].includes(value.kind) ||
66
+ value.column === undefined
67
+ )
68
+ throw Error(`query key ${value.kind} requires a separate index capability`);
69
+ return { kind: value.kind as Scalar["kind"], sql: `c${value.column}` };
70
+ }
71
+ export function planSqliteQueries(
72
+ nodes: Nodes,
73
+ aggregateId: string,
74
+ layout: Pick<SqliteLayout, "table" | "wireType" | "fields">
75
+ ) {
76
+ const plans: SqliteQueryPlan[] = [],
77
+ refusals: { sid: string; reason: string }[] = [];
78
+ for (const read of [...nodes.values()].filter(
79
+ (n): n is LawReadNode =>
80
+ n.kind === "read" && n.readKind === "query" && n.of.id === aggregateId
81
+ )) {
82
+ if (read.readKind !== "query") continue;
83
+ try {
84
+ if (read.predicate) throw Error("filtered query is not implemented");
85
+ if (!/^[a-f0-9]+$/i.test(read.entity.sid))
86
+ throw Error("unsafe read identity");
87
+ if (!read.key.length) throw Error("empty query key");
88
+ if (read.key.length + 1 > 2000)
89
+ throw Error("query index exceeds 2000-column SQLite target");
90
+ const keys = read.key.map((k) => {
91
+ const path = k.authoredPath.split(".");
92
+ const field = layout.fields.find((f) => f.name === path[0]);
93
+ if (!field) throw Error(`unmapped key ${k.authoredPath}`);
94
+ return { path, ...scalarSlot(field, path.slice(1)) };
95
+ });
96
+ const type = layout.fields.find((f) => f.name === "__type")!;
97
+ const archive = layout.fields.find((f) => f.name === "__archived");
98
+ if (!archive) throw Error("archive metadata not mapped");
99
+ // COALESCE handles absent archive cells (SQL NULL is not FALSE).
100
+ const guard = `c${type.presence}=2 AND c${type.value.column}=${literal(
101
+ layout.wireType
102
+ )} AND COALESCE(c${archive.value.column},0)<>1`;
103
+ const index = `r_${read.entity.sid.toLowerCase()}`;
104
+ plans.push({
105
+ sid: read.entity.sid,
106
+ name: read.entity.label,
107
+ keys: keys.map(({ path, kind }) => ({ path, kind })),
108
+ index,
109
+ ddl: `CREATE INDEX ${index} ON ${layout.table}(${keys
110
+ .map((k) => k.sql)
111
+ .join(",")},id) WHERE ${guard};`,
112
+ sql: `SELECT id FROM ${
113
+ layout.table
114
+ } INDEXED BY ${index} WHERE ${guard} AND ${keys
115
+ .map((k, i) => `(${k.sql})=?${i + 1}`)
116
+ .join(" AND ")} AND id>?${keys.length + 1} ORDER BY id LIMIT ?${
117
+ keys.length + 2
118
+ }`,
119
+ });
120
+ } catch (error) {
121
+ refusals.push({ sid: read.entity.sid, reason: (error as Error).message });
122
+ }
123
+ }
124
+ return { plans: plans.sort((a, b) => a.sid.localeCompare(b.sid)), refusals };
125
+ }
126
+ export function readFields(read: LawReadNode): readonly LawFieldPathRef[] {
127
+ switch (read.readKind) {
128
+ case "query":
129
+ return read.key;
130
+ case "count":
131
+ case "exists":
132
+ return read.groupBy ? [read.groupBy] : [];
133
+ case "sum":
134
+ case "min":
135
+ case "max":
136
+ return [read.value, ...(read.groupBy ? [read.groupBy] : [])];
137
+ case "ordered":
138
+ return [read.orderBy];
139
+ case "spatial":
140
+ return [read.geometry];
141
+ case "combined":
142
+ return [read.via];
143
+ case "temporalEnum":
144
+ return [read.source];
145
+ case "derived":
146
+ return [];
147
+ }
148
+ }
149
+ export function inspectSqliteReads(
150
+ nodes: Nodes,
151
+ layouts: readonly SqliteLayout[]
152
+ ) {
153
+ const reads = [...nodes.values()]
154
+ .filter((n): n is LawReadNode => n.kind === "read")
155
+ .map((read) => {
156
+ const aggregate = nodes.get(read.of.id),
157
+ domain = nodes.get(read.domain.id);
158
+ if (aggregate?.kind !== "aggregate" || domain?.kind !== "domain")
159
+ throw Error("read owner missing from compiled graph");
160
+ const layout = layouts.find(
161
+ (p) => p.aggregateSid === aggregate.entity.sid
162
+ );
163
+ const fields = readFields(read).map((p) => {
164
+ const field = aggregate.fields
165
+ .map((f) => nodes.get(f.id))
166
+ .find((f) => f?.entity.label === p.authoredPath.split(".")[0]);
167
+ return {
168
+ path: p.authoredPath,
169
+ fieldId: p.field.id,
170
+ storage: field?.kind === "field" ? field.storageKind : "unknown",
171
+ drivers:
172
+ field?.kind === "field"
173
+ ? field.mergeDrivers.map((d) => d.kind)
174
+ : [],
175
+ };
176
+ });
177
+ const spatial =
178
+ read.readKind === "spatial" &&
179
+ layout?.spatialIndexes.some((s) => s.sid === read.entity.sid);
180
+ const query = layout?.queryReads.some((q) => q.sid === read.entity.sid);
181
+ const count = layout?.countReads.some((q) => q.sid === read.entity.sid);
182
+ const computed = layout?.computedReads.some(
183
+ (q) => q.sid === read.entity.sid
184
+ );
185
+ const refusal =
186
+ layout?.queryRefusals.find((q) => q.sid === read.entity.sid) ??
187
+ layout?.countRefusals.find((q) => q.sid === read.entity.sid) ??
188
+ layout?.computedRefusals.find((q) => q.sid === read.entity.sid);
189
+ return {
190
+ sid: read.entity.sid,
191
+ name: read.entity.label,
192
+ domain: domain.entity.label,
193
+ kind: read.readKind,
194
+ aggregateSid: aggregate.entity.sid,
195
+ wireType: aggregate.wireType,
196
+ public: read.public,
197
+ contract: read.contract.id,
198
+ fields,
199
+ filtered: !!read.predicate,
200
+ status:
201
+ spatial || query || count || computed
202
+ ? "component-implemented"
203
+ : "missing",
204
+ reason: !layout
205
+ ? "aggregate layout unavailable"
206
+ : spatial || query || count || computed
207
+ ? null
208
+ : refusal?.reason ?? `${read.readKind} read adapter not implemented`,
209
+ requirements: [
210
+ read.readKind,
211
+ ...(fields.length > 1 ? ["compound"] : []),
212
+ ...(fields.some((f) => f.path.includes(".")) ? ["nested-path"] : []),
213
+ ...(fields.some((f) => f.storage === "set")
214
+ ? ["set-membership"]
215
+ : []),
216
+ ...(fields.some((f) => f.drivers.includes("Surfaced"))
217
+ ? ["surfaced-observation"]
218
+ : []),
219
+ ...(read.predicate ? ["predicate"] : []),
220
+ ],
221
+ runtimeVerified: false,
222
+ };
223
+ })
224
+ .sort(
225
+ (a, b) =>
226
+ a.domain.localeCompare(b.domain) ||
227
+ a.name.localeCompare(b.name) ||
228
+ a.sid.localeCompare(b.sid)
229
+ );
230
+ const kinds = Object.fromEntries(
231
+ [...new Set(reads.map((r) => r.kind))].sort().map((kind) => {
232
+ const group = reads.filter((r) => r.kind === kind);
233
+ return [
234
+ kind,
235
+ {
236
+ total: group.length,
237
+ implemented: group.filter((r) => r.status === "component-implemented")
238
+ .length,
239
+ missing: group.filter((r) => r.status === "missing").length,
240
+ },
241
+ ];
242
+ })
243
+ );
244
+ const foreignReads = [...nodes.values()]
245
+ .filter(
246
+ (n) => n.kind === "structural" && n.structuralKind === "foreign-read"
247
+ )
248
+ .map((n) => {
249
+ if (n.kind !== "structural" || n.structuralKind !== "foreign-read")
250
+ throw Error("unreachable");
251
+ return {
252
+ id: n.entity.id,
253
+ owner: n.owner.id,
254
+ query: n.query,
255
+ sourcePolicy: n.source.id,
256
+ requirements: [
257
+ "authenticated-source-frontier",
258
+ "source-policy",
259
+ "snapshot-binding",
260
+ ],
261
+ runtimeVerified: false,
262
+ };
263
+ });
264
+ return {
265
+ scope:
266
+ "declared read component coverage; not authorization, generated-client or runtime proof",
267
+ total: reads.length,
268
+ implemented: reads.filter((r) => r.status === "component-implemented")
269
+ .length,
270
+ missing: reads.filter((r) => r.status === "missing").length,
271
+ kinds,
272
+ reads,
273
+ foreignReads,
274
+ };
275
+ }
@@ -0,0 +1,185 @@
1
+ /** Component fixtures from authored descriptors, independently of the physical
2
+ * planner. Real wire encoder, synthetic values: NOT admitted tenant records.
3
+ * Keep this opt-in diagnostic outside compiler/law outputs and public barrels.
4
+ */
5
+ import type {
6
+ Field,
7
+ ValueObjectDescriptor,
8
+ ValueObjectFieldDescriptor,
9
+ ValueObjectFieldMeta,
10
+ } from "./fields.js";
11
+ import type { DomainModule } from "./codegen_dart.js";
12
+ import { encodeNominalValueObject } from "./wire_encode.js";
13
+ import type { LawGraph } from "./law_graph.js";
14
+
15
+ function object(
16
+ d: ValueObjectDescriptor,
17
+ types: Map<string, ValueObjectDescriptor>,
18
+ n: number
19
+ ): unknown {
20
+ if (d.geometry) {
21
+ const point = [1, 2.5];
22
+ return {
23
+ type: d.geometry,
24
+ coordinates:
25
+ d.geometry === "Point"
26
+ ? point
27
+ : d.geometry === "Polygon"
28
+ ? [[point, [2, 3], [3, 1], point]]
29
+ : [point, [2, 3]],
30
+ };
31
+ }
32
+ if (d.union) {
33
+ const [label, arm] = Object.entries(d.union).sort(([a], [b]) =>
34
+ a.localeCompare(b)
35
+ )[Math.floor(n / 3) % Object.keys(d.union).length]!;
36
+ return "ref" in arm
37
+ ? { type: label, value: object(types.get(arm.ref)!, types, n) }
38
+ : { type: label, ...members(arm.fields, types, n) };
39
+ }
40
+ return members(d.fields ?? {}, types, n);
41
+ }
42
+ function members(
43
+ fields: Readonly<Record<string, ValueObjectFieldDescriptor>>,
44
+ types: Map<string, ValueObjectDescriptor>,
45
+ n: number
46
+ ) {
47
+ return Object.fromEntries(
48
+ Object.entries(fields).flatMap(([name, f]) =>
49
+ f.optional && n % 3 === 0 ? [] : [[name, member(f, types, n)]]
50
+ )
51
+ );
52
+ }
53
+ function member(
54
+ f: ValueObjectFieldDescriptor,
55
+ types: Map<string, ValueObjectDescriptor>,
56
+ n: number
57
+ ): unknown {
58
+ if (f.nullable && n % 3 === 1) return null;
59
+ switch (f.type) {
60
+ case "string":
61
+ return f.digest ? "a".repeat(64) : n % 3 === 0 ? "" : `sample-λ-${n}`;
62
+ case "enum":
63
+ return f.values[n % f.values.length];
64
+ case "literal":
65
+ return f.value;
66
+ case "number":
67
+ // This interchange is JSON; the native scalar fixture separately covers
68
+ // IEEE negative-zero bits without JSON.stringify normalising them to zero.
69
+ return f.int ? n : n % 2 === 0 ? 0 : 1.25;
70
+ case "boolean":
71
+ return n % 2 === 0;
72
+ case "array":
73
+ return n % 3 === 0
74
+ ? []
75
+ : [member(f.items, types, n), member(f.items, types, n + 1)];
76
+ case "map":
77
+ return n % 3 === 0
78
+ ? {}
79
+ : {
80
+ "": member(f.values, types, n),
81
+ "λ:2/key": member(f.values, types, n + 1),
82
+ };
83
+ case "object":
84
+ case "geometry":
85
+ return object(types.get(f.ref)!, types, n);
86
+ }
87
+ }
88
+ function nominal(meta: ValueObjectFieldMeta, n: number) {
89
+ const types = new Map(
90
+ [meta.descriptor, ...meta.dependencies].map((d) => [d.name, d])
91
+ );
92
+ return {
93
+ ValueObject: encodeNominalValueObject(
94
+ meta.descriptor,
95
+ object(meta.descriptor, types, n),
96
+ types
97
+ ),
98
+ };
99
+ }
100
+ function value(f: Field, n: number): unknown {
101
+ if (f.nullSemantic && f.nullSemantic !== "forbid" && n % 3 === 1)
102
+ return { Json: null };
103
+ const ref = (type: string) => ({
104
+ workspace: "synthetic-workspace",
105
+ type,
106
+ id: `synthetic-${n}`,
107
+ });
108
+ if (f.nomosRef) return { NomosRef: ref(f.nomosRef.targetAggregateId) };
109
+ if (f.versionedForeignRef)
110
+ return {
111
+ VersionedNomosRef: {
112
+ pinned: ref(f.versionedForeignRef.targetAggregateId),
113
+ series: ref(f.versionedForeignRef.seriesAggregateId),
114
+ },
115
+ };
116
+ if (f.valueObject) return nominal(f.valueObject, n);
117
+ if (f.kind === "map") {
118
+ const leaf = f.mapValueVo
119
+ ? nominal(f.mapValueVo, n)
120
+ : f.mapValueKind === "int"
121
+ ? { Int: n }
122
+ : f.mapValueKind === "bool"
123
+ ? { Bool: n % 2 === 0 }
124
+ : { Str: `entry-${n}` };
125
+ return { Map: n % 3 === 0 ? {} : { "": leaf, "λ:2/key": leaf } };
126
+ }
127
+ if (f.kind === "set") return { Set: n % 3 === 0 ? [] : ["alpha", "βeta"] };
128
+ if (f.kind === "int") return { Int: n };
129
+ if (f.kind === "bool") return { Bool: n % 2 === 0 };
130
+ if (["string", "enum", "ref"].includes(f.kind)) return { Str: `sample-${n}` };
131
+ throw new Error(`unsupported descriptor fixture kind ${f.kind}`);
132
+ }
133
+ export function sqliteDescriptorSamples(
134
+ modules: readonly DomainModule[],
135
+ graphs: ReadonlyMap<string, LawGraph>
136
+ ) {
137
+ const seen = new Set<string>();
138
+ return modules.flatMap((mod) =>
139
+ mod.aggregates.flatMap((a) => {
140
+ // Shared framework handles may occur in multiple modules; physical binding
141
+ // is by the compiler's wireType + stable SID, supplied by the caller.
142
+ const node = graphs
143
+ .get(mod.name)!
144
+ .nodes.find((n) => n.kind === "aggregate" && n.entity.label === a.id);
145
+ if (node?.kind !== "aggregate")
146
+ throw new Error(`missing aggregate ${mod.name}.${a.id}`);
147
+ const key = node.entity.sid;
148
+ if (seen.has(key)) return [];
149
+ seen.add(key);
150
+ let arms = 1;
151
+ for (const f of Object.values(a.fields))
152
+ for (const meta of [f.valueObject, f.mapValueVo])
153
+ if (meta)
154
+ for (const d of [meta.descriptor, ...meta.dependencies])
155
+ arms = Math.max(arms, Object.keys(d.union ?? {}).length);
156
+ const labels = new Set(
157
+ node.fields.map(
158
+ (r) =>
159
+ graphs.get(mod.name)!.nodes.find((n) => n.entity.id === r.id)!
160
+ .entity.label
161
+ )
162
+ );
163
+ const base = {
164
+ aggregate: a.id,
165
+ sid: key,
166
+ wireType: node.wireType,
167
+ scope:
168
+ "synthetic descriptor values through the production nominal wire encoder; not admitted domain data",
169
+ };
170
+ try {
171
+ const samples = Array.from({ length: Math.max(3, arms * 3) }, (_, n) =>
172
+ Object.fromEntries(
173
+ Object.entries(a.fields)
174
+ .filter(([name]) => labels.has(name))
175
+ .map(([name, f]) => [name, value(f, n)])
176
+ )
177
+ );
178
+ return [{ ...base, samples }];
179
+ } catch (error) {
180
+ // An unsupported fixture must not erase the planner's useful diagnostics.
181
+ return [{ ...base, samples: [], samplingError: String(error) }];
182
+ }
183
+ })
184
+ );
185
+ }
@@ -13,7 +13,7 @@ export interface StableIdentityAggregateInput {
13
13
  }
14
14
 
15
15
  /**
16
- * Compatibility bridge for W4.1. The existing shape-aware continuity pass proposes
16
+ * Compatibility mapping for W4.1. The existing shape-aware continuity pass proposes
17
17
  * carries; the generalized registry owns the final SIDs and durable tombstones. Later
18
18
  * W4 work replaces those proposals with typed-graph/previous-USDA evidence.
19
19
  */
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import { z } from "zod";
3
3
  import type { DomainModule } from "./codegen_dart.js";
4
4
  import { canonicalJson } from "./canonical_json.js";
5
- import { encodeDriver } from "./drivers.js";
5
+ import { driversShareValueSpace, driverValueSpace, encodeDriver } from "./drivers.js";
6
6
  import type { Field } from "./fields.js";
7
7
  import {
8
8
  mintAggregateSid,
@@ -126,7 +126,16 @@ function fieldValueContractDetails(field: Field): { contract: string; shape: unk
126
126
  return { contract, shape: contractShape };
127
127
  }
128
128
 
129
- function fieldSchemaIdentity(
129
+ /**
130
+ * Stable identity of one field contract — byte-identical to the kernel's
131
+ * `field_schema_identity` (pinned by the golden in `stable_ids_for_module.test.ts` and
132
+ * `kernel/tests/field_schema_identity.rs`). The `driver` slot carries the driver's stored
133
+ * VALUE SPACE (`driverValueSpace`), not the driver: switching among single-value drivers
134
+ * (Lww, LwwCausal, LwwBy, FirstWriterWins, FirstWriterCandidates, Surfaced/Attributed of
135
+ * those) keeps the identity, because D20 stores the observation antichain and the driver is
136
+ * a projection-time reduction. The value kind and contract stay in the identity (a retype).
137
+ */
138
+ export function fieldSchemaIdentity(
130
139
  aggregateSid: string,
131
140
  fieldSid: string,
132
141
  kind: string,
@@ -141,7 +150,7 @@ function fieldSchemaIdentity(
141
150
  field: fieldSid,
142
151
  kind,
143
152
  valueContract,
144
- driver,
153
+ driver: driverValueSpace(driver),
145
154
  }),
146
155
  "utf8",
147
156
  )
@@ -214,7 +223,10 @@ function fieldEvolutionRules(
214
223
  prior?.schema !== undefined &&
215
224
  prior.schema !== targetSchema &&
216
225
  prior.shape !== undefined &&
217
- canonicalJson(prior.driver) === canonicalJson(driver) &&
226
+ // Same stored value space (a single-value driver switch is free under D20): the prior
227
+ // schema was minted under an older preimage, so its stamped observations still route.
228
+ prior.driver !== undefined &&
229
+ driversShareValueSpace(prior.driver, driver) &&
218
230
  safeAutomaticWidening(prior.shape, target.shape) &&
219
231
  !bySource.has(prior.schema)
220
232
  ) {
@@ -24,12 +24,12 @@ function callUsdaForTestIdentity(
24
24
  ? { ...aggregate, audience: { kind: "public" as const } }
25
25
  : aggregate),
26
26
  valueObjects: collectValueObjectDescriptors(candidate.aggregates),
27
- directives: candidate.directives.map((directive) => ({
28
- ...directive,
29
- ...((directive as { birthsChild?: boolean }).birthsChild === true
30
- ? { declaredQueryReads: [] }
31
- : {}),
32
- })),
27
+ // Keep object identity for every directive this fixture does not change: a business intent's
28
+ // `.directs` step holds the original directive, and the law graph treats a copy as a second declaration.
29
+ directives: candidate.directives.map((directive) =>
30
+ (directive as { birthsChild?: boolean }).birthsChild === true
31
+ ? { ...directive, declaredQueryReads: [] }
32
+ : directive),
33
33
  });
34
34
  const byName = new Map(
35
35
  [module, ...closureModules].map((candidate) => [candidate.name, normalize(candidate)]),
@@ -16,6 +16,7 @@ interface RelationshipTarget {
16
16
  readonly asset: string;
17
17
  readonly line: number;
18
18
  readonly path: string;
19
+ readonly relationship?: string;
19
20
  }
20
21
 
21
22
  const PRIM_DECLARATION = /^(\s*)(?:def|over)(?:\s+[A-Za-z_][A-Za-z0-9_:]*)?\s+"([^"]+)"\s*$/;
@@ -27,7 +28,10 @@ const RELATIONSHIP_TARGET = /<([^>]+)>/g;
27
28
  * This intentionally checks only absolute `/Nomos` targets. Asset paths, external scene references
28
29
  * and ordinary USD relationships retain normal OpenUSD semantics; Nomos law identities do not.
29
30
  */
30
- export function assertUsdaRelationshipIntegrity(assets: readonly UsdaRelationshipAsset[]): void {
31
+ export function assertUsdaRelationshipIntegrity(
32
+ assets: readonly UsdaRelationshipAsset[],
33
+ options: { readonly allowMissingRelationships?: ReadonlySet<string> } = {},
34
+ ): void {
31
35
  const prims = new Set<string>();
32
36
  const targets: RelationshipTarget[] = [];
33
37
 
@@ -48,13 +52,26 @@ export function assertUsdaRelationshipIntegrity(assets: readonly UsdaRelationshi
48
52
  for (const match of line.matchAll(RELATIONSHIP_TARGET)) {
49
53
  const path = match[1]!;
50
54
  if (path === "/Nomos" || path.startsWith("/Nomos/")) {
51
- targets.push({ asset: asset.logicalPath, line: offset + 1, path });
55
+ const relationship = /\brel\s+([A-Za-z_][A-Za-z0-9_:]*)\s*=/.exec(line)?.[1];
56
+ targets.push({
57
+ asset: asset.logicalPath,
58
+ line: offset + 1,
59
+ path,
60
+ ...(relationship === undefined ? {} : { relationship }),
61
+ });
52
62
  }
53
63
  }
54
64
  }
55
65
  }
56
66
 
57
- const missing = targets.filter((target) => !prims.has(target.path));
67
+ const missing = targets.filter(
68
+ (target) =>
69
+ !prims.has(target.path) &&
70
+ !(
71
+ target.relationship !== undefined &&
72
+ options.allowMissingRelationships?.has(target.relationship)
73
+ ),
74
+ );
58
75
  if (missing.length === 0) return;
59
76
  const examples = missing.slice(0, 8).map((target) =>
60
77
  `${target.asset}:${target.line} targets missing prim <${target.path}>`).join("\n ");
package/src/usda_text.ts CHANGED
@@ -3,7 +3,27 @@
3
3
 
4
4
  /** Escape a string for a double-quoted USDA string literal. */
5
5
  export function usdaString(value: string): string {
6
- return JSON.stringify(value);
6
+ let encoded = '"';
7
+ for (const character of value) {
8
+ switch (character) {
9
+ case '"': encoded += '\\"'; break;
10
+ case "\\": encoded += "\\\\"; break;
11
+ case "\n": encoded += "\\n"; break;
12
+ case "\r": encoded += "\\r"; break;
13
+ case "\t": encoded += "\\t"; break;
14
+ case "\b": encoded += "\\b"; break;
15
+ case "\f": encoded += "\\f"; break;
16
+ default: {
17
+ const codePoint = character.codePointAt(0)!;
18
+ if (codePoint < 0x20 || codePoint === 0x7f) {
19
+ encoded += `\\u${codePoint.toString(16).padStart(4, "0")}`;
20
+ } else {
21
+ encoded += character;
22
+ }
23
+ }
24
+ }
25
+ }
26
+ return `${encoded}"`;
7
27
  }
8
28
 
9
29
  /** Emit a USDA `string[]` literal. */