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
@@ -4,8 +4,7 @@ Hecks.bluebook "Bluebook" do
4
4
 
5
5
  reference_to Bluebook
6
6
 
7
- # THE CHAPTER IT IS IN, AND ITS NAME — the same shape a policy takes, and for
8
- # the same reason.
7
+ # The chapter it belongs to, and its name, as for a policy.
9
8
  identified_by :bluebook, :name
10
9
 
11
10
  attribute :name, ProcessManagerName
@@ -13,10 +12,7 @@ Hecks.bluebook "Bluebook" do
13
12
  attribute :starts_on, ProcessManagerText
14
13
  attribute :ends_on, ProcessManagerText
15
14
  attribute :states, list_of(SagaState)
16
- # S17, ADR 0026 — Handler nested here (see `entity "Handler"`, below),
17
- # an entity rather than its own root aggregate. `list_of(Handler)`
18
- # forward-references it the same way banking's own `attribute :ledger,
19
- # list_of(LedgerEntry)` names LedgerEntry before it is declared.
15
+ # Handler is a nested entity (below); list_of forward-references it.
20
16
  attribute :handlers, list_of(Handler)
21
17
 
22
18
  value_object "ProcessManagerName" do
@@ -32,15 +28,8 @@ Hecks.bluebook "Bluebook" do
32
28
  attribute :name, String
33
29
  end
34
30
 
35
- # S17, ADR 0026 — HandlerText/DispatchText/Binding, hoisted up from
36
- # the old standalone `aggregate "Handler"`/`aggregate "Dispatch"`. An
37
- # entity cannot declare its own `value_object` (EntityBuilder has no
38
- # such method — a piece borrows its owning aggregate's, the same way
39
- # LedgerEntry borrows Account's Money), so these live here now, at
40
- # the ROOT, where BOTH `entity "Handler"` and its own nested `entity
41
- # "Dispatch"` can still reach them — a piece mints no value objects
42
- # of its own AT ANY DEPTH, so there is exactly one pool however deep
43
- # the nesting goes (`EntityBuilder#entity`'s own comment).
31
+ # Value objects live at the root: an entity mints none of its own at any depth, so Handler and
32
+ # its nested Dispatch share this one pool.
44
33
  value_object "HandlerText" do
45
34
  attribute :value, String
46
35
  end
@@ -54,36 +43,15 @@ Hecks.bluebook "Bluebook" do
54
43
  attribute :value, String
55
44
  end
56
45
 
57
- # ONE DISPATCH'S OWN ORDER AMONG ITS HANDLER'S SIBLINGS — named
58
- # DispatchPosition rather than reusing ProcessManager's own `Position`
59
- # four lines below (same discipline as `MemberPosition`/shape.bluebook's
60
- # own comment on the identical choice): that one orders process
61
- # managers among a CHAPTER's siblings ; this one orders dispatches
62
- # within ONE handler. Same shape, different fact.
63
- #
64
- # Part of `identified_by`, below, alongside `command_name` — a real
65
- # handler fans the SAME command out more than once with different
66
- # `with:` bindings each leg (item #151's own real example: one
67
- # BodyPulse handler dispatching Signal.FireSignal once per organ),
68
- # and `command_name` alone collided the instant it did: the Judge's
69
- # own `entity_duplicate` check raised the moment a second dispatch of
70
- # the same command was declared, an uncaught crash for a legitimate,
71
- # common pattern. `position` names WHICH send this is and is safe to
72
- # fold into identity exactly where it would not be for Handler's own
73
- # `from_state` (a real business value) — a Dispatch is declared once,
74
- # at load time, and never re-addressed by identity afterward.
46
+ # Orders one handler's dispatches; Position orders process managers within a chapter.
47
+ # Part of Dispatch identity: a handler may send the same command several times with different
48
+ # `with:` bindings, so command_name alone collides.
75
49
  value_object "DispatchPosition" do
76
50
  attribute :value, Integer
77
51
  end
78
52
 
79
- # The way back: everything DECLARED IN the chapter above. The parent
80
- # reference IS the query.
81
- # WHERE IT SITS AMONG ITS SIBLINGS. Declaration order is a FACT ABOUT THE
82
- # SOURCE — the IR is a contract read straight from this file,
83
- # field for field AND INDEX FOR INDEX. So the language HOLDS it, instead of
84
- # inheriting it from whatever order a store happens to iterate: an ask that
85
- # does not say how it is ordered is answered in identity order, which is
86
- # right for every other ask and fatal for the one that is the SOURCE.
53
+ # Declaration order among siblings. The IR is read index for index, so the language
54
+ # holds it rather than inheriting whatever order a store iterates.
87
55
  value_object "Position" do
88
56
  attribute :value, Integer
89
57
  end
@@ -103,12 +71,7 @@ Hecks.bluebook "Bluebook" do
103
71
  attribute :name, ProcessManagerName
104
72
  attribute :correlates_by, ProcessManagerText
105
73
  attribute :starts_on, ProcessManagerText
106
- # A PROCEDURE NEED NOT DECLARE AN ENDING. The runtime has always held
107
- # this optional — ProcessManagerBuilder defaults `@ends_on` to nil,
108
- # validates only correlates_by/starts_on/states/handlers,
109
- # and fills it only if the line is written. The
110
- # language was the one saying it was required, and nothing in the corpus
111
- # had to disagree because every procedure in it happens to end.
74
+ # A procedure need not declare an ending; ProcessManagerBuilder defaults @ends_on to nil.
112
75
  attribute :ends_on, ProcessManagerText, optional: true
113
76
 
114
77
  attribute :position, Position, optional: true
@@ -132,27 +95,15 @@ Hecks.bluebook "Bluebook" do
132
95
  emits SagaStateAttached
133
96
  end
134
97
 
135
- # THE HANDLER'S OWN CREATION. S17, ADR 0026 — Handler is a genuine
136
- # ENTITY now (`entity "Handler"`, below), and an entity is never
137
- # created through its own dotted verb — banking's own LedgerEntry is
138
- # created by `Account.LogEntry`, an ordinary append on the OWNER,
139
- # never by a `LedgerEntry.Declare` of its own
140
- # (`EntityInterpreter#element_of` only LOCATES an element already on
141
- # the list — it has no path that creates one). So Handler's creation
142
- # moved here, onto ProcessManager, mirroring `State` beside it: a
143
- # bare, aggregate-level append.
98
+ # Handler creation lives here, not on Handler: an entity is created by an append on its owner,
99
+ # never by a dotted verb of its own.
144
100
  command "Handler" do
145
101
  role "Language"
146
102
  goal "Open a handler inside a process manager"
147
103
 
148
104
  attribute :event_type, HandlerText
149
- # A LEG ALWAYS SAYS WHERE IT MOVES FROM. There is no wildcard leg to be
150
- # optional for: `on "Event", transition: { from => to }` is the only
151
- # spelling the runtime reads, and it refuses anything else —
152
- # `single_transition` raises unless the hash holds exactly one from => to
153
- # pair, so a leg without one
154
- # is never built at all. `optional: true` here was
155
- # the language admitting a leg the runtime cannot parse.
105
+ # A leg always names its from state: the runtime refuses a transition without exactly one
106
+ # from => to pair.
156
107
  attribute :from_state, HandlerText
157
108
  attribute :to_state, HandlerText
158
109
 
@@ -161,59 +112,27 @@ Hecks.bluebook "Bluebook" do
161
112
  emits LegDeclared
162
113
  end
163
114
 
164
- # S17, ADR 0026 — ONE HANDLER, nested rather than its own root
165
- # aggregate. No `saga` field. It named the old word for a process
166
- # manager, held nothing — ProcessManagerHandler has no such reader,
167
- # so every Handler record's saga was empty — and repeated the parent
168
- # that its own containment already carries. A field that names the
169
- # wrong thing, holds nothing, and duplicates the reference beside it.
170
- #
171
- # `event_type` is an event name, or one of the Trigger vocabulary's
172
- # members when the leg answers something no aggregate announces — but
173
- # NOT, alone, Handler's own identity any more (items #151/#152's own
174
- # finding): a state machine legitimately answers the SAME event
175
- # differently depending on which state it is currently in — one event
176
- # name, several distinct legs (a BodyPulse handler that moves
177
- # `attentive -> attentive` and, separately, `sleeping_light ->
178
- # sleeping_light`) — and `event_type` alone collided the instant a
179
- # real corpus declared that shape: the Judge's own `entity_duplicate`
180
- # check raised `AlreadyExists` the moment the second leg was declared,
181
- # an uncaught crash, not a refusal, for a common, legitimate pattern.
182
- # `from_state` joins it below for exactly this reason — a real
183
- # business value, not a stand-in for missing meaning, the same
184
- # distinction `DispatchPosition`'s own comment (above) draws for its
185
- # sibling `Dispatch`. The process manager this leg belongs to stays
186
- # structural (which list this element sits in), never a stored field.
115
+ # One handler, nested under its process manager. event_type alone is not identity: one
116
+ # event can drive several legs from different states, so from_state joins it.
187
117
  entity "Handler" do
188
118
  description "One handler inside a process manager — the event it answers, the state move it makes, and the commands it sends. Nested under the process manager because a handler holds nested dispatches, which hold nested bindings."
189
119
 
190
120
  attribute :event_type, HandlerText
191
121
  attribute :from_state, HandlerText
192
122
  attribute :to_state, HandlerText
193
- # S17, ADR 0026 — Dispatch nested here too (see `entity "Dispatch"`,
194
- # below), one level further in than Handler itself.
195
123
  attribute :dispatches, list_of(Dispatch)
196
124
 
197
- # BOTH FIELDS TOGETHER — see the class-level comment above.
198
125
  identified_by :event_type, :from_state
199
126
 
200
- # THE DISPATCH'S OWN CREATION — same reason Handler's own creation
201
- # lives on ProcessManager, one level up: an entity is never created
202
- # through its own dotted verb. Reached as a DOTTED verb itself
203
- # (`ProcessManager.Handler.Dispatch`) since Handler, the owner
204
- # doing the creating here, is an entity too, not a real aggregate
205
- # with a bare verb of its own to dispatch into.
127
+ # Dispatch creation lives on the owner, reached as the dotted verb
128
+ # ProcessManager.Handler.Dispatch because Handler is an entity.
206
129
  command "Dispatch" do
207
130
  role "Language"
208
131
  goal "Open a dispatch inside a handler"
209
132
 
210
133
  attribute :command_name, DispatchText
211
- # THE WALK INDEX, never author-supplied — the same generic
212
- # POSITION handling `ValueObject.Member`'s own creating command
213
- # already relies on (`Judge#appends`), which fills this from
214
- # where the walk found the dispatch, not from a field the row
215
- # happens to hold. No real `.bluebook` author ever calls this
216
- # verb directly; only the Judge's own replay does.
134
+ # The walk index, filled by the Judge's replay from where it found the dispatch; never
135
+ # author-supplied.
217
136
  attribute :position, DispatchPosition
218
137
 
219
138
  sets :dispatches, append: { command_name: :command_name, position: :position }
@@ -221,19 +140,8 @@ Hecks.bluebook "Bluebook" do
221
140
  emits SendDeclared
222
141
  end
223
142
 
224
- # S17, ADR 0026 — ONE COMMAND A HANDLER DISPATCHES, nested two
225
- # levels in rather than its own root aggregate — "no life outside
226
- # its Handler" (the ADR's own words). The bindings are an open
227
- # map, which no value object can hold — that was always a reason
228
- # it could not be one, never a reason it could not be an entity.
229
- # `command_name` ALONE used to be Dispatch's own identity, the same
230
- # shape Handler's own `event_type` took one level up — and collided
231
- # the same way, for the same real reason (item #151): one handler
232
- # fanning the SAME command out several times with different `with:`
233
- # bindings each time (one BodyPulse handler dispatching
234
- # Signal.FireSignal once per organ). `position` joins it below —
235
- # see `DispatchPosition`'s own comment for why that field, unlike
236
- # Handler's `from_state`, is safe to fold into identity.
143
+ # One command a handler dispatches. Identity is command_name plus position, since a
144
+ # handler may send the same command several times with different bindings.
237
145
  entity "Dispatch" do
238
146
  description "One command a handler dispatches, with the arguments it binds. Nested under the handler because the bindings are an open map, which no value object can hold."
239
147
 
@@ -256,23 +164,8 @@ Hecks.bluebook "Bluebook" do
256
164
  emits BindingAttached
257
165
  end
258
166
 
259
- # THE COMPENSATING DISPATCH THIS ONE COMPENSATES FOR, IF ANY —
260
- # FLAT FIELDS on THIS SAME entity, mirroring `command_name`/
261
- # `with_spec` above one-for-one, rather than a nested (or
262
- # self-referential) second `Dispatch`: an entity's own attribute
263
- # type has to resolve against a value object, and neither a
264
- # self-reference to `Dispatch` (written from inside its own
265
- # block, before it exists to reference) nor a plain nested
266
- # entity reference passes that check the way `Handler.
267
- # dispatches: list_of(Dispatch)` does — that one resolves a
268
- # SIBLING already fully built by the time deferred construction
269
- # (ADR 0028) finishes; a dispatch compensating for itself has no
270
- # such sibling. `compensates_command_name` absent means no
271
- # compensation; present, together with whatever
272
- # `compensates_with_spec` holds, is everything
273
- # `Reconstruction#dispatch` needs to assemble the SAME
274
- # `DispatchSpec` shape `compensates` (the real, author-facing
275
- # word) fills.
167
+ # The dispatch this one compensates for, as flat fields: an entity attribute must
168
+ # resolve against a value object, so a self-referential Dispatch is not possible.
276
169
  attribute :compensates_command_name, DispatchText, optional: true
277
170
  attribute :compensates_with_spec, list_of(Binding)
278
171
 
@@ -301,9 +194,7 @@ Hecks.bluebook "Bluebook" do
301
194
  end
302
195
  end
303
196
 
304
- # HOW PROCESSMANAGER IS SPELLED. These rows live with the concept
305
- # they describe; SyntaxBoot discovers every aggregate-local seed table.
306
- # Contexts represented here: ProcessManager, Handler.
197
+ # Keyword and argument rows for process managers and handlers.
307
198
  value_object "KeywordSeed" do
308
199
  attribute :word, String
309
200
  attribute :context, String, admits: "Syntax::Context"
@@ -317,27 +208,13 @@ Hecks.bluebook "Bluebook" do
317
208
  attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
318
209
 
319
210
  member word: "correlates_by", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "correlates_by"
320
- # BARE CONSTANT ACCEPTED (ADR 0025, S6 — "events first-class"),
321
- # `starts_on Transfer::TransferRequested` / `ends_on
322
- # Transfer::TransferSettled`, same `kind: "constant"` + `kind:
323
- # "text"` ArgumentSeed pair `emits`/policy's own `on` already
324
- # carry (this row's own comment there). Now `calls:`-routed
325
- # (`starts_on_impl`/`ends_on_impl`, hand-written — GenericDispatch's
326
- # own `COERCE_BY_KIND` has no "constant" entry, so a bare
327
- # constant needs the same `Naming.event_ref` resolution `on_impl`/
328
- # `transition_impl` already do, not the plain `.to_s` a single
329
- # `kind: "text"` row used to get for free).
211
+ # starts_on and ends_on accept a bare constant or text; they route through hand-written impls
212
+ # because COERCE_BY_KIND has no "constant" entry and Naming.event_ref must resolve it.
330
213
  member word: "starts_on", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "", calls: "starts_on_impl"
331
214
  member word: "ends_on", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "", calls: "ends_on_impl"
332
215
  member word: "transition", context: "ProcessManager", body: "keywords", inner: "Handler", opens: "Handler", fills: "", calls: "transition_impl"
333
216
  member word: "transition", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "", calls: "transition_impl"
334
- # TWO ROWS, the SAME PAIR SHAPE `transition` takes just above —
335
- # `body: "none"` was already the only row (`opens: "Dispatch"`
336
- # already anticipated a block, unused until now); `body:
337
- # "keywords"` is the new one, opening `compensates` on the
338
- # dispatch it sits inside (per-dispatch saga compensation — see
339
- # `ProcessManagerBuilder::HandlerBuilder#dispatch_impl`'s own
340
- # comment).
217
+ # Two rows per dispatch: one with a block (opening `compensates`), one without.
341
218
  member word: "dispatch", context: "Handler", body: "keywords", inner: "Dispatch", opens: "Dispatch", fills: "", calls: "dispatch_impl"
342
219
  member word: "dispatch", context: "Handler", body: "none", inner: "", opens: "Dispatch", fills: "", calls: "dispatch_impl"
343
220
  member word: "compensates", context: "Dispatch", body: "none", inner: "", opens: "", fills: "", calls: "compensates_impl"
@@ -4,7 +4,7 @@ Hecks.bluebook "Bluebook" do
4
4
 
5
5
  reference_to Bluebook
6
6
 
7
- # THE CHAPTER IT IS IN, AND ITS NAME.
7
+ # The chapter it belongs to, and its name.
8
8
  identified_by :bluebook, :name
9
9
 
10
10
  attribute :name, ReadModelName
@@ -13,26 +13,23 @@ Hecks.bluebook "Bluebook" do
13
13
  attribute :reference_name, ReadModelText
14
14
  attribute :reference_target, ReadModelText
15
15
  attribute :aggregate_heads, list_of(Head)
16
- # The same open map a query carries — see Query's AskOption. A read model
17
- # inherits every specification option an ask has, so it holds them the same way.
16
+ # The same open map a query carries (see Query's AskOption).
18
17
  attribute :options, list_of(ProjectionOption)
19
- # WHICH of the eligible head's own fields to nest its rows under, in
20
- # declared order. Rows, not a single value object with N fields — an
21
- # arbitrary NUMBER of fields, the same reason `aggregate_heads`/
22
- # `options` are lists rather than fixed attributes.
18
+ # Fields whose values nest the eligible head's rows, in declared order; a list because the
19
+ # number of fields is open.
23
20
  attribute :group_by, list_of(GroupByField)
24
- # `count`/`median_field` are the OTHER two reductions a read model
25
- # may declare over its one eligible head, siblings of `group_by`
26
- # rather than of `options` — same permissive `ReadModelText` shape,
27
- # and the same UNmarked-optional spelling `reference_name`/
28
- # `reference_target` already use just above (permissiveness lives
29
- # in `ReadModelText`'s own lack of an invariant, not in an
30
- # `optional:` flag this chapter's aggregate-level attributes never
31
- # carry) — "true"/"" for `count`, a field name or "" for
32
- # `median_field`, both legitimately absent on a read model that
33
- # declares neither.
21
+ # The other reductions over the one eligible head; empty when none is declared
22
+ # (ADR 0078 — a read model reports one shape, so at most one is ever set).
34
23
  attribute :count, ReadModelText, optional: true
35
24
  attribute :median_field, ReadModelText, optional: true
25
+ attribute :sum_field, ReadModelText, optional: true
26
+ attribute :avg_field, ReadModelText, optional: true
27
+ attribute :min_field, ReadModelText, optional: true
28
+ attribute :max_field, ReadModelText, optional: true
29
+ attribute :percentile_field, ReadModelText, optional: true
30
+ attribute :percentile_at, ReadModelText, optional: true
31
+ attribute :any_field, ReadModelText, optional: true
32
+ attribute :all_field, ReadModelText, optional: true
36
33
 
37
34
  value_object "ReadModelName" do
38
35
  attribute :value, String
@@ -40,8 +37,7 @@ Hecks.bluebook "Bluebook" do
40
37
  end
41
38
 
42
39
  value_object "ReadModelText" do
43
- # deliberately permissive : query_name / ref_name / ref_target are
44
- # legitimately empty on a read model that has not named them yet
40
+ # Deliberately permissive: query_name and the reference fields may be legitimately empty.
45
41
  attribute :value, String
46
42
  end
47
43
 
@@ -60,7 +56,7 @@ Hecks.bluebook "Bluebook" do
60
56
  attribute :option, String
61
57
  attribute :key, String
62
58
  attribute :value, String
63
- # optional: not every projection option carries an `at` (C3.7)
59
+ # Only some options carry an `at`.
64
60
  attribute :at, String, optional: true
65
61
  end
66
62
 
@@ -69,14 +65,8 @@ Hecks.bluebook "Bluebook" do
69
65
  invariant("a group_by field is named") { !field.to_s.empty? }
70
66
  end
71
67
 
72
- # The way back: everything DECLARED IN the chapter above. The parent
73
- # reference IS the query.
74
- # WHERE IT SITS AMONG ITS SIBLINGS. Declaration order is a FACT ABOUT THE
75
- # SOURCE — the IR is a contract read straight from this file,
76
- # field for field AND INDEX FOR INDEX. So the language HOLDS it, instead of
77
- # inheriting it from whatever order a store happens to iterate: an ask that
78
- # does not say how it is ordered is answered in identity order, which is
79
- # right for every other ask and fatal for the one that is the SOURCE.
68
+ # Declaration order among siblings. The IR is read index for index, so the language
69
+ # holds it rather than inheriting whatever order a store iterates.
80
70
  value_object "Position" do
81
71
  attribute :value, Integer
82
72
  end
@@ -96,10 +86,7 @@ Hecks.bluebook "Bluebook" do
96
86
  attribute :name, ReadModelName
97
87
  attribute :description, ProjectionPurpose, optional: true
98
88
  attribute :query_name, ReadModelText
99
- # Both optional now — a ROOTLESS read model (no `reference_to`
100
- # declared at all) has neither. Permanently empty, not "not yet
101
- # set" — see Gather's own comment below for why that distinction
102
- # matters.
89
+ # Optional: a rootless read model (no `reference_to`) permanently has neither (see Gather).
103
90
  attribute :reference_name, ReadModelText, optional: true
104
91
  attribute :reference_target, ReadModelText, optional: true
105
92
 
@@ -118,26 +105,14 @@ Hecks.bluebook "Bluebook" do
118
105
  role "Language"
119
106
  goal "Attach one aggregate head to the read model"
120
107
 
121
- # A HEAD IS THE AGGREGATE IT NAMES. There is no head with nothing gathered:
122
- # `add_aggregate_head` is only ever reached from an `include Target`,
123
- # so the builder cannot produce one
124
- # without it — the field is a plain
125
- # required, non-empty name. `as` and
126
- # `many` are both DERIVED from it when the author does not spell them, which
127
- # is the clearest statement that it is the part that cannot be missing.
108
+ # A head is the aggregate it names; add_aggregate_head is only reached from `include Target`.
109
+ # `as` and `many` are derived from it when the author does not spell them.
128
110
  attribute :aggregate, ReadModelText
129
111
  attribute :as, ReadModelText
130
112
  attribute :many, ReadModelText
131
113
 
132
- # NOT "reference_target must already be set" anymore — reference_target
133
- # is fixed forever at Declare time (nothing ever changes it later), so
134
- # that rule was really "this read model must have SOME reference, ever"
135
- # — exactly the constraint a ROOTLESS read model (bulk, no root,
136
- # `group_by`'s own real use) deliberately doesn't meet, permanently,
137
- # on purpose, not by omission. Removed rather than relaxed: there is
138
- # no runtime fact left here that distinguishes "forgot to declare a
139
- # reference" from "declared rootless on purpose" — both look
140
- # identical (`reference_target` empty) by the time Gather is judged.
114
+ # No "reference_target must be set" given: a rootless read model (bulk, group_by) permanently
115
+ # lacks one, which is indistinguishable from forgetting to declare it.
141
116
 
142
117
  sets :aggregate_heads, append: { aggregate: :aggregate, as: :as, many: :many }
143
118
 
@@ -157,14 +132,8 @@ Hecks.bluebook "Bluebook" do
157
132
  emits GroupByFieldAdded
158
133
  end
159
134
 
160
- # `count`/`median` are LATE-SET scalars, the same shape `Lifecycle`'s
161
- # own `state_field`/`state_start` already are on `Aggregate`
162
- # (aggregate.bluebook) — a command carrying its own value and a bare
163
- # `sets field, to: field` copying it onto the record, rather
164
- # than an `append:` (they are not lists, and there is only ever one
165
- # of each). `count`/`median_field` are declared here, not folded
166
- # into `Declare`, for the same reason `GroupBy` is its own command
167
- # above: neither is known until the DSL body runs past `include`.
135
+ # count and median are late-set scalars, like Lifecycle's state_field: one value each, copied
136
+ # by `sets`, and unknown until the DSL body runs past `include`.
168
137
  command "Count" do
169
138
  role "Language"
170
139
  goal "Mark the read model as a bare row count over its one eligible collection"
@@ -187,13 +156,91 @@ Hecks.bluebook "Bluebook" do
187
156
  emits MedianFieldSet
188
157
  end
189
158
 
159
+ command "Sum" do
160
+ role "Language"
161
+ goal "Mark the read model as the total of one numeric field across its one eligible collection"
162
+
163
+ given("a sum field is named") { !sum_field.value.to_s.empty? }
164
+
165
+ sets :sum_field
166
+
167
+ emits SumFieldSet
168
+ end
169
+
170
+ command "Avg" do
171
+ role "Language"
172
+ goal "Mark the read model as the mean of one numeric field across its one eligible collection"
173
+
174
+ given("an avg field is named") { !avg_field.value.to_s.empty? }
175
+
176
+ sets :avg_field
177
+
178
+ emits AvgFieldSet
179
+ end
180
+
181
+ command "Min" do
182
+ role "Language"
183
+ goal "Mark the read model as the smallest value of one numeric field across its one eligible collection"
184
+
185
+ given("a min field is named") { !min_field.value.to_s.empty? }
186
+
187
+ sets :min_field
188
+
189
+ emits MinFieldSet
190
+ end
191
+
192
+ command "Max" do
193
+ role "Language"
194
+ goal "Mark the read model as the largest value of one numeric field across its one eligible collection"
195
+
196
+ given("a max field is named") { !max_field.value.to_s.empty? }
197
+
198
+ sets :max_field
199
+
200
+ emits MaxFieldSet
201
+ end
202
+
203
+ command "Percentile" do
204
+ role "Language"
205
+ goal "Mark the read model as one interpolated rank of one numeric field across its one eligible collection"
206
+
207
+ given("a percentile field is named") { !percentile_field.value.to_s.empty? }
208
+
209
+ sets :percentile_field
210
+ sets :percentile_at
211
+
212
+ emits PercentileFieldSet
213
+ end
214
+
215
+ command "Any" do
216
+ role "Language"
217
+ goal "Mark the read model as whether any row's boolean field is true across its one eligible collection"
218
+
219
+ given("an any field is named") { !any_field.value.to_s.empty? }
220
+
221
+ sets :any_field
222
+
223
+ emits AnyFieldSet
224
+ end
225
+
226
+ command "All" do
227
+ role "Language"
228
+ goal "Mark the read model as whether every row's boolean field is true across its one eligible collection"
229
+
230
+ given("an all field is named") { !all_field.value.to_s.empty? }
231
+
232
+ sets :all_field
233
+
234
+ emits AllFieldSet
235
+ end
236
+
190
237
  command "Option" do
191
238
  role "Language"
192
239
  goal "Attach one part of one specification option to the read model"
193
240
 
194
241
  attribute :option, ReadModelText
195
242
  attribute :key, ReadModelText
196
- # Same reading as Query.Option above — an option key may stand alone.
243
+ # Same reading as Query.Option: an option key may stand alone.
197
244
  attribute :value, ReadModelText, optional: true
198
245
  attribute :at, ReadModelText, optional: true
199
246
 
@@ -204,9 +251,7 @@ Hecks.bluebook "Bluebook" do
204
251
  emits OptionAttached
205
252
  end
206
253
 
207
- # HOW READMODEL IS SPELLED. These rows live with the concept
208
- # they describe; SyntaxBoot discovers every aggregate-local seed table.
209
- # Contexts represented here: ReadModel.
254
+ # Keyword and argument rows for read models; SyntaxBoot discovers every aggregate-local table.
210
255
  value_object "KeywordSeed" do
211
256
  attribute :word, String
212
257
  attribute :context, String, admits: "Syntax::Context"
@@ -225,6 +270,13 @@ Hecks.bluebook "Bluebook" do
225
270
  member word: "group_by", context: "ReadModel", body: "none", inner: "", opens: "", fills: "group_by", calls: "group_by_impl"
226
271
  member word: "count", context: "ReadModel", body: "none", inner: "", opens: "", fills: "count"
227
272
  member word: "median", context: "ReadModel", body: "none", inner: "", opens: "", fills: "median_field"
273
+ member word: "sum", context: "ReadModel", body: "none", inner: "", opens: "", fills: "sum_field"
274
+ member word: "avg", context: "ReadModel", body: "none", inner: "", opens: "", fills: "avg_field"
275
+ member word: "min", context: "ReadModel", body: "none", inner: "", opens: "", fills: "min_field"
276
+ member word: "max", context: "ReadModel", body: "none", inner: "", opens: "", fills: "max_field"
277
+ member word: "percentile", context: "ReadModel", body: "none", inner: "", opens: "", fills: "percentile_field", calls: "percentile_impl"
278
+ member word: "any", context: "ReadModel", body: "none", inner: "", opens: "", fills: "any_field"
279
+ member word: "all", context: "ReadModel", body: "none", inner: "", opens: "", fills: "all_field"
228
280
  member word: "where", context: "ReadModel", body: "none", inner: "", opens: "", fills: "options", calls: "where_impl"
229
281
  member word: "order_by", context: "ReadModel", body: "none", inner: "", opens: "", fills: "options", calls: "order_by_impl"
230
282
  member word: "authorize", context: "ReadModel", body: "none", inner: "", opens: "", fills: "options", calls: "authorize_impl"
@@ -256,9 +308,23 @@ Hecks.bluebook "Bluebook" do
256
308
  member keyword: "include", context: "ReadModel", at: "", named: "as", kind: "symbol", required: "false", fills: "as"
257
309
  member keyword: "group_by", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "group_by", variadic: "true"
258
310
  member keyword: "median", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "median_field"
311
+ member keyword: "sum", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "sum_field"
312
+ member keyword: "avg", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "avg_field"
313
+ member keyword: "min", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "min_field"
314
+ member keyword: "max", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "max_field"
315
+ member keyword: "percentile", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "percentile_field"
316
+ member keyword: "percentile", context: "ReadModel", at: "", named: "at", kind: "number", required: "true", fills: "percentile_at"
317
+ member keyword: "any", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "any_field"
318
+ member keyword: "all", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "all_field"
259
319
  member keyword: "where", context: "ReadModel", at: "1", named: "", kind: "pairs", required: "true", fills: ""
320
+ # ADR 0055: which many-side `include`d aggregate (by type) this option applies to —
321
+ # only recognized here, in ReadModel context, since a plain Query has no such
322
+ # disambiguation to make (rust/parser's own query_derive::refuse_on_target keeps
323
+ # refusing it there instead).
324
+ member keyword: "where", context: "ReadModel", at: "", named: "on", kind: "constant", required: "false", fills: "target"
260
325
  member keyword: "order_by", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "field"
261
326
  member keyword: "order_by", context: "ReadModel", at: "2", named: "", kind: "symbol", required: "false", fills: "direction"
327
+ member keyword: "order_by", context: "ReadModel", at: "", named: "on", kind: "constant", required: "false", fills: "target"
262
328
  member keyword: "authorize", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "policy"
263
329
  member keyword: "authorize", context: "ReadModel", at: "", named: "tenant", kind: "symbol", required: "false", fills: "tenant"
264
330
  member keyword: "inspect_query", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "false", fills: "mode"