hecks 2.7.0 → 2.9.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 (463) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +11 -0
  3. data/lib/hecks/adapters/driven/claude_code.rb +4 -104
  4. data/lib/hecks/adapters/driven/d1.rb +44 -237
  5. data/lib/hecks/adapters/driven/folder.rb +17 -76
  6. data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
  7. data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
  8. data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
  9. data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
  10. data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
  11. data/lib/hecks/adapters/driven/heki.rb +13 -42
  12. data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
  13. data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
  14. data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
  15. data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
  16. data/lib/hecks/adapters/driven/lambda.rb +10 -84
  17. data/lib/hecks/adapters/driven/local_storage.rb +5 -40
  18. data/lib/hecks/adapters/driven/memory.rb +18 -99
  19. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
  20. data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
  21. data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
  22. data/lib/hecks/adapters/driven/postgres/reconnect.rb +4 -30
  23. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
  24. data/lib/hecks/adapters/driven/postgres.rb +145 -134
  25. data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
  26. data/lib/hecks/adapters/driven/prism.rb +7 -30
  27. data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
  28. data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
  29. data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
  30. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
  31. data/lib/hecks/adapters/driven/sqlite.rb +128 -65
  32. data/lib/hecks/adapters/driven/tenant_provisioner.rb +15 -37
  33. data/lib/hecks/adapters/driven.rb +5 -36
  34. data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
  35. data/lib/hecks/behaviors/dsl.rb +7 -25
  36. data/lib/hecks/behaviors/expectations.rb +32 -142
  37. data/lib/hecks/behaviors/ir.rb +7 -20
  38. data/lib/hecks/behaviors/rspec.rb +6 -17
  39. data/lib/hecks/behaviors/runner.rb +10 -34
  40. data/lib/hecks/behaviors.rb +4 -8
  41. data/lib/hecks/bluebook/aggregate.rb +9 -75
  42. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
  43. data/lib/hecks/bluebook/assembly/build.rb +4 -15
  44. data/lib/hecks/bluebook/assembly/contract.rb +15 -136
  45. data/lib/hecks/bluebook/assembly/contracts.rb +54 -174
  46. data/lib/hecks/bluebook/assembly/marks.rb +31 -223
  47. data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
  48. data/lib/hecks/bluebook/assembly.rb +6 -45
  49. data/lib/hecks/bluebook/attribute.rb +12 -61
  50. data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -39
  51. data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
  52. data/lib/hecks/bluebook/behaviour/chapter.rb +17 -42
  53. data/lib/hecks/bluebook/behaviour/command.rb +14 -66
  54. data/lib/hecks/bluebook/behaviour/domain_port.rb +4 -20
  55. data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
  56. data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
  57. data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
  58. data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
  59. data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
  60. data/lib/hecks/bluebook/behaviour/read_model.rb +38 -26
  61. data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
  62. data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
  63. data/lib/hecks/bluebook/capabilities.rb +17 -49
  64. data/lib/hecks/bluebook/chapter.rb +10 -48
  65. data/lib/hecks/bluebook/command.rb +23 -81
  66. data/lib/hecks/bluebook/domain_port.rb +14 -63
  67. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
  68. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
  69. data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
  70. data/lib/hecks/bluebook/dsl/binding_proxy.rb +17 -65
  71. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +86 -708
  72. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +56 -170
  73. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
  74. data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
  75. data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
  76. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +12 -87
  77. data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
  78. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
  79. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +26 -189
  80. data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
  81. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
  82. data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
  83. data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
  84. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
  85. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
  86. data/lib/hecks/bluebook/dsl/query_builder.rb +11 -42
  87. data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
  88. data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
  89. data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
  90. data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
  91. data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
  92. data/lib/hecks/bluebook/dsl/world_builder.rb +19 -106
  93. data/lib/hecks/bluebook/entity.rb +13 -71
  94. data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
  95. data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
  96. data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
  97. data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
  98. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
  99. data/lib/hecks/bluebook/expression/resolver.rb +37 -660
  100. data/lib/hecks/bluebook/hexagon.rb +5 -28
  101. data/lib/hecks/bluebook/lifecycle.rb +5 -16
  102. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
  103. data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
  104. data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
  105. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
  106. data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
  107. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +24 -176
  108. data/lib/hecks/bluebook/meta_validator/shapes.rb +54 -268
  109. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -308
  110. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
  111. data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
  112. data/lib/hecks/bluebook/meta_validator.rb +79 -349
  113. data/lib/hecks/bluebook/model_check/client_profile.rb +10 -91
  114. data/lib/hecks/bluebook/model_check.rb +102 -600
  115. data/lib/hecks/bluebook/pattern_subset.rb +11 -69
  116. data/lib/hecks/bluebook/process_manager.rb +13 -83
  117. data/lib/hecks/bluebook/project_loader.rb +3 -39
  118. data/lib/hecks/bluebook/project_register.rb +12 -60
  119. data/lib/hecks/bluebook/query.rb +9 -48
  120. data/lib/hecks/bluebook/read_model.rb +57 -81
  121. data/lib/hecks/bluebook/reference.rb +7 -41
  122. data/lib/hecks/bluebook/smoke_test.rb +8 -98
  123. data/lib/hecks/bluebook/synthesizer.rb +13 -62
  124. data/lib/hecks/bluebook/translation.rb +26 -62
  125. data/lib/hecks/bluebook/value_object.rb +11 -36
  126. data/lib/hecks/bluebook.rb +5 -22
  127. data/lib/hecks/cache_dir.rb +84 -0
  128. data/lib/hecks/cli/document.rb +86 -0
  129. data/lib/hecks/cli/ir.rb +45 -0
  130. data/lib/hecks/cli/mcp.rb +31 -0
  131. data/lib/hecks/cli/mcp_door.rb +366 -0
  132. data/lib/hecks/cli/model_check.rb +203 -0
  133. data/lib/hecks/cli/project_cli.rb +90 -0
  134. data/lib/hecks/cli/project_diagrams.rb +36 -0
  135. data/lib/hecks/cli/run.rb +173 -0
  136. data/lib/hecks/cli/smoke_test.rb +45 -0
  137. data/lib/hecks/cli/stores.rb +53 -0
  138. data/lib/hecks/cli.rb +160 -0
  139. data/lib/hecks/construct.rb +8 -34
  140. data/lib/hecks/deploy/bluebook/deploy.bluebook +33 -142
  141. data/lib/hecks/deploy/bluebook/deploy.hecksagon +2 -9
  142. data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
  143. data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
  144. data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
  145. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
  146. data/lib/hecks/embryonaut_bluebook.rb +4 -71
  147. data/lib/hecks/facade/cli_door.rb +24 -106
  148. data/lib/hecks/facade/cli_runner.rb +28 -172
  149. data/lib/hecks/facade/command_request.rb +13 -33
  150. data/lib/hecks/facade/handle.rb +34 -121
  151. data/lib/hecks/facade/json_door.rb +31 -146
  152. data/lib/hecks/facade/surface/aggregate_door.rb +39 -104
  153. data/lib/hecks/facade/surface/chapter.rb +10 -54
  154. data/lib/hecks/facade/surface.rb +8 -23
  155. data/lib/hecks/facade.rb +10 -25
  156. data/lib/hecks/forms/app.rb +15 -70
  157. data/lib/hecks/forms/command_form_renderer.rb +10 -29
  158. data/lib/hecks/forms/field_renderer.rb +17 -156
  159. data/lib/hecks/forms/field_shape.rb +30 -222
  160. data/lib/hecks/forms/html.rb +12 -47
  161. data/lib/hecks/forms/index_renderer.rb +1 -4
  162. data/lib/hecks/forms/page.rb +3 -9
  163. data/lib/hecks/forms/params.rb +14 -60
  164. data/lib/hecks/forms/port_argument.rb +2 -19
  165. data/lib/hecks/forms/query_form_renderer.rb +4 -79
  166. data/lib/hecks/forms/record_renderer.rb +8 -75
  167. data/lib/hecks/forms/record_table.rb +7 -50
  168. data/lib/hecks/forms/reference_options.rb +3 -30
  169. data/lib/hecks/forms/value_object_shape.rb +8 -35
  170. data/lib/hecks/forms.rb +5 -33
  171. data/lib/hecks/fqn.rb +5 -12
  172. data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
  173. data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
  174. data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
  175. data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
  176. data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
  177. data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
  178. data/lib/hecks/framework.rb +11 -80
  179. data/lib/hecks/freezer.rb +5 -39
  180. data/lib/hecks/grammar/expression.bluebook +15 -40
  181. data/lib/hecks/grammar/translation.bluebook +3 -6
  182. data/lib/hecks/grammar.rb +16 -41
  183. data/lib/hecks/ir.rb +14 -83
  184. data/lib/hecks/language/adapter.bluebook +2 -7
  185. data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
  186. data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
  187. data/lib/hecks/language/bluebook/bluebook.bluebook +15 -83
  188. data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
  189. data/lib/hecks/language/bluebook/command.bluebook +27 -144
  190. data/lib/hecks/language/bluebook/entity.bluebook +24 -97
  191. data/lib/hecks/language/bluebook/policy.bluebook +16 -67
  192. data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
  193. data/lib/hecks/language/bluebook/projection.bluebook +126 -60
  194. data/lib/hecks/language/bluebook/query.bluebook +12 -43
  195. data/lib/hecks/language/bluebook/shape.bluebook +23 -73
  196. data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
  197. data/lib/hecks/language/bluebook/vocabulary.bluebook +98 -197
  198. data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
  199. data/lib/hecks/language/hecksagon/domain_port.bluebook +4 -19
  200. data/lib/hecks/language/hecksagon/hecksagon.bluebook +6 -25
  201. data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
  202. data/lib/hecks/language/oidc.json +35 -0
  203. data/lib/hecks/language/port.bluebook +4 -17
  204. data/lib/hecks/language/translation/translation.bluebook +3 -9
  205. data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
  206. data/lib/hecks/language/world/wiring.bluebook +1 -3
  207. data/lib/hecks/language/world/world.bluebook +5 -7
  208. data/lib/hecks/literal.rb +8 -50
  209. data/lib/hecks/mcp_door_scope.rb +95 -0
  210. data/lib/hecks/mcp_stdio_guard.rb +4 -41
  211. data/lib/hecks/naming.rb +29 -137
  212. data/lib/hecks/ports/access_control.rb +7 -23
  213. data/lib/hecks/ports/agent/answers.rb +5 -23
  214. data/lib/hecks/ports/agent.rb +47 -172
  215. data/lib/hecks/ports/authentication.rb +12 -39
  216. data/lib/hecks/ports/authorization.rb +16 -43
  217. data/lib/hecks/ports/clock.rb +5 -45
  218. data/lib/hecks/ports/extraction.rb +7 -12
  219. data/lib/hecks/ports/identity_assignment.rb +8 -29
  220. data/lib/hecks/ports/identity_generation.rb +6 -29
  221. data/lib/hecks/ports/identity_resolution.rb +2 -10
  222. data/lib/hecks/ports/key_vault.rb +9 -45
  223. data/lib/hecks/ports/persistence/append_only.rb +62 -65
  224. data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
  225. data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
  226. data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
  227. data/lib/hecks/ports/persistence/plugin.rb +13 -42
  228. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +38 -141
  229. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
  230. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +16 -84
  231. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +7 -26
  232. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -22
  233. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
  234. data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
  235. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
  236. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
  237. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
  238. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
  239. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
  240. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
  241. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +18 -75
  242. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
  243. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
  244. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
  245. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
  246. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
  247. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +14 -115
  248. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
  249. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +127 -554
  250. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
  251. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
  252. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
  253. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
  254. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
  255. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
  256. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +9 -25
  257. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +22 -122
  258. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
  259. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
  260. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
  261. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
  262. data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
  263. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
  264. data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
  265. data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
  266. data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
  267. data/lib/hecks/ports/persistence/state_codec.rb +23 -103
  268. data/lib/hecks/ports/persistence.rb +7 -14
  269. data/lib/hecks/ports/projection.rb +42 -84
  270. data/lib/hecks/ports/query/in_memory.rb +10 -58
  271. data/lib/hecks/ports/query/ordering.rb +11 -32
  272. data/lib/hecks/ports/query.rb +14 -37
  273. data/lib/hecks/ports.rb +2 -8
  274. data/lib/hecks/projections/bootstrap_table.rb +11 -43
  275. data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
  276. data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
  277. data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
  278. data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
  279. data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
  280. data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
  281. data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
  282. data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
  283. data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
  284. data/lib/hecks/projections/deploy/fargate.rb +35 -202
  285. data/lib/hecks/projections/deploy/lambda.rb +151 -679
  286. data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
  287. data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
  288. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
  289. data/lib/hecks/projections/deploy/preview/script.rb +2 -14
  290. data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
  291. data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
  292. data/lib/hecks/projections/deploy/preview/template.rb +2 -58
  293. data/lib/hecks/projections/deploy/preview.rb +2 -67
  294. data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
  295. data/lib/hecks/projections/deploy/scripts.rb +4 -57
  296. data/lib/hecks/projections/deploy/shared.rb +47 -146
  297. data/lib/hecks/projections/deploy/smoke.rb +4 -61
  298. data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
  299. data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
  300. data/lib/hecks/projections/deploy/template_diff.rb +5 -57
  301. data/lib/hecks/projections/diagrams.rb +20 -582
  302. data/lib/hecks/projections/glossary/html.rb +14 -130
  303. data/lib/hecks/projections/glossary/markdown.rb +8 -69
  304. data/lib/hecks/projections/glossary/mermaid.rb +9 -66
  305. data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
  306. data/lib/hecks/projections/glossary/sentences.rb +14 -159
  307. data/lib/hecks/projections/glossary.rb +30 -222
  308. data/lib/hecks/projections/ir.rb +3 -10
  309. data/lib/hecks/projections/model/deviations.rb +15 -42
  310. data/lib/hecks/projections/model.rb +12 -51
  311. data/lib/hecks/projections/oidc.rb +12 -56
  312. data/lib/hecks/projections/parser_table.rb +9 -28
  313. data/lib/hecks/projections/reference.rb +9 -16
  314. data/lib/hecks/projections/rust_vocabulary.rb +12 -250
  315. data/lib/hecks/projections/shape.rb +3 -29
  316. data/lib/hecks/projections/statements.rb +7 -86
  317. data/lib/hecks/projections/vocabulary.rb +6 -22
  318. data/lib/hecks/projections.rb +2 -16
  319. data/lib/hecks/projector/cli_projector.rb +60 -375
  320. data/lib/hecks/projector/docs_projector.rb +10 -201
  321. data/lib/hecks/projector/exporter.rb +46 -138
  322. data/lib/hecks/projector/ir_projector.rb +2 -9
  323. data/lib/hecks/projector/narrate_projector.rb +15 -189
  324. data/lib/hecks/projector/target.rb +13 -76
  325. data/lib/hecks/projector.rb +30 -121
  326. data/lib/hecks/query_specification/common/comparators.rb +5 -26
  327. data/lib/hecks/query_specification/common/comparison.rb +35 -143
  328. data/lib/hecks/query_specification/common/dsl.rb +8 -24
  329. data/lib/hecks/query_specification/common/null_policy.rb +20 -70
  330. data/lib/hecks/query_specification/common/options.rb +2 -6
  331. data/lib/hecks/query_specification/common/where_clause.rb +2 -10
  332. data/lib/hecks/query_specification/field_path.rb +37 -77
  333. data/lib/hecks/query_specification/hop_path.rb +12 -76
  334. data/lib/hecks/release/gem_pin.rb +2 -26
  335. data/lib/hecks/release/runner/ci_publisher.rb +93 -0
  336. data/lib/hecks/release/runner/commands.rb +66 -0
  337. data/lib/hecks/release/runner/console.rb +52 -0
  338. data/lib/hecks/release/runner/gem_publisher.rb +43 -0
  339. data/lib/hecks/release/runner/git.rb +48 -0
  340. data/lib/hecks/release/runner/npm_publisher.rb +75 -0
  341. data/lib/hecks/release/runner/preflight.rb +104 -0
  342. data/lib/hecks/release/runner/published.rb +55 -0
  343. data/lib/hecks/release/runner/tagger.rb +80 -0
  344. data/lib/hecks/release/runner.rb +215 -0
  345. data/lib/hecks/rendering.rb +4 -26
  346. data/lib/hecks/router/namespace_installer.rb +12 -36
  347. data/lib/hecks/router.rb +4 -8
  348. data/lib/hecks/runtime/aggregate_lock.rb +8 -33
  349. data/lib/hecks/runtime/boot_gates.rb +3 -18
  350. data/lib/hecks/runtime/caller.rb +19 -59
  351. data/lib/hecks/runtime/capability_graph.rb +5 -21
  352. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
  353. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
  354. data/lib/hecks/runtime/command_interpreter.rb +125 -307
  355. data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
  356. data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
  357. data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
  358. data/lib/hecks/runtime/command_rules/emission.rb +8 -21
  359. data/lib/hecks/runtime/command_rules/references.rb +23 -202
  360. data/lib/hecks/runtime/dependency_planning.rb +30 -102
  361. data/lib/hecks/runtime/dispatcher.rb +82 -241
  362. data/lib/hecks/runtime/entity_element.rb +40 -462
  363. data/lib/hecks/runtime/entity_interpreter.rb +65 -220
  364. data/lib/hecks/runtime/errors.rb +32 -115
  365. data/lib/hecks/runtime/event.rb +3 -25
  366. data/lib/hecks/runtime/identity.rb +18 -154
  367. data/lib/hecks/runtime/instance.rb +18 -150
  368. data/lib/hecks/runtime/interpreting.rb +11 -70
  369. data/lib/hecks/runtime/invocation.rb +28 -164
  370. data/lib/hecks/runtime/loader.rb +48 -186
  371. data/lib/hecks/runtime/outbox.rb +38 -261
  372. data/lib/hecks/runtime/policy_interpreter.rb +38 -200
  373. data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
  374. data/lib/hecks/runtime/query_interpreter.rb +45 -187
  375. data/lib/hecks/runtime/reaction_invocation.rb +36 -138
  376. data/lib/hecks/runtime/read_model_interpreter.rb +139 -208
  377. data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
  378. data/lib/hecks/runtime/reference_hop.rb +8 -81
  379. data/lib/hecks/runtime/refusal_wording.rb +8 -89
  380. data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
  381. data/lib/hecks/runtime/registry/verification.rb +52 -225
  382. data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
  383. data/lib/hecks/runtime/registry.rb +103 -244
  384. data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
  385. data/lib/hecks/runtime/routing.rb +4 -15
  386. data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
  387. data/lib/hecks/runtime/saga_interpreter.rb +79 -263
  388. data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
  389. data/lib/hecks/runtime/tenant_check.rb +6 -68
  390. data/lib/hecks/runtime/tenant_scope.rb +3 -28
  391. data/lib/hecks/runtime/value/admission.rb +16 -67
  392. data/lib/hecks/runtime/value/coercion.rb +155 -641
  393. data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
  394. data/lib/hecks/runtime/value.rb +12 -84
  395. data/lib/hecks/runtime.rb +17 -65
  396. data/lib/hecks/storehouse.rb +146 -567
  397. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
  398. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
  399. data/lib/hecks/vendoring/git_environment.rb +2 -8
  400. data/lib/hecks/vendoring/git_source.rb +4 -10
  401. data/lib/hecks/vendoring.rb +7 -46
  402. data/lib/hecks/version.rb +3 -14
  403. data/lib/hecks/vocabulary.rb +5 -0
  404. data/lib/hecks.rb +32 -82
  405. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
  406. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
  407. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
  408. metadata +30 -59
  409. data/lib/hecks/bench/cli.rb +0 -74
  410. data/lib/hecks/bench/environment.rb +0 -100
  411. data/lib/hecks/bench/postgres_probe.rb +0 -41
  412. data/lib/hecks/bench/report.rb +0 -116
  413. data/lib/hecks/bench/ruby_runner.rb +0 -151
  414. data/lib/hecks/bench/run.rb +0 -55
  415. data/lib/hecks/bench/rust_runner.rb +0 -165
  416. data/lib/hecks/bench/stats.rb +0 -75
  417. data/lib/hecks/bench/suite.rb +0 -172
  418. data/lib/hecks/bench/workload.rb +0 -137
  419. data/lib/hecks/bench.rb +0 -28
  420. data/lib/hecks/codemod.rb +0 -443
  421. data/lib/hecks/corpus.rb +0 -479
  422. data/lib/hecks/doc/reference.rb +0 -585
  423. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -684
  424. data/lib/hecks/fuzzing/combination_miner.rb +0 -178
  425. data/lib/hecks/fuzzing/concurrent_dispatch.rb +0 -469
  426. data/lib/hecks/fuzzing/coverage_campaign.rb +0 -161
  427. data/lib/hecks/fuzzing/differential.rb +0 -192
  428. data/lib/hecks/fuzzing/domain_generator.rb +0 -871
  429. data/lib/hecks/fuzzing/era_boundary.rb +0 -154
  430. data/lib/hecks/fuzzing/form_census.rb +0 -285
  431. data/lib/hecks/fuzzing/generated_domain_check.rb +0 -171
  432. data/lib/hecks/fuzzing/invalid_value_generator.rb +0 -125
  433. data/lib/hecks/fuzzing/isolated_boot.rb +0 -658
  434. data/lib/hecks/fuzzing/nondeterministic.rb +0 -79
  435. data/lib/hecks/fuzzing/persistence_parity.rb +0 -253
  436. data/lib/hecks/fuzzing/properties/corrections.rb +0 -125
  437. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +0 -688
  438. data/lib/hecks/fuzzing/properties/guards.rb +0 -398
  439. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +0 -399
  440. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +0 -137
  441. data/lib/hecks/fuzzing/properties/outbox.rb +0 -180
  442. data/lib/hecks/fuzzing/properties/querying.rb +0 -260
  443. data/lib/hecks/fuzzing/properties.rb +0 -267
  444. data/lib/hecks/fuzzing/qa_settings.rb +0 -164
  445. data/lib/hecks/fuzzing/replay.rb +0 -930
  446. data/lib/hecks/fuzzing/rotation_priority.rb +0 -114
  447. data/lib/hecks/fuzzing/rust_gap_manifest.rb +0 -139
  448. data/lib/hecks/fuzzing/self_consistency.rb +0 -825
  449. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +0 -532
  450. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +0 -171
  451. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +0 -127
  452. data/lib/hecks/fuzzing/sequence_generator/picker.rb +0 -116
  453. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +0 -138
  454. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +0 -344
  455. data/lib/hecks/fuzzing/sequence_generator.rb +0 -311
  456. data/lib/hecks/fuzzing/shrinker.rb +0 -309
  457. data/lib/hecks/fuzzing/structural_skips.rb +0 -53
  458. data/lib/hecks/fuzzing/sweep_depth.rb +0 -61
  459. data/lib/hecks/fuzzing/target_capabilities.rb +0 -255
  460. data/lib/hecks/fuzzing/value_generator.rb +0 -340
  461. data/lib/hecks/fuzzing.rb +0 -23
  462. data/lib/hecks/grammar/evolve.rb +0 -524
  463. data/lib/hecks/query_ir.rb +0 -482
@@ -1,27 +1,11 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module MetaValidator
4
- # The leaf shapes of a reconstructed bluebook, and the encodings that go with
5
- # them.
6
- #
7
- # Reconstruction walks the tree; this rebuilds the small hashes at its tips —
8
- # an attribute, a rule, a where-clause, a transition — and undoes the two
9
- # things the walk encodes on the way in: an attribute's type offered as the ID
10
- # of whatever it names, and an append flattened to one row per binding.
11
- #
12
- # Separate from the traversal because they are different concerns, and because
13
- # the two together were 211 code lines against a 200 limit.
4
+ # The leaf shapes of a reconstructed bluebook: the small hashes at each tip of
5
+ # the tree (attribute, rule, where-clause, transition), decoded from their wire form.
14
6
  module Shapes
15
7
  # The type came in as the id of what it names, so it goes back out as the
16
8
  # name — or, for another aggregate's head, as the encoding the IR spells.
17
- #
18
- # @param field [Hash{Symbol => Object}] one dispatched attribute row
19
- # @param aggregate_id [String] the owning aggregate's own id, to
20
- # strip from an owned value-object type
21
- # @return [Hash{Symbol => Object}] `:name` (`Symbol`, `nil`),
22
- # `:type` (`String`), `:list`/`:optional` (`Boolean`), `:default`
23
- # (decoded literal, `nil` when absent), `:pattern`/`:admits`/
24
- # `:relationship` (`String`, `nil` when absent)
25
9
  def attribute(field, aggregate_id)
26
10
  type = text(field[:type]).to_s
27
11
 
@@ -32,27 +16,19 @@ module Hecks
32
16
  default: decode_literal(text(field[:default])),
33
17
  # Read back the same way `list` is — both are booleans about the
34
18
  # attribute, held as text, and dropping either would rebuild a
35
- # bluebook that no longer says what it said.
19
+ # bluebook that says something other than what was written.
36
20
  optional: text(field[:optional]).to_s == "true",
37
21
  pattern: presence(text(field[:pattern])),
38
- # The round trip is the only way in. The grammar registry keeps the
39
- # assembled graph — the language as its own judge read it back — so a
40
- # fact dropped here is a fact no downstream projection ever sees, no
41
- # matter how plainly the .bluebook file declares it.
22
+ # The round trip is the only way in: the grammar registry keeps the
23
+ # assembled graph, so a fact dropped here is a fact no projection
24
+ # downstream ever sees, however plainly the .bluebook declares it.
42
25
  admits: presence(text(field[:admits])),
43
26
  relationship: presence(text(field[:relationship]))
44
27
  }
45
28
  end
46
29
 
47
- # A type this aggregate owns, offered as its id and read back as its name.
48
- # Prefixed with the owner and the identity join, because that is the value
49
- # object's identity — the aggregate it belongs to, then its name.
50
- #
51
- # @param type [String] the attribute's own dispatched `type` cell
52
- # @param aggregate_id [String] the owning aggregate's own id
53
- # @return [String, nil] `type` with the owner's own identity prefix
54
- # stripped, or `nil` if `type` does not carry that prefix (an
55
- # ordinary type name, or a cross-aggregate reference)
30
+ # A type this aggregate owns, offered on the wire as its id.
31
+ # Read back here as the bare name, stripping the owner/identity prefix.
56
32
  def owned_type(type, aggregate_id)
57
33
  prefix = Naming.identity([aggregate_id, ""])
58
34
  return nil unless type.start_with?(prefix)
@@ -60,64 +36,20 @@ module Hecks
60
36
  type.delete_prefix(prefix)
61
37
  end
62
38
 
63
- # A type another aggregate of the same chapter declares, read back as its name.
64
- #
65
- # An attribute typed with a sibling aggregate's value object or entity is offered
66
- # as that declaration's id (chapter, owning aggregate, name), three segments. A
67
- # `Reference<X>` is offered as the target head's id, two segments. The extra segment
68
- # is what tells a type name from a reference, so a three-segment id is the bare
69
- # declaration name and only a two-segment id is a reference.
70
- #
71
- # @param type [String] the attribute's own dispatched `type` cell
72
- # @return [String, nil] the declaration's bare name when `type` is a three-segment id;
73
- # `nil` for a head's two-segment id
39
+ # A sibling aggregate's declared type, offered as its id; read back as the bare name.
40
+ # A three-segment id names a declaration; a two-segment id is a Reference head instead.
74
41
  def sibling_type(type)
75
42
  segments = type.split(Naming::IDENTITY_JOIN)
76
43
  segments.last if segments.size == 3
77
44
  end
78
45
 
79
- # One part of an identity, read back as the path it went in as. The inverse
80
- # of `Marks#identity_path`, and named the same so the two directions read
81
- # as one table.
82
- #
83
- # @param part [Hash{Symbol => Object}] one dispatched identity-part row
84
- # @return [String] the identity part's own path text
46
+ # The inverse of `Marks#identity_path`, named the same so the two
47
+ # directions read as one table.
85
48
  def identity_path(part) = text(part[:value]).to_s
86
49
 
87
- # An argument, a parameter, a piece's attribute — the three places an
88
- # attribute is written that carry no owner id to strip... except a
89
- # piece's own attribute now does : an entity is its own root (repeating
90
- # the aggregate's whole shape one level down), so its attributes name a
91
- # value object exactly the way an aggregate's own do (`Judge#cell`'s own
92
- # comment), and reconstruction has to undo the same owned-vs-reference
93
- # split `attribute`, below, already undoes for an aggregate — not the
94
- # cruder "any qualified name is a Reference" guess this used before,
95
- # which mistook a piece's own value-object type for a cross-aggregate
96
- # head every time.
97
- #
98
- # `aggregate_id`, passed only for a piece's own attribute (an
99
- # argument or a parameter carries no value-object type at all — see
100
- # entity.bluebook's/command.bluebook's own comments on why — so the
101
- # generic reader path calls this with one argument and gets the
102
- # old reading unchanged), is the piece's owning aggregate — the same
103
- # one its own attribute types were resolved against on the way in
104
- # (`Judge#owning_aggregate_ref`).
105
- #
106
- # A reference among the other two came in as the head's ID, because
107
- # that is what Command/Query.Reference offer, so it goes back out as
108
- # the encoding the IR spells. A qualified name is the tell : an
109
- # ordinary type names something declared beside it (`Money`,
110
- # `AccountNumber`) and never carries a chapter, while a head's id
111
- # always does.
112
- #
113
- # @param field [Hash{Symbol => Object}] one dispatched attribute,
114
- # argument, or parameter row
115
- # @param aggregate_id [String, nil] the piece's own owning
116
- # aggregate id, passed only for a piece's own attribute
117
- # @return [Hash{Symbol => Object}] `:name` (`Symbol`, `nil`),
118
- # `:type` (`String`), `:list`/`:optional` (`Boolean`), `:default`
119
- # (decoded literal, `nil` when absent), `:pattern`/`:admits`/
120
- # `:relationship` (`String`, `nil` when absent)
50
+ # An argument, a parameter, or (via `aggregate_id`) a piece's own attribute —
51
+ # a piece's own attribute names a value object exactly the way an aggregate's
52
+ # own does, so it takes the same owned-type reading `attribute`, above, does.
121
53
  def shape_field(field, aggregate_id = nil)
122
54
  return attribute(field, aggregate_id) if aggregate_id
123
55
 
@@ -125,10 +57,8 @@ module Hecks
125
57
 
126
58
  {
127
59
  name: text(field[:name])&.to_sym,
128
- # A qualified name is the tell : an ordinary type names something
129
- # declared beside it (`Money`, `AccountNumber`) and carries no join at
130
- # all, where a head's id always does (chapter + name, joined the way
131
- # every derived id is).
60
+ # A qualified name is the tell: an ordinary type (`Money`, `AccountNumber`)
61
+ # carries no join at all, while a head's id always does (chapter + name).
132
62
  type: type.include?(Naming::IDENTITY_JOIN) ? reference_type(type) : text(field[:type]),
133
63
  list: text(field[:list]).to_s == "true",
134
64
  default: decode_literal(text(field[:default])),
@@ -139,109 +69,47 @@ module Hecks
139
69
  }
140
70
  end
141
71
 
142
- # An absent pattern is nil, not "". The language holds every field as
143
- # text, so a field nobody set comes back as the empty string — and ""
144
- # is a real regex (it matches everything), so keeping it would turn
145
- # "no pattern" into "a pattern that always passes" and quietly cost the
146
- # IR its round trip.
147
- #
148
- # @param text [String, nil] a dispatched cell's own already-unwrapped
149
- # text
150
- # @return [String, nil] `text`, or `nil` when `text` is `nil` or
151
- # empty
72
+ # "" is a real regex (matches everything) — kept as-is it would silently
73
+ # turn "no pattern" into "always matches", so it is coerced to nil here.
152
74
  def presence(text)
153
75
  value = text.to_s
154
76
  value.empty? ? nil : value
155
77
  end
156
78
 
157
- # A literal, read back from the self-describing form Readings#encode_literal
158
- # wrote — the same reader Assembly::Marks uses, because it is the same
159
- # spelling. The forms are exactly the five the Primitive vocabulary admits —
160
- # String, Integer, Float, TrueClass, FalseClass — plus a symbol, and an
161
- # object literal, which is what `to: { value: "good" }` is: a value object's
162
- # fields written inline.
163
- #
164
- # @param text [String, nil] the self-describing wire spelling
165
- # `Readings#encode_literal` wrote
166
- # @return [Object] `nil`, `true`, `false`, `Integer`, `Float`,
167
- # `Symbol`, `Hecks::StateRef`, `String`, `Hash`, or `Array` — or
168
- # `text` itself, stripped, when it matches no known spelling
79
+ # The self-describing form `Readings#encode_literal` wrote — the same
80
+ # reader `Assembly::Marks` uses, for the identical spelling.
169
81
  def decode_literal(text) = Literal.read(text)
170
82
 
171
- # Reads a rule's plain description/canonical pair, for a
172
- # `given`/`invariant`/`ensures`.
173
- #
174
- # @param row [Hash{Symbol => Object}] one dispatched rule row
175
- # @return [Hash{Symbol => String}] `:description` and `:canonical`
83
+ # A rule's plain description/canonical pair, for a `given`/`invariant`/`ensures`.
176
84
  def rule(row) = { description: text(row[:description]), canonical: text(row[:canonical]) }
177
85
 
178
- # S12, ADR 0025 — `projects :name, from: :"reference.remote_field"`,
179
- # read back the same three plain identifiers `rule` above reads
180
- # description/canonical as.
181
- #
182
- # @param row [Hash{Symbol => Object}] one dispatched projected-field
183
- # row
184
- # @return [Hash{Symbol => String}] `:name`, `:reference`, and
185
- # `:remote_field`
86
+ # `projects :name, from: :"reference.remote_field"` (ADR 0025), read back as
87
+ # its plain name/reference/remote_field triple.
186
88
  def projected_field(row)
187
89
  { name: text(row[:name]), reference: text(row[:reference]), remote_field: text(row[:remote_field]) }
188
90
  end
189
91
 
190
- # `provenance from: {...}` rides the same literal encoding `default:`
191
- # does — an object literal, self-describing via Hecks::Literal — one
192
- # level up: a whole keyword's argument rather than an attribute's
193
- # `default:`.
194
- #
195
- # @param row [Hash{Symbol => Object}] a dispatched row carrying a
196
- # `:provenance` cell
197
- # @return [Object] the decoded `from:` object literal, or `nil` when
198
- # absent
92
+ # `provenance from: {...}` rides the same literal encoding `default:` does,
93
+ # one level up: a whole keyword's argument rather than an attribute's.
199
94
  def provenance(row) = decode_literal(text(row[:provenance]))
200
95
 
201
- # `command "Debit", from: "open"` — the same literal encoding
202
- # `provenance`/`default:` already ride (S10, ADR 0025), one
203
- # state or an array of them, or nil for a command with no
204
- # lifecycle guard.
205
- #
206
- # @param row [Hash{Symbol => Object}] a dispatched row carrying a
207
- # `:from` cell
208
- # @return [String, Array<String>, nil] the decoded lifecycle guard
209
- # state(s), or `nil` for a command with no lifecycle guard
96
+ # `command "Debit", from: "open"` (ADR 0025) — the same literal encoding
97
+ # `provenance`/`default:` ride, one state or an array of them, or nil.
210
98
  def from(row) = decode_literal(text(row[:from]))
211
99
 
212
- # A flag is held as text ("true"/"false") and emitted as a boolean —
213
- # `Policy#expect_undelivered` on the wire.
214
- #
215
- # @param row [Hash{Symbol => Object}] a dispatched row carrying an
216
- # `:expect_undelivered` cell
217
- # @return [Boolean] whether the flag reads `"true"`
100
+ # A flag held as text ("true"/"false"), emitted as a boolean.
218
101
  def expect_undelivered?(row) = text(row[:expect_undelivered]).to_s == "true"
219
102
 
220
- # The option rows, gathered back into the shapes `extra_options_to_h` spells.
221
- #
222
- # One row per part, so a compound option is several rows and a repeated one is
223
- # several groups told apart by `at`. Grouping by option name and then by `at`
224
- # rebuilds both without either knowing which options exist — the whole point
225
- # of holding them as an open map.
226
- #
227
- # @param row [Hash{Symbol => Object}] a dispatched row carrying an
228
- # `:options` list
229
- # @return [Hash{Symbol => Object}] one entry per option name; each
230
- # value is `gathered`'s own return for that option's own parts
103
+ # Regroups dispatched option rows into the shape `extra_options_to_h` spells:
104
+ # one row per part, several `at`-keyed groups for a repeated option.
231
105
  def options_of(row)
232
106
  Array(row[:options])
233
107
  .group_by { |part| text(part[:option]) }
234
108
  .to_h { |option, parts| [option.to_sym, gathered(parts)] }
235
109
  end
236
110
 
237
- # Groups one option's own dispatched parts back into a single
238
- # binding, or several `at`-keyed groups for a repeated option.
239
- #
240
- # @param parts [Array<Hash{Symbol => Object}>] one option's own
241
- # dispatched key/value/at rows
242
- # @return [Hash{Symbol => String}, Array<Hash{Symbol => String}>]
243
- # a single `key => value` hash when no part carries `at`;
244
- # otherwise an array of such hashes, one per distinct `at`
111
+ # One option's own parts, grouped back into a single binding — or several
112
+ # `at`-keyed groups when the option repeats.
245
113
  def gathered(parts)
246
114
  repeated, single = parts.partition { |part| !text(part[:at]).to_s.empty? }
247
115
  return single.to_h { |part| [text(part[:key]).to_sym, text(part[:value])] } if repeated.empty?
@@ -251,29 +119,14 @@ module Hecks
251
119
  .map { |group| group.to_h { |part| [text(part[:key]).to_sym, text(part[:value])] } }
252
120
  end
253
121
 
254
- # The IR keeps a where's field as a string, not a symbol — it is read back
255
- # out, never called. The value stays raw text here on purpose : this
256
- # feeds the declaration hash Assembly::Marks#where_clause decodes
257
- # from (via `read`), and decoding twice is worse than once — a
258
- # kwarg reference (":ceiling") decoded here into the Symbol :ceiling
259
- # would have its colon stripped by `read`'s own `.to_s` and come
260
- # back out as the plain string "ceiling", indistinguishable from a
261
- # literal of the same name. One decode, at the one place that builds
262
- # the object every comparator actually reads.
263
- #
264
- # @param row [Hash{Symbol => Object}] one dispatched where-clause row
265
- # @return [Hash{Symbol => String}] `:field`, `:op`, and `:value`
266
- # (raw text, undecoded)
122
+ # Kept as raw text, not decoded: this feeds `Assembly::Marks#where_clause`,
123
+ # which decodes it via `read` — decoding here first would strip a kwarg
124
+ # reference's colon, indistinguishable after from a same-named literal.
267
125
  def where_clause(row)
268
126
  { field: text(row[:field]), op: text(row[:op]), value: text(row[:value]) }
269
127
  end
270
128
 
271
129
  # One object in the IR, two fields in the language.
272
- #
273
- # @param row [Hash{Symbol => Object}] a dispatched row carrying
274
- # `:order_field`/`:order_way` cells
275
- # @return [Hash{Symbol => String}, nil] `:field` and `:direction`,
276
- # or `nil` when no `order_field` was declared
277
130
  def order_by(row)
278
131
  field = text(row[:order_field])
279
132
  return nil if field.to_s.empty?
@@ -281,12 +134,7 @@ module Hecks
281
134
  { field: field, direction: text(row[:order_way]) }
282
135
  end
283
136
 
284
- # Reads a read model's own declared row limit.
285
- #
286
- # @param row [Hash{Symbol => Object}] a dispatched row carrying a
287
- # `:limit` cell
288
- # @return [Hash{Symbol => String}, nil] `{value: ceiling}`, or `nil`
289
- # when no limit was declared
137
+ # A read model's own declared row limit, or nil when none was declared.
290
138
  def limit(row)
291
139
  ceiling = text(row[:limit])
292
140
  return nil if ceiling.to_s.empty?
@@ -294,12 +142,6 @@ module Hecks
294
142
  { value: ceiling }
295
143
  end
296
144
 
297
- # Reads one lifecycle transition row.
298
- #
299
- # @param row [Hash{Symbol => Object}] one dispatched lifecycle
300
- # transition row
301
- # @return [Hash{Symbol => String}] `:command`, `:from_state`, and
302
- # `:to_state`
303
145
  def transition(row)
304
146
  {
305
147
  command: text(row[:command]),
@@ -308,83 +150,38 @@ module Hecks
308
150
  }
309
151
  end
310
152
 
311
- # Reads one reference head — a process manager handler's own
312
- # aggregate binding.
313
- #
314
- # @param row [Hash{Symbol => Object}] one dispatched reference-head
315
- # row
316
- # @return [Hash{Symbol => Object}] `:aggregate`/`:as` (`String`) and
317
- # `:many` (`Boolean`)
318
153
  def head(row)
319
154
  {
320
155
  aggregate: text(row[:aggregate]),
321
- # A String, like an entity's identified_by. The IR is not uniform about
322
- # this and only a round trip says so.
156
+ # A String, like an entity's identified_by. The IR is not uniform
157
+ # about this and only a round trip says so.
323
158
  as: text(row[:as]),
324
159
  many: text(row[:many]).to_s == "true"
325
160
  }
326
161
  end
327
162
 
328
- # Reads a read model's own `group_by` field name.
329
- #
330
- # @param row [Hash{Symbol => Object}] a dispatched row carrying a
331
- # `:field` cell
332
- # @return [Hash{Symbol => String}] `{field: ...}`
333
163
  def group_by_field(row) = { field: text(row[:field]) }
334
164
 
335
- # `count`'s own boolean, read back the same way `head`'s own
336
- # `many` is (`text(row[:many]).to_s == "true"`) — except a
337
- # `ReadModel.Count` command is dispatched at all only when
338
- # `@count` was truthy (`MetaValidator::Judge#setters` skips a
339
- # setter whose every source is absent), so an undeclared read
340
- # model's own `count` field never gets written and comes back
341
- # `nil` here, never `"false"` — matching `ReadModel#to_h`'s own
342
- # `true`/`nil` pair (never `false`) exactly, rather than the
343
- # unconditional `true`/`false` `head`'s own `many` needs (every
344
- # head does get a `Gather` dispatch, declared or derived).
345
- #
346
- # @param row [Hash{Symbol => Object}] a dispatched row carrying a
347
- # `:count` cell
348
- # @return [Boolean, nil] `true` when the flag reads `"true"`, `nil`
349
- # for an undeclared read model's own `count`
165
+ # Mirrors `head`'s own `many`, but nil (never `false`) for an undeclared
166
+ # read model — matching `ReadModel#to_h`'s own true/nil pairing.
350
167
  def read_model_count(row) = (true if text(row[:count]).to_s == "true")
351
168
 
352
- # The append flattening, in reverse.
353
- #
354
- # An append binds several fields at once and the language's Change holds one
355
- # field/kind/source triple, so the walk offers an append once per binding.
356
- # Rebuilding groups those rows back into the single mutation the IR keeps —
357
- # the only place here that undoes something rather than simply reading it.
358
- #
359
- # @param row [Hash{Symbol => Object}] a dispatched row carrying a
360
- # `:mutations` list
361
- # @return [Array<Hash{Symbol => Object}>] one hash per distinct
362
- # `target`/`op` pair, each `mutation`'s own return
169
+ # `percentile_at` is stored as text (the self-hosted grammar's own
170
+ # `ReadModelText`, ADR 0078), but the wire and `ReadModel#initialize`'s
171
+ # own `&.to_f` both want a Float.
172
+ def read_model_percentile_at(row) = text(row[:percentile_at])&.to_f
173
+
174
+ # The append flattening, in reverse: regroups per-binding rows back
175
+ # into one mutation per distinct target/op pair.
363
176
  def mutations(row)
364
177
  Array(row[:mutations])
365
178
  .group_by { |change| [text(change[:target]), text(change[:op])] }
366
179
  .map { |(target, op), bindings| mutation(target, op, bindings) }
367
180
  end
368
181
 
369
- # `sign:` — read the same way the declared side computes it
370
- # (`Bluebook::Mutation.sign_for`, item #5 of the whole-project
371
- # table-unification survey), not stored on any row here — the
372
- # meta-domain's own Change entity carries no `sign` field of its
373
- # own (it is a pure function of `op`, nothing to persist), so
374
- # reconstruction recomputes it the same way a freshly-built
375
- # Mutation's own `to_h` lambda does, rather than leaving the key
376
- # silently absent (spec/round_trip_spec's whole point: a field the
377
- # language does not hold is a named gap, not a byte-for-byte one).
378
- #
379
- # @param target [String] the mutated field's own name
380
- # @param oper [String] the mutation's operation name, such as
381
- # `"set"`, `"append"`, `"delegate"`, or `"corrects"`
382
- # @param bindings [Array<Hash{Symbol => Object}>] this target/op
383
- # pair's own dispatched binding rows
384
- # @return [Hash{Symbol => Object}] `:target`/`:op` (`Symbol`),
385
- # `:sign` (`String`), plus `:fields` (`appended`'s own return) for
386
- # `"append"`/`"delegate"`/`"corrects"`, or `:source`
387
- # (`classified`'s own return) for anything else
182
+ # `sign:` is recomputed via `Mutation.sign_for`, not stored on any row —
183
+ # Change carries no `sign` field of its own, so a fresh Mutation's `to_h`
184
+ # derives it the same way here, rather than leaving the key silently absent.
388
185
  def mutation(target, oper, bindings)
389
186
  base = { target: target.to_sym, op: oper.to_sym, sign: Hecks::Bluebook::Mutation.sign_for(oper) }
390
187
  # `:delegate`/`:corrects` (CommandBuilder#delegates_to's and
@@ -395,24 +192,13 @@ module Hecks
395
192
  base.merge(source: classified(bindings.first))
396
193
  end
397
194
 
398
- # Rebuilds an append's own field -> source map from its flattened
399
- # per-binding rows.
400
- #
401
- # @param bindings [Array<Hash{Symbol => Object}>] one append's own
402
- # dispatched binding rows
403
- # @return [Hash{Symbol => String}] each bound field name mapped to
404
- # its own source text
195
+ # Rebuilds an append's own field -> source map from its flattened per-binding rows.
405
196
  def appended(bindings)
406
197
  bindings.to_h { |binding| [text(binding[:field]).to_sym, text(binding[:source])] }
407
198
  end
408
199
 
409
- # Classifies a single-binding mutation's own source.
410
- #
411
- # @param binding [Hash{Symbol => Object}] one dispatched binding row
412
- # @return [Hash{Symbol => Object}] `{kind: "argument"|"state",
413
- # name: String}` for an argument or state reference, or
414
- # `{kind: "literal", value: Object}` (the decoded literal) for
415
- # anything else
200
+ # Classifies a single-binding mutation's own source: argument/state
201
+ # reference, or a decoded literal.
416
202
  def classified(binding)
417
203
  kind = text(binding[:kind])
418
204
  value = text(binding[:source])