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
@@ -2,13 +2,8 @@ require_relative "word_gate"
2
2
  module Hecks
3
3
  module Bluebook
4
4
  module DSL
5
- # Parses a `process_manager "Name" do ... end` block into a
6
- # `ProcessManager` — its own `starts_on`/`ends_on` events, what
7
- # correlates its instances (`correlates_by`), and the `transition`-
8
- # declared state machine whose `dispatch`es (each optionally paired
9
- # with its own per-dispatch `compensates`) become its handlers. States
10
- # are derived from the transitions rather than declared separately
11
- # (S7, ADR 0025).
5
+ # Parses a `process_manager "Name" do ... end` block into a `ProcessManager`; its states
6
+ # are derived from its `transition`s (ADR 0025).
12
7
  class ProcessManagerBuilder
13
8
  GRAMMAR_CONTEXT = "ProcessManager".freeze
14
9
 
@@ -24,16 +19,9 @@ module Hecks
24
19
 
25
20
  # Records the event that begins a fresh instance of this process manager.
26
21
  #
27
- # `starts_on Transfer::TransferRequested` — bare constant
28
- # accepted (ADR 0025, S6 — "events first-class"), resolved
29
- # through `ConstShim` the same way `on_impl`/`transition_impl`
30
- # resolve an event reference — but through `Naming.
31
- # event_name_ref`, not `Naming.event_ref` (that method's own
32
- # header has the full account: `SagaInterpreter` matches
33
- # `pm.starts_on`/`pm.ends_on` against a bare `event.name`, never
34
- # a "." qualified one). A plain String still passes through
35
- # unchanged, both for `shadow_parse` and for any corpus site a
36
- # future pass hasn't migrated yet.
22
+ # `starts_on Transfer::TransferRequested`: a bare constant, stored as the bare event
23
+ # name (`Naming.event_name_ref`) because `SagaInterpreter` matches an undotted name.
24
+ # A plain String passes through unchanged.
37
25
  #
38
26
  # @param event_ref [Symbol, String, Module] the event, as a bare constant (a
39
27
  # `ScopedConstant` module `ConstShim` resolves) or quoted text
@@ -42,9 +30,7 @@ module Hecks
42
30
  @starts_on = Naming.event_name_ref(event_ref)
43
31
  end
44
32
 
45
- # Records the event this process manager expects to close out its instance on.
46
- #
47
- # `ends_on` — same reasoning as `starts_on_impl`, above.
33
+ # Records the event that closes out this process manager's instance.
48
34
  #
49
35
  # @param event_ref [Symbol, String, Module] the event, as a bare constant (a
50
36
  # `ScopedConstant` module `ConstShim` resolves) or quoted text
@@ -53,67 +39,14 @@ module Hecks
53
39
  @ends_on = Naming.event_name_ref(event_ref)
54
40
  end
55
41
 
56
- # `correlates_by` — item #13's full metaprogrammed dispatch,
57
- # slice 1 (whole-project table-unification survey): a bare,
58
- # kind-driven coerce-and-assign with nothing else, executed by
59
- # `GenericDispatch`.
60
- #
61
- # `starts_on`/`ends_on` are hand-written rather than table-driven
62
- # the same way, because ADR 0025 S6 gives each a second,
63
- # `kind: "constant"` ArgumentSeed row (`starts_on
64
- # Transfer::TransferRequested`) — `GenericDispatch::COERCE_BY_KIND`
65
- # only knows `"text"`/`"symbol"`, and `shape_for` refuses to pick a
66
- # `single_fill` shape at all once two Argument rows share a
67
- # `fills:` target (`arguments.size == 1` below), so both words are
68
- # `calls:`-routed like `transition` already is.
69
-
70
- # Records one leg of this process manager's state machine: the event that takes it, the
71
- # state(s) it applies from, and the dispatches (and optional compensation) it fires.
72
- #
73
- # One state-machine vocabulary (S7, ADR 0025 — "events and
74
- # reactions"): the same word `Lifecycle#transition` already
75
- # carries, one level over — `transition "AccountDebited" =>
76
- # "awaiting_credit", from: "requested" do ... end` replaces `on
77
- # "AccountDebited", transition: { "requested" => "awaiting_
78
- # credit" } do ... end`. Same bare rocket-pair argument shape
79
- # (not a named `transition:` kwarg wrapping a second Hash), same
80
- # `from:` — including the array form Lifecycle's own commands
81
- # could already take and a process manager's own events could
82
- # not — and the states a procedure runs on are derived from the
83
- # transitions that name them, the same way `Behaviour::Lifecycle
84
- # #states` already derives an aggregate's ; `state "x"` lines
85
- # duplicated exactly what the transition list already said,
86
- # and could drift from it (`validate!`'s own "undeclared state"
87
- # check existed only because they could).
42
+ # Records one leg of the state machine: the event that takes it, the state(s) it
43
+ # applies from, and the dispatches (with optional compensations) it fires.
88
44
  #
89
- # `starts_on`/`ends_on` are not unified into this — verified
90
- # against the real corpus rather than assumed: Settlement's own
91
- # `ends_on "TransferSettled"` names an event none of its own
92
- # transitions ever handle (`Transfer.Settle`'s own emission, a
93
- # full step downstream of the transition that dispatches it),
94
- # so "the terminal state's own event" is not a fact the
95
- # transition graph carries — deriving it would either be wrong
96
- # for this exact corpus member or need a second new word to
97
- # cover the case, which is not less vocabulary than keeping the
98
- # one that already says it correctly.
99
- #
100
- # Expands immediately, unlike `Lifecycle#transition` (which
101
- # defers to `Behaviour::Lifecycle#expand`, called at emission
102
- # time) — `ProcessManager`'s own IR constructor takes `states:`/
103
- # `handlers:` exactly as it always has, so the runtime
104
- # (`Behaviour::ProcessManager`, `SagaInterpreter`, saga
105
- # persistence/rehydration) needs no change at all: what changed
106
- # is how the declaration reaches that same shape, not the shape
107
- # a real run ever sees or persists.
108
- # Reached through `calls: "transition_impl"`. Not exercised during boot itself — checked
109
- # directly, no core/attached chapter declares a `ProcessManager` of its own — though the
110
- # (context, word) pair is still carried in `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`
111
- # unconditionally, along with every other `calls:`-routed row.
45
+ # States are derived from the transitions, not declared.
112
46
  #
113
47
  # @param mapping [Hash] one `event => target_state` pair plus a required `from:` key
114
- # naming the source state(s) (`String`, `Symbol`, or `Array<String, Symbol>`) this
115
- # transition applies from
116
- # @yield the transition's dispatch body, `instance_eval`'d against a fresh `HandlerBuilder`
48
+ # naming the source state(s): a `String`, `Symbol`, or an `Array` of them
49
+ # @yield the transition's dispatch body, `instance_eval`'d against a `HandlerBuilder`
117
50
  # @return [void]
118
51
  # @raise [Bluebook::DSL::ProcessManagerBuilder::InvalidProcessManager] if `mapping` names
119
52
  # no `from:`
@@ -121,18 +54,8 @@ module Hecks
121
54
  mapping = mapping.dup
122
55
  from = mapping.delete(:from)
123
56
 
124
- # Always required, unlike `Lifecycle#transition`'s own `from:`
125
- # — an aggregate's unconstrained transition is admitted from
126
- # any current state (`Behaviour::Lifecycle#applies_from?`
127
- # returns true for a nil `from`), a reading `SagaInterpreter#
128
- # advance_saga`'s own admission check does not share: it tests
129
- # `instance[:state] == handler.from_state` by plain equality,
130
- # nothing softer. Leaving that check unchanged (this slice's
131
- # own scope decision — see the class-level comment on why the
132
- # runtime stays untouched) means an unconstrained PM
133
- # transition would build cleanly and then match no instance
134
- # ever, silently — refused here instead, at the one point that
135
- # can still see the mistake.
57
+ # `from:` is required: the saga's admission check tests `from_state` by plain equality,
58
+ # so a transition with no `from:` would match no instance.
136
59
  if from.nil?
137
60
  raise InvalidProcessManager,
138
61
  "#{@name}'s transition #{mapping.inspect} names no from: — a process manager's own " \
@@ -144,23 +67,8 @@ module Hecks
144
67
  handler.instance_eval(&block) if block
145
68
 
146
69
  mapping.each do |event_type, target|
147
- # Bare constant accepted (ADR 0025, S6 — "events first-
148
- # class"), `transition Account::AccountDebited => "state"` —
149
- # `Naming.event_name_ref`, not the dotted `Naming.event_ref`
150
- # transform `PolicyBuilder#on_impl` uses (that method's own
151
- # header has the full account, found live wiring a real
152
- # migrated corpus site into `bin/model_check` for the first
153
- # time: `SagaInterpreter#advance_saga` matches `handler.
154
- # event_type` against a bare `event.name`, never a "."
155
- # qualified one — a policy's own cross-aggregate match
156
- # works differently, splitting the qualifier apart from the
157
- # name rather than comparing the whole string). Writing the
158
- # qualifier is still worth it (the same provenance `trigger
159
- # Account::Debit` gives a reader) — `event_name_ref` keeps
160
- # only the final segment, so `Account::AccountDebited` and a
161
- # bare `AccountDebited` store identically. A plain String
162
- # still passes through unchanged, both for `shadow_parse`
163
- # and for every corpus site this pass didn't migrate.
70
+ # `event_name_ref` keeps only the final segment: `SagaInterpreter` matches a bare
71
+ # `event.name`, so `Account::AccountDebited` and `AccountDebited` store the same.
164
72
  state_transition = StateTransition.new(target: target, from: from)
165
73
  expand(Naming.event_name_ref(event_type), state_transition, handler.dispatches).each { |row| @handlers << row }
166
74
  end
@@ -202,12 +110,7 @@ module Hecks
202
110
 
203
111
  private
204
112
 
205
- # One declared transition is several rows when `from` names more
206
- # than one source state — `Behaviour::Lifecycle#expand`'s own
207
- # comment, the identical fan-out, one level over: a
208
- # `ProcessManagerHandler` only ever carries a single `from_state`,
209
- # so a `from: [...]` transition mints one row per source, each
210
- # carrying the same dispatches.
113
+ # One row per source state, since a `ProcessManagerHandler` carries a single `from_state`.
211
114
  def expand(event_type, transition, dispatches)
212
115
  sources = transition.from.nil? ? [nil] : Array(transition.from)
213
116
 
@@ -221,15 +124,7 @@ module Hecks
221
124
  end
222
125
  end
223
126
 
224
- # Derived, not declared (S7) — every state this procedure ever
225
- # runs on is already named by some transition's own `from_state`
226
- # or `to_state`; a state nothing transitions into or out of is
227
- # not a state this procedure has, the same reading
228
- # `Behaviour::Lifecycle#states` already gives an aggregate's own
229
- # field. First-seen order, walking declaration order — `begin_
230
- # saga`'s own `pm.states.first` is what a fresh instance starts
231
- # in, so the order has to survive the derivation, not just the
232
- # membership.
127
+ # First-seen order matters: `pm.states.first` is the state a fresh instance starts in.
233
128
  def derived_states
234
129
  @handlers.flat_map { |h| [h.from_state, h.to_state] }.reject(&:empty?).uniq
235
130
  end
@@ -240,16 +135,8 @@ module Hecks
240
135
  "nothing would tie its events to one instance"
241
136
  end
242
137
 
243
- # **The field, named** — never the value object that carries it. A bare
244
- # `correlates_by :end_to_end` reads whatever the payload holds under
245
- # that key as the correlation key, and what a non-scalar key even
246
- # is stays open (the object itself? its serialised text?).
247
- # Requiring the dotted spelling —
248
- # `:"end_to_end.value"` — makes every correlates_by name a scalar
249
- # by construction, the same discipline `identified_by` already
250
- # holds a head to. This is a syntactic check, not a type check: it
251
- # does not know or care whether the field is a value object, only
252
- # that the declaration cannot leave that question open.
138
+ # Names a scalar (`:"end_to_end.value"`), never a whole field or value object.
139
+ # A syntactic check: the dotted spelling leaves no question about the key's type.
253
140
  unless @correlates_by.to_s.include?(".")
254
141
  raise InvalidProcessManager, "#{@name} correlates_by #{@correlates_by.inspect}, which names a whole " \
255
142
  "field rather than one of its scalars — say which one, e.g. " \
@@ -269,12 +156,8 @@ module Hecks
269
156
  refuse_ambiguous_legs!
270
157
  end
271
158
 
272
- # C10.3 — a leg is selected by (event, current state), so two
273
- # legs answering the same event from the same state would leave
274
- # the runtime to pick by declaration order, silently. Refused
275
- # here, where the declaration can still be read whole. (`from:
276
- # [...]` fan-out counts: `transition E => "a", from: ["x", "y"]`
277
- # and `transition E => "b", from: "y"` collide on ("E", "y").)
159
+ # A leg is selected by (event, current state), so two legs on the same pair would
160
+ # be picked by declaration order; `from: [...]` fan-out counts.
278
161
  def refuse_ambiguous_legs!
279
162
  return if MetaValidator.shadow_parsing? # frozen era text is history
280
163
 
@@ -292,10 +175,7 @@ module Hecks
292
175
  end
293
176
  end
294
177
 
295
- # The body of one `transition ... do ... end` block — collects the
296
- # `dispatch` calls (each optionally opening its own `compensates`
297
- # via the nested `DispatchBuilder`) that fire when this transition
298
- # is taken.
178
+ # The body of one `transition ... do ... end` block; collects its `dispatch` calls.
299
179
  class HandlerBuilder
300
180
  GRAMMAR_CONTEXT = "Handler".freeze
301
181
 
@@ -309,34 +189,12 @@ module Hecks
309
189
  # Records one command this transition dispatches, and, if given a block, the
310
190
  # compensation that reverses it.
311
191
  #
312
- # The command itself (ADR 0025, "events and reactions" — command
313
- # references become first-class), same shape and same reasons
314
- # as `PolicyBuilder#trigger`'s own header — bare constant live,
315
- # quoted text only under shadow-parsing (S0a's bridge; frozen
316
- # era text still writes `dispatch "Banking::Account.Debit"`).
317
- #
318
- # Reached through `calls: "dispatch_impl"`.
319
- #
320
- # An optional block opens `compensates` on this dispatch
321
- # specifically — per-dispatch saga compensation, replacing a
322
- # hand-written list at the saga's own `on :refused` leg. Real,
323
- # live bug this closes: `examples/banking/bluebook/transfers_
324
- # and_payments.bluebook`'s own `Settlement` saga wrote a
325
- # compensating reversal by hand that depended on an event only
326
- # fired if someone dispatched it manually — "the reversal was
327
- # written and never armed" (that file's own comment). The
328
- # runtime now tracks which legs actually completed
329
- # (`SagaInterpreter`'s own `completed_compensations`) and
330
- # compensates only those, newest first, instead of trusting an
331
- # author's static list to be complete and correctly ordered.
192
+ # The command is a bare constant; quoted text is accepted only under shadow-parsing.
332
193
  #
333
- # @param command_ref [Symbol, String, Module] the command, as a bare constant (a
334
- # `ScopedConstant` module `ConstShim` resolves) or, under shadow-parsing, quoted text
335
- # @param with [Hash{Symbol => Object}, nil] a projection onto the command's own
336
- # arguments, the same `key => value` shape a policy's own `trigger ..., with:` takes;
337
- # `nil` forwards the triggering context verbatim
338
- # @yield the dispatch's own `compensates` body, `instance_eval`'d against a
339
- # `DispatchBuilder`
194
+ # @param command_ref [Symbol, String, Module] the command, as a bare constant
195
+ # @param with [Hash{Symbol => Object}, nil] a projection onto the command's arguments,
196
+ # as in a policy's `trigger ..., with:`; `nil` forwards the triggering context
197
+ # @yield the `compensates` body, run only if this leg completed
340
198
  # @return [Bluebook::DispatchSpec] the dispatch just recorded
341
199
  # @raise [Bluebook::DSL::ProcessManagerBuilder::InvalidProcessManager] if `command_ref`
342
200
  # is quoted text outside shadow-parsing
@@ -356,11 +214,8 @@ module Hecks
356
214
  if block
357
215
  builder = DispatchBuilder.new
358
216
  builder.instance_eval(&block)
359
- # `instance_variable_get`, not a public `compensates_spec`
360
- # reader — a public one would be a method the grammar
361
- # never declares, exactly what `spec/syntax_conformance_
362
- # spec.rb`'s "answers only words the language declares"
363
- # check exists to catch.
217
+ # `instance_variable_get`, not a public reader: a reader would be a method the
218
+ # grammar never declares (syntax_conformance_spec).
364
219
  spec.compensates = builder.instance_variable_get(:@compensates_spec)
365
220
  end
366
221
 
@@ -368,16 +223,8 @@ module Hecks
368
223
  spec
369
224
  end
370
225
 
371
- # The nested scope `dispatch ... do ... end` opens — one word
372
- # only (`compensates`), the compensating half of the dispatch it
373
- # sits inside. Its own `compensates_impl` builds a second
374
- # `DispatchSpec`, shape-identical to `HandlerBuilder#dispatch_
375
- # impl`'s own — a compensation takes the exact same two
376
- # arguments (a bare command constant, an optional `with:`)
377
- # because it resolves through the identical scope (current
378
- # event payload, opening event memory, correlation binding)
379
- # any saga dispatch already does
380
- # (`SagaInterpreter#dispatch_args`).
226
+ # The nested scope `dispatch ... do ... end` opens; its one word, `compensates`,
227
+ # takes the same arguments as `dispatch` and resolves in the same saga scope.
381
228
  class DispatchBuilder
382
229
  GRAMMAR_CONTEXT = "Dispatch".freeze
383
230
 
@@ -29,17 +29,8 @@ module Hecks
29
29
 
30
30
  # Declares a query parameter that names another aggregate's identity.
31
31
  #
32
- # A query parameter naming another aggregate's own identity
33
- # (Card.Active's own `Board`, filtering to one board's cards) —
34
- # just a plain attribute typed as a reference,
35
- # `AttributeCollector#attribute_impl` already handling a Reference
36
- # exactly like any other. No "acts on itself" case to
37
- # distinguish here the way a command's own reference_to has —
38
- # a query has no root of its own to act on, only parameters.
39
- #
40
- # Answers the `reference_to` word through the table's `calls:`
41
- # column — item #13's full metaprogrammed dispatch (slice 4b).
42
- # Bootstrap-reachable, in `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`.
32
+ # A plain attribute typed as a reference; a query has no root of its own to act on.
33
+ # Reached through `calls: "reference_to_impl"`.
43
34
  #
44
35
  # @param type [Module, Symbol, String] the referenced aggregate, written as a bare
45
36
  # constant
@@ -86,31 +77,17 @@ module Hecks
86
77
  def self.build(name, owner_attributes: [], &block)
87
78
  builder = new(name)
88
79
  builder.instance_eval(&block) if block
89
- # `send`, not a public call — this isn't a bluebook DSL word (no
90
- # author ever writes `derive_from_owner!` inside a query block),
91
- # just internal wiring between this class method and the instance
92
- # it just built. Kept private below so syntax_conformance_spec's
93
- # own "every word QueryBuilder answers is declared" check doesn't
94
- # mistake it for one.
80
+ # `send`: `derive_from_owner!` is internal wiring, not a DSL word, so it stays private
81
+ # (syntax_conformance_spec).
95
82
  builder.send(:derive_from_owner!, owner_attributes, block) if block
96
83
  builder.build
97
84
  end
98
85
 
99
86
  private
100
87
 
101
- # A block parameter names one of the owner's (the aggregate or entity
102
- # this query is declared on) own already-declared attributes —
103
- # `query "ForDecision" do |decision| where decision: :decision end`
104
- # on Submission, whose own `attribute :decision, DecisionRef` already
105
- # says what `decision` is. Restating `attribute :decision, DecisionRef`
106
- # a second time inside the query was pure duplication; this derives
107
- # the same type from the owner instead. Only fills in a name the block
108
- # body did not already declare explicitly (checked after instance_eval
109
- # runs, so an existing bluebook still spelling it out both ways keeps
110
- # working unchanged — this only removes the need to, never refuses
111
- # the choice to). A block parameter matching nothing on the owner is
112
- # left alone; MetaValidator's own unresolved-attribute check names it,
113
- # the same way a typo in a hand-written `attribute` call already does.
88
+ # Fills in a block parameter that names an owner attribute (`query "X" do |decision|`)
89
+ # with the owner's type, unless the body declared it. Unmatched names are left for
90
+ # MetaValidator's unresolved-attribute check.
114
91
  def derive_from_owner!(owner_attributes, block)
115
92
  block.parameters.each do |kind, param_name|
116
93
  next unless %i[req opt].include?(kind)
@@ -119,22 +96,14 @@ module Hecks
119
96
  owner_attr = owner_attributes.find { |a| a.name == param_name }
120
97
  next unless owner_attr
121
98
 
122
- # `Attribute.new` directly, not the public `attribute(...)` DSL
123
- # entry — `owner_attr.type` is already spelled (a demodulised
124
- # String, `Attribute#spell`'s own doing), not a bareword the
125
- # bluebook author typed, so it must not run through
126
- # `AttributeCollector#attribute`'s quoted-type refusal (ADR
127
- # 0025, "Attributes") — that refusal exists for DSL source
128
- # text, not for a type already resolved elsewhere and copied.
99
+ # `Attribute.new` directly: `owner_attr.type` is already spelled, so it must not go
100
+ # through the quoted-type refusal meant for DSL source text.
129
101
  attributes << Attribute.new(name: param_name, type: owner_attr.type, optional: owner_attr.optional?)
130
102
  end
131
103
  end
132
104
 
133
- # `cursor` parses, round-trips through the IR, and is read by nothing —
134
- # no interpreter (Memory, Sqlite, Postgres) ever applies it. Refusing
135
- # it here, rather than deleting the word, keeps the declared syntax
136
- # honest (the language still knows the shape) while refusing to let a
137
- # bluebook author believe cursor-based pagination actually happens.
105
+ # `cursor` parses and round-trips but no interpreter applies it; refuse it so an author
106
+ # does not believe cursor pagination happens.
138
107
  def seal_cursor
139
108
  return unless @cursor
140
109