hecks 2.8.0 → 3.0.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 (886) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +50 -7
  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 +32 -100
  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 +10 -32
  23. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
  24. data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
  25. data/lib/hecks/adapters/driven/postgres.rb +149 -136
  26. data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
  27. data/lib/hecks/adapters/driven/prism.rb +48 -38
  28. data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
  29. data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
  30. data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
  31. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
  32. data/lib/hecks/adapters/driven/sqlite.rb +128 -65
  33. data/lib/hecks/adapters/driven/tenant_provisioner.rb +76 -62
  34. data/lib/hecks/adapters/driven.rb +5 -36
  35. data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
  36. data/lib/hecks/behaviors/dsl.rb +7 -25
  37. data/lib/hecks/behaviors/expectations.rb +32 -142
  38. data/lib/hecks/behaviors/ir.rb +7 -20
  39. data/lib/hecks/behaviors/rspec.rb +6 -17
  40. data/lib/hecks/behaviors/runner.rb +10 -34
  41. data/lib/hecks/behaviors.rb +4 -8
  42. data/lib/hecks/bench/cli.rb +62 -0
  43. data/lib/hecks/bench/environment.rb +71 -0
  44. data/lib/hecks/bench/postgres_probe.rb +30 -0
  45. data/lib/hecks/bench/report.rb +76 -0
  46. data/lib/hecks/bench/ruby_runner.rb +93 -0
  47. data/lib/hecks/bench/run.rb +55 -0
  48. data/lib/hecks/bench/rust_runner.rb +101 -0
  49. data/lib/hecks/bench/stats.rb +46 -0
  50. data/lib/hecks/bench/suite.rb +98 -0
  51. data/lib/hecks/bench/workload.rb +89 -0
  52. data/lib/hecks/bench.rb +17 -0
  53. data/lib/hecks/bluebook/aggregate.rb +9 -75
  54. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
  55. data/lib/hecks/bluebook/assembly/build.rb +4 -15
  56. data/lib/hecks/bluebook/assembly/contract.rb +15 -136
  57. data/lib/hecks/bluebook/assembly/contracts.rb +56 -174
  58. data/lib/hecks/bluebook/assembly/marks.rb +31 -223
  59. data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
  60. data/lib/hecks/bluebook/assembly.rb +6 -45
  61. data/lib/hecks/bluebook/attribute.rb +12 -61
  62. data/lib/hecks/bluebook/behaviour/aggregate.rb +39 -39
  63. data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
  64. data/lib/hecks/bluebook/behaviour/chapter.rb +14 -42
  65. data/lib/hecks/bluebook/behaviour/command.rb +14 -66
  66. data/lib/hecks/bluebook/behaviour/domain_port.rb +11 -20
  67. data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
  68. data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
  69. data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
  70. data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
  71. data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
  72. data/lib/hecks/bluebook/behaviour/read_model.rb +25 -31
  73. data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
  74. data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
  75. data/lib/hecks/bluebook/capabilities.rb +17 -49
  76. data/lib/hecks/bluebook/chapter.rb +16 -50
  77. data/lib/hecks/bluebook/command.rb +23 -81
  78. data/lib/hecks/bluebook/domain_port.rb +49 -67
  79. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
  80. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
  81. data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
  82. data/lib/hecks/bluebook/dsl/binding_proxy.rb +16 -69
  83. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +96 -708
  84. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +63 -169
  85. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +3 -1
  86. data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
  87. data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
  88. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +42 -89
  89. data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
  90. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
  91. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +148 -197
  92. data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
  93. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
  94. data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
  95. data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
  96. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
  97. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
  98. data/lib/hecks/bluebook/dsl/query_builder.rb +38 -43
  99. data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
  100. data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
  101. data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
  102. data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
  103. data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
  104. data/lib/hecks/bluebook/dsl/world_builder.rb +46 -111
  105. data/lib/hecks/bluebook/entity.rb +13 -71
  106. data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
  107. data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
  108. data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
  109. data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
  110. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
  111. data/lib/hecks/bluebook/expression/resolver.rb +39 -661
  112. data/lib/hecks/bluebook/hexagon.rb +18 -33
  113. data/lib/hecks/bluebook/lifecycle.rb +5 -16
  114. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
  115. data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
  116. data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
  117. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
  118. data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
  119. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -176
  120. data/lib/hecks/bluebook/meta_validator/shapes.rb +53 -267
  121. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -306
  122. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
  123. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
  124. data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
  125. data/lib/hecks/bluebook/meta_validator.rb +87 -352
  126. data/lib/hecks/bluebook/model_check/client_profile.rb +6 -21
  127. data/lib/hecks/bluebook/model_check.rb +122 -596
  128. data/lib/hecks/bluebook/pattern_subset.rb +49 -69
  129. data/lib/hecks/bluebook/process_manager.rb +13 -83
  130. data/lib/hecks/bluebook/project_loader.rb +3 -39
  131. data/lib/hecks/bluebook/project_register.rb +12 -60
  132. data/lib/hecks/bluebook/query.rb +27 -51
  133. data/lib/hecks/bluebook/read_model.rb +57 -81
  134. data/lib/hecks/bluebook/reference.rb +7 -41
  135. data/lib/hecks/bluebook/smoke_test.rb +9 -99
  136. data/lib/hecks/bluebook/synthesizer.rb +13 -62
  137. data/lib/hecks/bluebook/translation.rb +26 -62
  138. data/lib/hecks/bluebook/value_object.rb +11 -36
  139. data/lib/hecks/bluebook.rb +5 -22
  140. data/lib/hecks/cache_dir.rb +4 -23
  141. data/lib/hecks/canonical_json.rb +30 -0
  142. data/lib/hecks/chapters.rb +102 -0
  143. data/lib/hecks/cli/behaviors.rb +61 -0
  144. data/lib/hecks/cli/canonicalise.rb +25 -0
  145. data/lib/hecks/cli/check_engine_agreement.rb +32 -0
  146. data/lib/hecks/cli/check_era.rb +88 -0
  147. data/lib/hecks/cli/console.rb +66 -0
  148. data/lib/hecks/cli/deploy_template_diff.rb +40 -0
  149. data/lib/hecks/cli/doc_coverage.rb +32 -0
  150. data/lib/hecks/cli/document.rb +5 -23
  151. data/lib/hecks/cli/expression_projection.rb +41 -0
  152. data/lib/hecks/cli/follow.rb +88 -0
  153. data/lib/hecks/cli/history.rb +44 -0
  154. data/lib/hecks/cli/ir.rb +4 -6
  155. data/lib/hecks/cli/mcp.rb +5 -6
  156. data/lib/hecks/cli/model_check.rb +24 -88
  157. data/lib/hecks/cli/pattern_cases.rb +47 -0
  158. data/lib/hecks/cli/present.rb +39 -0
  159. data/lib/hecks/cli/project_cli.rb +223 -64
  160. data/lib/hecks/cli/project_diagrams.rb +4 -10
  161. data/lib/hecks/cli/project_glossary.rb +44 -0
  162. data/lib/hecks/cli/reference.rb +46 -0
  163. data/lib/hecks/cli/refresh_projections.rb +44 -0
  164. data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +150 -0
  165. data/lib/hecks/cli/release.rb +70 -0
  166. data/lib/hecks/cli/release_gem.rb +59 -0
  167. data/lib/hecks/cli/rspec_io_parallel_files.rb +137 -0
  168. data/lib/hecks/cli/rspec_shard_files.rb +66 -0
  169. data/lib/hecks/cli/run.rb +15 -61
  170. data/lib/hecks/cli/seed_semantics_corpus.rb +71 -0
  171. data/lib/hecks/cli/serve_query_ir_mcp.rb +30 -0
  172. data/lib/hecks/cli/shape.rb +70 -0
  173. data/lib/hecks/cli/smoke_http.rb +230 -0
  174. data/lib/hecks/cli/smoke_test.rb +7 -19
  175. data/lib/hecks/cli/spec_example.rb +27 -0
  176. data/lib/hecks/cli/statements.rb +32 -0
  177. data/lib/hecks/cli/stores.rb +4 -6
  178. data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
  179. data/lib/hecks/cli.rb +216 -73
  180. data/lib/hecks/codemod.rb +324 -0
  181. data/lib/hecks/construct.rb +8 -34
  182. data/lib/hecks/corpus.rb +423 -0
  183. data/lib/hecks/deploy/bluebook/deploy.bluebook +617 -158
  184. data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -11
  185. data/lib/hecks/deploy/oidc.json +82 -2
  186. data/lib/hecks/doc/reference.rb +351 -0
  187. data/lib/hecks/doors/cli_door.rb +196 -0
  188. data/lib/hecks/doors/cli_runner.rb +297 -0
  189. data/lib/hecks/{facade → doors}/command_request.rb +14 -34
  190. data/lib/hecks/doors/handle.rb +206 -0
  191. data/lib/hecks/doors/json_door.rb +132 -0
  192. data/lib/hecks/doors/launcher_options.rb +129 -0
  193. data/lib/hecks/{cli → doors}/mcp_door.rb +25 -120
  194. data/lib/hecks/doors/mcp_door_scope.rb +97 -0
  195. data/lib/hecks/doors/ruby_door/aggregate_door.rb +162 -0
  196. data/lib/hecks/doors/ruby_door/chapter.rb +72 -0
  197. data/lib/hecks/doors/ruby_door.rb +77 -0
  198. data/lib/hecks/doors.rb +61 -0
  199. data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
  200. data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
  201. data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
  202. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
  203. data/lib/hecks/embryonaut_bluebook.rb +5 -72
  204. data/lib/hecks/engine_agreement.rb +156 -0
  205. data/lib/hecks/facade.rb +23 -51
  206. data/lib/hecks/forms/app.rb +21 -76
  207. data/lib/hecks/forms/banking_presentation.rb +50 -0
  208. data/lib/hecks/forms/command_form_renderer.rb +10 -29
  209. data/lib/hecks/forms/field_renderer.rb +17 -156
  210. data/lib/hecks/forms/field_shape.rb +31 -222
  211. data/lib/hecks/forms/html.rb +12 -47
  212. data/lib/hecks/forms/index_renderer.rb +1 -4
  213. data/lib/hecks/forms/page.rb +3 -9
  214. data/lib/hecks/forms/params.rb +14 -60
  215. data/lib/hecks/forms/port_argument.rb +2 -19
  216. data/lib/hecks/forms/query_form_renderer.rb +4 -79
  217. data/lib/hecks/forms/record_renderer.rb +8 -75
  218. data/lib/hecks/forms/record_table.rb +7 -50
  219. data/lib/hecks/forms/reference_options.rb +3 -30
  220. data/lib/hecks/forms/value_object_shape.rb +8 -35
  221. data/lib/hecks/forms.rb +5 -33
  222. data/lib/hecks/fqn.rb +5 -12
  223. data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
  224. data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
  225. data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
  226. data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
  227. data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
  228. data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
  229. data/lib/hecks/framework.rb +11 -80
  230. data/lib/hecks/freezer.rb +5 -39
  231. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +393 -0
  232. data/lib/hecks/fuzzing/combination_miner.rb +86 -0
  233. data/lib/hecks/fuzzing/concurrent_dispatch.rb +214 -0
  234. data/lib/hecks/fuzzing/coverage_campaign.rb +143 -0
  235. data/lib/hecks/fuzzing/differential.rb +156 -0
  236. data/lib/hecks/fuzzing/domain_generator.rb +615 -0
  237. data/lib/hecks/fuzzing/era_boundary.rb +71 -0
  238. data/lib/hecks/fuzzing/form_census.rb +136 -0
  239. data/lib/hecks/fuzzing/generated_domain_check.rb +93 -0
  240. data/lib/hecks/fuzzing/invalid_value_generator.rb +64 -0
  241. data/lib/hecks/fuzzing/isolated_boot.rb +301 -0
  242. data/lib/hecks/fuzzing/nondeterministic.rb +51 -0
  243. data/lib/hecks/fuzzing/outside_world.rb +45 -0
  244. data/lib/hecks/fuzzing/persistence_parity.rb +102 -0
  245. data/lib/hecks/fuzzing/properties/corrections.rb +88 -0
  246. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +314 -0
  247. data/lib/hecks/fuzzing/properties/guards.rb +190 -0
  248. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +300 -0
  249. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +93 -0
  250. data/lib/hecks/fuzzing/properties/outbox.rb +89 -0
  251. data/lib/hecks/fuzzing/properties/querying.rb +175 -0
  252. data/lib/hecks/fuzzing/properties.rb +162 -0
  253. data/lib/hecks/fuzzing/qa_settings.rb +123 -0
  254. data/lib/hecks/fuzzing/replay.rb +505 -0
  255. data/lib/hecks/fuzzing/rotation_priority.rb +48 -0
  256. data/lib/hecks/fuzzing/rust_gap_manifest.rb +108 -0
  257. data/lib/hecks/fuzzing/self_consistency.rb +339 -0
  258. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +385 -0
  259. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +132 -0
  260. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +95 -0
  261. data/lib/hecks/fuzzing/sequence_generator/picker.rb +77 -0
  262. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +109 -0
  263. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +237 -0
  264. data/lib/hecks/fuzzing/sequence_generator.rb +189 -0
  265. data/lib/hecks/fuzzing/shrinker.rb +166 -0
  266. data/lib/hecks/fuzzing/structural_skips.rb +33 -0
  267. data/lib/hecks/fuzzing/sweep_depth.rb +43 -0
  268. data/lib/hecks/fuzzing/target_capabilities.rb +163 -0
  269. data/lib/hecks/fuzzing/value_generator.rb +216 -0
  270. data/lib/hecks/fuzzing.rb +23 -0
  271. data/lib/hecks/grammar/evolve.rb +336 -0
  272. data/lib/hecks/grammar/expression.bluebook +15 -40
  273. data/lib/hecks/grammar/translation.bluebook +3 -6
  274. data/lib/hecks/grammar.rb +16 -41
  275. data/lib/hecks/hecks/adapters/codebase/codemods.rb +45 -0
  276. data/lib/hecks/hecks/adapters/codebase/conformance.rb +71 -0
  277. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +202 -0
  278. data/lib/hecks/hecks/adapters/codebase/gem_registry.rb +80 -0
  279. data/lib/hecks/hecks/adapters/codebase/kernel_tables.rb +54 -0
  280. data/lib/hecks/hecks/adapters/codebase/language.rb +240 -0
  281. data/lib/hecks/hecks/adapters/codebase/npm_registry.rb +102 -0
  282. data/lib/hecks/hecks/adapters/codebase/publishing.rb +142 -0
  283. data/lib/hecks/hecks/adapters/codebase/regeneration.rb +67 -0
  284. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +90 -0
  285. data/lib/hecks/hecks/adapters/codebase/ruby_child.rb +83 -0
  286. data/lib/hecks/hecks/adapters/codebase/secret_vault.rb +36 -0
  287. data/lib/hecks/hecks/adapters/codebase/source_tree.adapter +7 -0
  288. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +189 -0
  289. data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +71 -0
  290. data/lib/hecks/hecks/adapters/codebase/style.rb +171 -0
  291. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +55 -0
  292. data/lib/hecks/hecks/adapters/codebase/test_suite.rb +165 -0
  293. data/lib/hecks/hecks/adapters/codebase/tree.rb +111 -0
  294. data/lib/hecks/hecks/adapters/console_capture.rb +79 -0
  295. data/lib/hecks/hecks/adapters/deploy_toolchain.adapter +7 -0
  296. data/lib/hecks/hecks/adapters/deploy_toolchain.rb +108 -0
  297. data/lib/hecks/hecks/adapters/git.adapter +7 -0
  298. data/lib/hecks/hecks/adapters/git.rb +102 -0
  299. data/lib/hecks/hecks/adapters/host_http.adapter +7 -0
  300. data/lib/hecks/hecks/adapters/host_http.rb +65 -0
  301. data/lib/hecks/hecks/adapters/in_process_boot.adapter +7 -0
  302. data/lib/hecks/hecks/adapters/in_process_boot.rb +197 -0
  303. data/lib/hecks/hecks/adapters/in_process_operations.rb +202 -0
  304. data/lib/hecks/hecks/adapters/journal_store/changes.rb +143 -0
  305. data/lib/hecks/hecks/adapters/journal_store/compaction.rb +145 -0
  306. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +132 -0
  307. data/lib/hecks/hecks/adapters/journal_store/examination.rb +135 -0
  308. data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +163 -0
  309. data/lib/hecks/hecks/adapters/journal_store/readings.rb +187 -0
  310. data/lib/hecks/hecks/adapters/journal_store.adapter +7 -0
  311. data/lib/hecks/hecks/adapters/journal_store.rb +64 -0
  312. data/lib/hecks/hecks/adapters/local_files.adapter +7 -0
  313. data/lib/hecks/hecks/adapters/local_files.rb +46 -0
  314. data/lib/hecks/hecks/adapters/pg_admin.adapter +7 -0
  315. data/lib/hecks/hecks/adapters/pg_admin.rb +245 -0
  316. data/lib/hecks/hecks/adapters/process_pool.adapter +7 -0
  317. data/lib/hecks/hecks/adapters/process_pool.rb +119 -0
  318. data/lib/hecks/hecks/adapters/rust_toolchain.adapter +7 -0
  319. data/lib/hecks/hecks/adapters/rust_toolchain.rb +179 -0
  320. data/lib/hecks/hecks/adapters/rust_workspace.rb +150 -0
  321. data/lib/hecks/hecks/adapters/shell.adapter +7 -0
  322. data/lib/hecks/hecks/adapters/shell.rb +49 -0
  323. data/lib/hecks/hecks/adapters/terminal.adapter +7 -0
  324. data/lib/hecks/hecks/adapters/terminal.rb +74 -0
  325. data/lib/hecks/hecks/codebase.behaviors +172 -0
  326. data/lib/hecks/hecks/codebase.bluebook +2453 -0
  327. data/lib/hecks/hecks/context_map.hecksagon +13 -0
  328. data/lib/hecks/hecks/custodian.behaviors +179 -0
  329. data/lib/hecks/hecks/custodian.bluebook +1847 -0
  330. data/lib/hecks/hecks/deploy.behaviors +74 -0
  331. data/lib/hecks/hecks/deploy.world +12 -0
  332. data/lib/hecks/hecks/environments/memory.world +10 -0
  333. data/lib/hecks/hecks/governance.world +7 -0
  334. data/lib/hecks/hecks/hecks.behaviors +62 -0
  335. data/lib/hecks/hecks/hecks.bluebook +124 -0
  336. data/lib/hecks/hecks/hecks.hecksagon +390 -0
  337. data/lib/hecks/hecks/hecks.world +42 -0
  338. data/lib/hecks/ir.rb +14 -83
  339. data/lib/hecks/kernel_capabilities.rb +194 -0
  340. data/lib/hecks/language/adapter.bluebook +2 -7
  341. data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
  342. data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
  343. data/lib/hecks/language/bluebook/bluebook.bluebook +26 -83
  344. data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
  345. data/lib/hecks/language/bluebook/command.bluebook +27 -144
  346. data/lib/hecks/language/bluebook/entity.bluebook +24 -97
  347. data/lib/hecks/language/bluebook/policy.bluebook +16 -67
  348. data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
  349. data/lib/hecks/language/bluebook/projection.bluebook +126 -60
  350. data/lib/hecks/language/bluebook/query.bluebook +19 -43
  351. data/lib/hecks/language/bluebook/shape.bluebook +23 -73
  352. data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
  353. data/lib/hecks/language/bluebook/vocabulary.bluebook +83 -198
  354. data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
  355. data/lib/hecks/language/hecksagon/domain_port.bluebook +14 -19
  356. data/lib/hecks/language/hecksagon/hecksagon.bluebook +26 -25
  357. data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
  358. data/lib/hecks/language/oidc.json +35 -0
  359. data/lib/hecks/language/port.bluebook +4 -17
  360. data/lib/hecks/language/translation/translation.bluebook +3 -9
  361. data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
  362. data/lib/hecks/language/world/wiring.bluebook +1 -3
  363. data/lib/hecks/language/world/world.bluebook +5 -7
  364. data/lib/hecks/literal.rb +8 -50
  365. data/lib/hecks/mcp_stdio_guard.rb +4 -41
  366. data/lib/hecks/naming.rb +29 -137
  367. data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
  368. data/lib/hecks/persistence_legacy_fixture.rb +113 -0
  369. data/lib/hecks/ports/access_control.rb +7 -23
  370. data/lib/hecks/ports/agent/answers.rb +5 -23
  371. data/lib/hecks/ports/agent.rb +47 -172
  372. data/lib/hecks/ports/authentication.rb +12 -39
  373. data/lib/hecks/ports/authorization.rb +16 -43
  374. data/lib/hecks/ports/clock.rb +5 -45
  375. data/lib/hecks/ports/extraction.rb +7 -12
  376. data/lib/hecks/ports/identity_assignment.rb +8 -29
  377. data/lib/hecks/ports/identity_generation.rb +6 -29
  378. data/lib/hecks/ports/identity_resolution.rb +2 -10
  379. data/lib/hecks/ports/key_vault.rb +9 -45
  380. data/lib/hecks/ports/persistence/append_only.rb +61 -64
  381. data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
  382. data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
  383. data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
  384. data/lib/hecks/ports/persistence/plugin.rb +13 -42
  385. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +44 -144
  386. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
  387. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +20 -85
  388. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +6 -25
  389. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +18 -24
  390. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
  391. data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
  392. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
  393. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
  394. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
  395. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
  396. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
  397. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
  398. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +19 -76
  399. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
  400. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
  401. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
  402. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
  403. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
  404. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +43 -127
  405. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
  406. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +131 -555
  407. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
  408. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +227 -0
  409. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
  410. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
  411. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
  412. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
  413. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
  414. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +50 -47
  415. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -124
  416. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
  417. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
  418. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
  419. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
  420. data/lib/hecks/ports/persistence/plugins/era/translation.rb +1 -0
  421. data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
  422. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
  423. data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
  424. data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
  425. data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
  426. data/lib/hecks/ports/persistence/state_codec.rb +47 -108
  427. data/lib/hecks/ports/persistence.rb +7 -14
  428. data/lib/hecks/ports/projection.rb +42 -84
  429. data/lib/hecks/ports/query/in_memory.rb +10 -58
  430. data/lib/hecks/ports/query/ordering.rb +11 -32
  431. data/lib/hecks/ports/query.rb +14 -37
  432. data/lib/hecks/ports.rb +2 -8
  433. data/lib/hecks/projection_files.rb +285 -0
  434. data/lib/hecks/projections/bootstrap_table.rb +12 -44
  435. data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
  436. data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
  437. data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
  438. data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
  439. data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
  440. data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
  441. data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
  442. data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
  443. data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
  444. data/lib/hecks/projections/deploy/fargate.rb +40 -207
  445. data/lib/hecks/projections/deploy/lambda.rb +191 -708
  446. data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
  447. data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
  448. data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
  449. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
  450. data/lib/hecks/projections/deploy/preview/script.rb +2 -14
  451. data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
  452. data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
  453. data/lib/hecks/projections/deploy/preview/template.rb +3 -59
  454. data/lib/hecks/projections/deploy/preview.rb +2 -67
  455. data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +1 -1
  456. data/lib/hecks/projections/deploy/scripts/expected-era.header +1 -1
  457. data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +3 -3
  458. data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
  459. data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +1 -1
  460. data/lib/hecks/projections/deploy/scripts.rb +4 -57
  461. data/lib/hecks/projections/deploy/shared.rb +48 -147
  462. data/lib/hecks/projections/deploy/smoke.rb +4 -61
  463. data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
  464. data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
  465. data/lib/hecks/projections/deploy/template_diff.rb +5 -57
  466. data/lib/hecks/projections/diagrams.rb +22 -584
  467. data/lib/hecks/projections/glossary/html.rb +14 -130
  468. data/lib/hecks/projections/glossary/markdown.rb +8 -69
  469. data/lib/hecks/projections/glossary/mermaid.rb +9 -66
  470. data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
  471. data/lib/hecks/projections/glossary/sentences.rb +14 -159
  472. data/lib/hecks/projections/glossary.rb +30 -222
  473. data/lib/hecks/projections/ir.rb +3 -10
  474. data/lib/hecks/projections/model/deviations.rb +16 -43
  475. data/lib/hecks/projections/model.rb +12 -51
  476. data/lib/hecks/projections/oidc.rb +12 -56
  477. data/lib/hecks/projections/parser_table.rb +13 -32
  478. data/lib/hecks/projections/reference.rb +4 -18
  479. data/lib/hecks/projections/rust_vocabulary.rb +13 -251
  480. data/lib/hecks/projections/shape.rb +3 -29
  481. data/lib/hecks/projections/statements.rb +7 -86
  482. data/lib/hecks/projections/vocabulary.rb +6 -22
  483. data/lib/hecks/projections.rb +2 -16
  484. data/lib/hecks/projector/cli_projector.rb +154 -400
  485. data/lib/hecks/projector/docs_projector.rb +10 -201
  486. data/lib/hecks/projector/exporter.rb +42 -134
  487. data/lib/hecks/projector/ir_projector.rb +2 -9
  488. data/lib/hecks/projector/narrate_projector.rb +15 -189
  489. data/lib/hecks/projector/target.rb +13 -76
  490. data/lib/hecks/projector.rb +30 -121
  491. data/lib/hecks/quality_control/adapters/agent.adapter +7 -0
  492. data/lib/hecks/quality_control/adapters/agent.rb +58 -0
  493. data/lib/hecks/quality_control/adapters/angle_tools.adapter +7 -0
  494. data/lib/hecks/quality_control/adapters/angle_tools.rb +15 -0
  495. data/lib/hecks/quality_control/adapters/clearance_recorder.rb +36 -0
  496. data/lib/hecks/quality_control/adapters/clearance_tools.adapter +7 -0
  497. data/lib/hecks/quality_control/adapters/clearance_tools.rb +17 -0
  498. data/lib/hecks/quality_control/adapters/git_pr.adapter +7 -0
  499. data/lib/hecks/quality_control/adapters/git_pr.rb +226 -0
  500. data/lib/hecks/quality_control/adapters/github_checks.adapter +9 -0
  501. data/lib/hecks/quality_control/adapters/github_checks.rb +83 -0
  502. data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +56 -0
  503. data/lib/hecks/quality_control/adapters/github_issues.adapter +7 -0
  504. data/lib/hecks/quality_control/adapters/github_issues.rb +49 -0
  505. data/lib/hecks/quality_control/adapters/qa_tool.rb +59 -0
  506. data/lib/hecks/quality_control/adapters/sweep_tools.adapter +7 -0
  507. data/lib/hecks/quality_control/adapters/sweep_tools.rb +51 -0
  508. data/lib/hecks/quality_control/adapters/target_tools.adapter +7 -0
  509. data/lib/hecks/quality_control/adapters/target_tools.rb +43 -0
  510. data/lib/hecks/quality_control/cli/child.rb +45 -0
  511. data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +45 -0
  512. data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +248 -0
  513. data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +163 -0
  514. data/lib/hecks/quality_control/cli/qa_generated_domains.rb +450 -0
  515. data/lib/hecks/quality_control/cli/qa_log_bug.rb +195 -0
  516. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +220 -0
  517. data/lib/hecks/quality_control/cli/qa_open_pr.rb +305 -0
  518. data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +154 -0
  519. data/lib/hecks/quality_control/cli/qa_postgres_role.rb +159 -0
  520. data/lib/hecks/quality_control/cli/qa_pr_check.rb +232 -0
  521. data/lib/hecks/quality_control/cli/qa_seed_angles.rb +142 -0
  522. data/lib/hecks/quality_control/cli/qa_seed_targets.rb +69 -0
  523. data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +280 -0
  524. data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +329 -0
  525. data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +92 -0
  526. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +117 -0
  527. data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +175 -0
  528. data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +60 -0
  529. data/lib/hecks/quality_control/cli/qa_sweep.rb +611 -0
  530. data/lib/hecks/quality_control/cli/qa_tick.rb +274 -0
  531. data/lib/hecks/quality_control/quality_control.bluebook +2224 -0
  532. data/lib/hecks/quality_control/quality_control.hecksagon +13 -0
  533. data/lib/hecks/quality_control/quality_control.ports.hecksagon +54 -0
  534. data/lib/hecks/query_ir.rb +346 -0
  535. data/lib/hecks/query_ir_mcp.rb +198 -0
  536. data/lib/hecks/query_specification/common/comparators.rb +5 -26
  537. data/lib/hecks/query_specification/common/comparison.rb +35 -143
  538. data/lib/hecks/query_specification/common/dsl.rb +8 -24
  539. data/lib/hecks/query_specification/common/null_policy.rb +20 -70
  540. data/lib/hecks/query_specification/common/options.rb +2 -6
  541. data/lib/hecks/query_specification/common/where_clause.rb +2 -10
  542. data/lib/hecks/query_specification/field_path.rb +37 -77
  543. data/lib/hecks/query_specification/hop_path.rb +12 -76
  544. data/lib/hecks/release/gem_pin.rb +2 -26
  545. data/lib/hecks/release/runner/ci_publisher.rb +5 -8
  546. data/lib/hecks/release/runner/clean_tree.rb +42 -0
  547. data/lib/hecks/release/runner/commands.rb +2 -4
  548. data/lib/hecks/release/runner/console.rb +6 -0
  549. data/lib/hecks/release/runner/gem_publisher.rb +15 -9
  550. data/lib/hecks/release/runner/npm_publisher.rb +9 -53
  551. data/lib/hecks/release/runner/preflight.rb +29 -20
  552. data/lib/hecks/release/runner/published.rb +8 -26
  553. data/lib/hecks/release/runner/tagger.rb +31 -23
  554. data/lib/hecks/release/runner.rb +60 -38
  555. data/lib/hecks/rendering.rb +4 -26
  556. data/lib/hecks/router/namespace_installer.rb +15 -39
  557. data/lib/hecks/router.rb +4 -8
  558. data/lib/hecks/runtime/adapter_lookup.rb +124 -0
  559. data/lib/hecks/runtime/aggregate_lock.rb +8 -33
  560. data/lib/hecks/runtime/boot_gates.rb +3 -18
  561. data/lib/hecks/runtime/caller.rb +19 -59
  562. data/lib/hecks/runtime/capability_graph.rb +5 -21
  563. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
  564. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +27 -160
  565. data/lib/hecks/runtime/command_interpreter.rb +124 -306
  566. data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
  567. data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
  568. data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
  569. data/lib/hecks/runtime/command_rules/emission.rb +8 -21
  570. data/lib/hecks/runtime/command_rules/references.rb +23 -202
  571. data/lib/hecks/runtime/dependency_planning.rb +50 -104
  572. data/lib/hecks/runtime/dispatcher.rb +134 -243
  573. data/lib/hecks/runtime/entity_element.rb +40 -462
  574. data/lib/hecks/runtime/entity_interpreter.rb +64 -219
  575. data/lib/hecks/runtime/errors.rb +32 -115
  576. data/lib/hecks/runtime/event.rb +3 -25
  577. data/lib/hecks/runtime/identity.rb +18 -154
  578. data/lib/hecks/runtime/instance.rb +18 -150
  579. data/lib/hecks/runtime/interpreting.rb +14 -70
  580. data/lib/hecks/runtime/invocation.rb +28 -164
  581. data/lib/hecks/runtime/loader.rb +109 -194
  582. data/lib/hecks/runtime/outbox.rb +39 -262
  583. data/lib/hecks/runtime/policy_interpreter.rb +43 -202
  584. data/lib/hecks/runtime/port_operation_interpreter.rb +28 -97
  585. data/lib/hecks/runtime/query_interpreter.rb +122 -187
  586. data/lib/hecks/runtime/reaction_invocation.rb +36 -138
  587. data/lib/hecks/runtime/reaction_outcome.rb +89 -0
  588. data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
  589. data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
  590. data/lib/hecks/runtime/reference_hop.rb +8 -81
  591. data/lib/hecks/runtime/refusal_wording.rb +28 -87
  592. data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
  593. data/lib/hecks/runtime/registry/verification.rb +213 -227
  594. data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
  595. data/lib/hecks/runtime/registry.rb +156 -247
  596. data/lib/hecks/runtime/remote_dispatcher.rb +68 -154
  597. data/lib/hecks/runtime/routing.rb +4 -15
  598. data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
  599. data/lib/hecks/runtime/saga_interpreter.rb +79 -263
  600. data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
  601. data/lib/hecks/runtime/tenant_check.rb +6 -68
  602. data/lib/hecks/runtime/tenant_scope.rb +3 -28
  603. data/lib/hecks/runtime/value/admission.rb +16 -67
  604. data/lib/hecks/runtime/value/coercion.rb +162 -760
  605. data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
  606. data/lib/hecks/runtime/value/field_checks.rb +172 -0
  607. data/lib/hecks/runtime/value.rb +15 -84
  608. data/lib/hecks/runtime.rb +35 -69
  609. data/lib/hecks/rust_build/conformance.rb +158 -0
  610. data/lib/hecks/rust_build/conformance_fuzz.rb +71 -0
  611. data/lib/hecks/rust_build/coverage.rb +218 -0
  612. data/lib/hecks/rust_build/native_build.rb +124 -0
  613. data/lib/hecks/rust_build/project_rust/root_mod.rb +120 -0
  614. data/lib/hecks/rust_build/project_rust.rb +332 -0
  615. data/lib/hecks/rust_build/wasm.rb +105 -0
  616. data/lib/hecks/rust_build/wasm_browser.rb +113 -0
  617. data/lib/hecks/rust_build.rb +144 -0
  618. data/lib/hecks/storehouse.rb +155 -582
  619. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +10 -34
  620. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
  621. data/lib/hecks/three_zero/forms.yml +127 -0
  622. data/lib/hecks/three_zero.rb +12 -0
  623. data/lib/hecks/tools/argument_gate_matrix.rb +316 -0
  624. data/lib/hecks/tools/comment_style.rb +1070 -0
  625. data/lib/hecks/tools/corpus_report.rb +87 -0
  626. data/lib/hecks/tools/deploy_recipe.rb +255 -0
  627. data/lib/hecks/tools/deploy_recipe_lint.rb +282 -0
  628. data/lib/hecks/tools/drop_implicit_append_fields.rb +95 -0
  629. data/lib/hecks/tools/era_projection_backfill.rb +94 -0
  630. data/lib/hecks/tools/era_reattest.rb +146 -0
  631. data/lib/hecks/tools/evolve_run.rb +189 -0
  632. data/lib/hecks/tools/fuzz_sweep.rb +373 -0
  633. data/lib/hecks/tools/heki_compaction.rb +100 -0
  634. data/lib/hecks/tools/hoist_local_givens.rb +246 -0
  635. data/lib/hecks/tools/journal_compaction.rb +89 -0
  636. data/lib/hecks/tools/oidc_manifests.rb +70 -0
  637. data/lib/hecks/tools/query_ir_run.rb +81 -0
  638. data/lib/hecks/tools/regeneration_run.rb +166 -0
  639. data/lib/hecks/tools/rust_comment_style.rb +642 -0
  640. data/lib/hecks/tools/sequence_script.rb +62 -0
  641. data/lib/hecks/tools/tail_merge.rb +117 -0
  642. data/lib/hecks/tools/tenant_provisioning.rb +142 -0
  643. data/lib/hecks/tools/translation_audit.rb +208 -0
  644. data/lib/hecks/tools/translation_scaffold.rb +131 -0
  645. data/lib/hecks/tools.rb +86 -0
  646. data/lib/hecks/vendoring/git_environment.rb +2 -8
  647. data/lib/hecks/vendoring/git_source.rb +4 -10
  648. data/lib/hecks/vendoring.rb +7 -46
  649. data/lib/hecks/version.rb +3 -14
  650. data/lib/hecks.rb +52 -90
  651. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
  652. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
  653. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
  654. data/qa/settings.yml +66 -0
  655. data/rust/.cargo/config.toml +6 -0
  656. data/rust/.gitignore +2 -0
  657. data/rust/Cargo.lock +54 -0
  658. data/rust/Cargo.toml +61 -0
  659. data/rust/build/.cargo/config.toml +3 -0
  660. data/rust/build/.gitignore +1 -0
  661. data/rust/build/Cargo.lock +7 -0
  662. data/rust/build/Cargo.toml +19 -0
  663. data/rust/build/src/build_artifact.rs +47 -0
  664. data/rust/build/src/cargo_sync.rs +248 -0
  665. data/rust/build/src/json.rs +421 -0
  666. data/rust/build/src/lineage_pass.rs +285 -0
  667. data/rust/build/src/main.rs +51 -0
  668. data/rust/build/src/optional_pass.rs +150 -0
  669. data/rust/build/src/pipeline.rs +264 -0
  670. data/rust/build/src/reserved_names.rs +76 -0
  671. data/rust/build/src/resolve.rs +124 -0
  672. data/rust/build/src/root.rs +25 -0
  673. data/rust/build/src/sidecars.rs +73 -0
  674. data/rust/build/src/subprocess.rs +51 -0
  675. data/rust/build/src/tmp.rs +31 -0
  676. data/rust/codegen/.cargo/config.toml +3 -0
  677. data/rust/codegen/.gitignore +1 -0
  678. data/rust/codegen/Cargo.lock +7 -0
  679. data/rust/codegen/Cargo.toml +20 -0
  680. data/rust/codegen/src/attr.rs +32 -0
  681. data/rust/codegen/src/bridging.rs +481 -0
  682. data/rust/codegen/src/commands.rs +1226 -0
  683. data/rust/codegen/src/constraints.rs +109 -0
  684. data/rust/codegen/src/dependency_planning.rs +209 -0
  685. data/rust/codegen/src/domain_generator.rs +1288 -0
  686. data/rust/codegen/src/exemplar.rs +230 -0
  687. data/rust/codegen/src/expr_emitter.rs +87 -0
  688. data/rust/codegen/src/fielded.rs +192 -0
  689. data/rust/codegen/src/hecks_naming.rs +33 -0
  690. data/rust/codegen/src/json.rs +335 -0
  691. data/rust/codegen/src/json_codec.rs +697 -0
  692. data/rust/codegen/src/literal.rs +207 -0
  693. data/rust/codegen/src/main.rs +290 -0
  694. data/rust/codegen/src/manifest.rs +227 -0
  695. data/rust/codegen/src/mutations.rs +784 -0
  696. data/rust/codegen/src/naming.rs +286 -0
  697. data/rust/codegen/src/ports.rs +208 -0
  698. data/rust/codegen/src/prelude.rs +116 -0
  699. data/rust/codegen/src/queries.rs +786 -0
  700. data/rust/codegen/src/reactions.rs +532 -0
  701. data/rust/codegen/src/read_models.rs +697 -0
  702. data/rust/codegen/src/reference_specs.rs +40 -0
  703. data/rust/codegen/src/registry.rs +966 -0
  704. data/rust/codegen/src/reserved_names.rs +76 -0
  705. data/rust/codegen/src/shared.rs +93 -0
  706. data/rust/codegen/src/skip_reason.rs +25 -0
  707. data/rust/codegen/src/types.rs +362 -0
  708. data/rust/host/.cargo/config.toml +3 -0
  709. data/rust/host/.gitignore +1 -0
  710. data/rust/host/Cargo.lock +4297 -0
  711. data/rust/host/Cargo.toml +61 -0
  712. data/rust/host/HECKS_RELEASE +1 -0
  713. data/rust/host/rds-ca-bundle.pem +2736 -0
  714. data/rust/host/src/api.rs +1596 -0
  715. data/rust/host/src/approval.rs +652 -0
  716. data/rust/host/src/auth.rs +1287 -0
  717. data/rust/host/src/bin/expr_harness.rs +46 -0
  718. data/rust/host/src/bin/lineage_harness.rs +119 -0
  719. data/rust/host/src/bin/mint_harness.rs +135 -0
  720. data/rust/host/src/checkout.rs +265 -0
  721. data/rust/host/src/dispatch.rs +1443 -0
  722. data/rust/host/src/expr_json.rs +1117 -0
  723. data/rust/host/src/field_hints.rs +52 -0
  724. data/rust/host/src/ir.rs +733 -0
  725. data/rust/host/src/journal.rs +874 -0
  726. data/rust/host/src/lambda_client.rs +378 -0
  727. data/rust/host/src/log.rs +147 -0
  728. data/rust/host/src/main.rs +474 -0
  729. data/rust/host/src/mint.rs +1865 -0
  730. data/rust/host/src/payments/keystore.rs +330 -0
  731. data/rust/host/src/payments/tests.rs +1400 -0
  732. data/rust/host/src/payments.rs +767 -0
  733. data/rust/host/src/presentation.rs +698 -0
  734. data/rust/host/src/presentation_write.rs +1431 -0
  735. data/rust/host/src/query_step.rs +149 -0
  736. data/rust/host/src/rate_limit.rs +904 -0
  737. data/rust/host/src/reference_transform.rs +241 -0
  738. data/rust/host/src/reference_validate.rs +338 -0
  739. data/rust/host/src/resend.rs +296 -0
  740. data/rust/host/src/secrets.rs +106 -0
  741. data/rust/host/src/server.rs +663 -0
  742. data/rust/host/src/storage_shape.rs +175 -0
  743. data/rust/host/src/test_pg.rs +40 -0
  744. data/rust/host/src/ui_schema.rs +1351 -0
  745. data/rust/host/src/wasm_runner.rs +191 -0
  746. data/rust/host/src/web/newsletter/cooldown.rs +126 -0
  747. data/rust/host/src/web/newsletter/tests.rs +104 -0
  748. data/rust/host/src/web/newsletter.rs +310 -0
  749. data/rust/host/src/web/newsletter_send.rs +357 -0
  750. data/rust/host/src/web/registrations.rs +1505 -0
  751. data/rust/host/src/web.rs +2937 -0
  752. data/rust/lsp/.gitignore +1 -0
  753. data/rust/lsp/Cargo.lock +7 -0
  754. data/rust/lsp/Cargo.toml +16 -0
  755. data/rust/lsp/README.md +133 -0
  756. data/rust/lsp/src/diagnostics.rs +165 -0
  757. data/rust/lsp/src/json.rs +385 -0
  758. data/rust/lsp/src/main.rs +399 -0
  759. data/rust/lsp/src/outline.rs +177 -0
  760. data/rust/lsp/src/rpc.rs +67 -0
  761. data/rust/parser/.cargo/config.toml +5 -0
  762. data/rust/parser/.gitignore +1 -0
  763. data/rust/parser/Cargo.lock +7 -0
  764. data/rust/parser/Cargo.toml +21 -0
  765. data/rust/parser/src/build/closed_sets.rs +27 -0
  766. data/rust/parser/src/build/identity.rs +276 -0
  767. data/rust/parser/src/build/mod.rs +12 -0
  768. data/rust/parser/src/build/naming.rs +141 -0
  769. data/rust/parser/src/build/pattern_subset.rs +161 -0
  770. data/rust/parser/src/build/query_derive.rs +72 -0
  771. data/rust/parser/src/build/query_inference.rs +269 -0
  772. data/rust/parser/src/build/query_options.rs +100 -0
  773. data/rust/parser/src/build/read_model.rs +94 -0
  774. data/rust/parser/src/build/references.rs +32 -0
  775. data/rust/parser/src/canonical.rs +114 -0
  776. data/rust/parser/src/diag.rs +55 -0
  777. data/rust/parser/src/emit.rs +953 -0
  778. data/rust/parser/src/expr/ast_json.rs +147 -0
  779. data/rust/parser/src/expr/evaluator.rs +81 -0
  780. data/rust/parser/src/expr/mod.rs +84 -0
  781. data/rust/parser/src/expr/resolver.rs +497 -0
  782. data/rust/parser/src/ir.rs +387 -0
  783. data/rust/parser/src/keywords.rs +585 -0
  784. data/rust/parser/src/lex.rs +662 -0
  785. data/rust/parser/src/main.rs +252 -0
  786. data/rust/parser/src/parse/aggregate.rs +612 -0
  787. data/rust/parser/src/parse/chapter.rs +517 -0
  788. data/rust/parser/src/parse/command.rs +637 -0
  789. data/rust/parser/src/parse/domain_port.rs +127 -0
  790. data/rust/parser/src/parse/entity.rs +527 -0
  791. data/rust/parser/src/parse/file.rs +67 -0
  792. data/rust/parser/src/parse/hecksagon.rs +231 -0
  793. data/rust/parser/src/parse/lifecycle.rs +162 -0
  794. data/rust/parser/src/parse/mod.rs +1262 -0
  795. data/rust/parser/src/parse/policy.rs +87 -0
  796. data/rust/parser/src/parse/process_manager.rs +305 -0
  797. data/rust/parser/src/parse/query.rs +100 -0
  798. data/rust/parser/src/parse/read_model.rs +214 -0
  799. data/rust/parser/src/parse/value_object.rs +250 -0
  800. data/rust/parser/src/ruby_value.rs +422 -0
  801. data/rust/project/bridging.rb +257 -0
  802. data/rust/project/commands.rb +877 -0
  803. data/rust/project/constraints.rb +86 -0
  804. data/rust/project/dependency_planning.rb +178 -0
  805. data/rust/project/domain_generator.rb +980 -0
  806. data/rust/project/exemplar.rb +148 -0
  807. data/rust/project/expr_emitter.rb +72 -0
  808. data/rust/project/fielded.rb +141 -0
  809. data/rust/project/json_codec.rb +641 -0
  810. data/rust/project/mutations.rb +721 -0
  811. data/rust/project/naming.rb +205 -0
  812. data/rust/project/ports.rb +65 -0
  813. data/rust/project/queries.rb +493 -0
  814. data/rust/project/reactions.rb +317 -0
  815. data/rust/project/read_models.rb +690 -0
  816. data/rust/project/reference_specs.rb +27 -0
  817. data/rust/project/registry.rb +396 -0
  818. data/rust/project/skip_reason.rb +29 -0
  819. data/rust/project/types.rb +225 -0
  820. data/rust/project/write_if_changed.rb +83 -0
  821. data/rust/project.rb +30 -0
  822. data/rust/project_rust_pipeline.rb +383 -0
  823. data/rust/src/exemplar/commands.rs +279 -0
  824. data/rust/src/exemplar/constraints.rs +18 -0
  825. data/rust/src/exemplar/fielded.rs +280 -0
  826. data/rust/src/exemplar/json.rs +277 -0
  827. data/rust/src/exemplar/mod.rs +17 -0
  828. data/rust/src/exemplar/mutations.rs +80 -0
  829. data/rust/src/exemplar/queries.rs +33 -0
  830. data/rust/src/exemplar/reactions.rs +88 -0
  831. data/rust/src/exemplar/read_models.rs +48 -0
  832. data/rust/src/exemplar/registry.rs +166 -0
  833. data/rust/src/exemplar/types.rs +44 -0
  834. data/rust/src/kernel/attribute_shapes/composite.rs +88 -0
  835. data/rust/src/kernel/attribute_shapes/list.rs +18 -0
  836. data/rust/src/kernel/attribute_shapes/mod.rs +44 -0
  837. data/rust/src/kernel/attribute_shapes/optional.rs +9 -0
  838. data/rust/src/kernel/attribute_shapes/scalar.rs +39 -0
  839. data/rust/src/kernel/cli.rs +585 -0
  840. data/rust/src/kernel/dispatch.rs +1090 -0
  841. data/rust/src/kernel/expr.rs +458 -0
  842. data/rust/src/kernel/expression_operators/arithmetic.rs +128 -0
  843. data/rust/src/kernel/expression_operators/comparison.rs +48 -0
  844. data/rust/src/kernel/expression_operators/enumeration.rs +232 -0
  845. data/rust/src/kernel/expression_operators/logical.rs +13 -0
  846. data/rust/src/kernel/expression_operators/membership.rs +18 -0
  847. data/rust/src/kernel/expression_operators/mod.rs +68 -0
  848. data/rust/src/kernel/expression_operators/pattern_match.rs +73 -0
  849. data/rust/src/kernel/expression_operators/positional.rs +126 -0
  850. data/rust/src/kernel/expression_operators/presence.rs +101 -0
  851. data/rust/src/kernel/expression_operators/sign_test.rs +16 -0
  852. data/rust/src/kernel/expression_operators/sized.rs +35 -0
  853. data/rust/src/kernel/expression_operators/text.rs +79 -0
  854. data/rust/src/kernel/expression_operators/to_string.rs +18 -0
  855. data/rust/src/kernel/json.rs +779 -0
  856. data/rust/src/kernel/mod.rs +133 -0
  857. data/rust/src/kernel/named_query.rs +219 -0
  858. data/rust/src/kernel/orchestrate.rs +1810 -0
  859. data/rust/src/kernel/pattern.rs +307 -0
  860. data/rust/src/kernel/query_comparators.rs +206 -0
  861. data/rust/src/kernel/query_ordering.rs +103 -0
  862. data/rust/src/kernel/read_model.rs +914 -0
  863. data/rust/src/kernel/reference_lookup.rs +149 -0
  864. data/rust/src/kernel/repository.rs +468 -0
  865. data/rust/src/kernel/routing.rs +612 -0
  866. data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +118 -0
  867. data/rust/src/kernel/vocab/entity_dispatch_order.rs +114 -0
  868. data/rust/src/kernel/vocab/field_hint.rs +70 -0
  869. data/rust/src/kernel/vocab/mod.rs +20 -0
  870. data/rust/src/kernel/vocab/query_comparator.rs +65 -0
  871. data/rust/src/kernel/vocab/refusal_template.rs +1592 -0
  872. data/rust/src/lib.rs +8 -0
  873. data/rust/src/main.rs +16 -0
  874. data/rust/web/.gitignore +1 -0
  875. data/rust/web/Cargo.lock +119 -0
  876. data/rust/web/Cargo.toml +18 -0
  877. data/rust/web/src/lib.rs +8 -0
  878. metadata +478 -12
  879. data/lib/hecks/facade/cli_door.rb +0 -178
  880. data/lib/hecks/facade/cli_runner.rb +0 -271
  881. data/lib/hecks/facade/handle.rb +0 -293
  882. data/lib/hecks/facade/json_door.rb +0 -247
  883. data/lib/hecks/facade/surface/aggregate_door.rb +0 -222
  884. data/lib/hecks/facade/surface/chapter.rb +0 -116
  885. data/lib/hecks/facade/surface.rb +0 -61
  886. data/lib/hecks/mcp_door_scope.rb +0 -176
@@ -1,50 +1,37 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # **What a lifecycle does**. Its declared half is a field, a starting
5
- # state and a transition list. Everything here reads that — which
6
- # states exist, which transition a command takes, and how one
7
- # declared transition expands into the several rows the emission
8
- # carries when `from` names more than one source state.
4
+ # Readings over a lifecycle's field, starting state and transition list.
9
5
  module Lifecycle
10
- # Lists every state this lifecycle can be in.
6
+ # Every state this lifecycle can be in.
11
7
  #
12
- # @return [Array<String>] every state this lifecycle can be in — the
13
- # default plus each declared transition's own target, deduplicated
8
+ # @return [Array<String>] the default plus each transition's target, deduplicated
14
9
  def states
15
10
  ([default] + transitions.map { |_command, t| t.target }).uniq
16
11
  end
17
12
 
18
- # Finds every transition a command declares.
13
+ # Every transition a command declares.
19
14
  #
20
- # @param command [String, Symbol] the command name to find declared
21
- # transitions for
22
- # @return [Array<Bluebook::StateTransition>] every transition declared
23
- # for `command`
15
+ # @param command [String, Symbol]
16
+ # @return [Array<Bluebook::StateTransition>]
24
17
  def transitions_for(command)
25
18
  transitions.select { |name, _| name == command.to_s }.map { |_, t| t }
26
19
  end
27
20
 
28
- # Finds the state a command moves the record to.
21
+ # The state a command moves the record to.
29
22
  #
30
- # @param command [String, Symbol] the command name to find the target
31
- # state for
32
- # @param current_state [String, Symbol, nil] the record's current
33
- # state, to pick the one declared transition that admits it; `nil`
34
- # to skip that check and take the first declared transition
35
- # @return [String, nil] the state `command` moves the record to, or
36
- # `nil` when `command` declares no transition at all
37
- # @raise [Runtime::WiringError] if `command` declares transitions but
38
- # none of them admits `current_state`
23
+ # @param command [String, Symbol]
24
+ # @param current_state [String, Symbol, nil] picks the transition that admits it;
25
+ # `nil` takes the first declared transition
26
+ # @return [String, nil] `nil` when `command` declares no transition
27
+ # @raise [Runtime::WiringError] if transitions are declared but none admits `current_state`
39
28
  def target_for(command, current_state = nil)
40
29
  match_transition(command, current_state)&.target
41
30
  end
42
31
 
43
32
  private
44
33
 
45
- # One declared transition is several rows when `from` names more
46
- # than one source state — the emission carries them flat, so the
47
- # fan-out happens here rather than in whatever reads it.
34
+ # A transition whose `from` names several states becomes one row per source state.
48
35
  def expand(command, transition)
49
36
  sources = transition.from.nil? ? [nil] : Array(transition.from)
50
37
 
@@ -58,20 +45,8 @@ module Hecks
58
45
  return nil if matches.empty?
59
46
  return matches.first unless current_state
60
47
 
61
- # Not `|| matches.first` — that would silently hand back an
62
- # arbitrary declared transition for `command` whenever none of
63
- # them actually admitted `current_state`, picking a `target`
64
- # that command dispatch would in fact refuse (that
65
- # refusal is `CommandRules::Admissibility#admissible_transition`'s
66
- # own job, which raises `LifecycleRefused` for exactly this
67
- # case rather than guessing — this module has no state subject
68
- # to build that refusal message from, only the two bare
69
- # values callers passed in). Zero production callers reach
70
- # this branch today (both real dispatch paths that check a
71
- # transition go through `admissible_transition`, not
72
- # `target_for`/`match_transition`), so this raise is a
73
- # backstop, not a live behaviour change — same shape as
74
- # `CommandRules::Arithmetic#sign_of`'s own fix.
48
+ # No `|| matches.first`: that would return a target command dispatch refuses.
49
+ # `CommandRules::Admissibility#admissible_transition` owns the real refusal.
75
50
  matches.find { |t| applies_from?(t, current_state) } ||
76
51
  raise(Runtime::WiringError,
77
52
  "no transition for #{command.inspect} admits state #{current_state.inspect} " \
@@ -1,53 +1,36 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # **What a policy does**. Its declared half is four plain fields; these
5
- # are the readings taken off them.
4
+ # Readings over a policy's declared fields.
6
5
  module Policy
7
- # The bluebook's name for this construct, asked the same way of a class
8
- # that has crossed over and of an IR object that has not. Collapses into
9
- # Construct when this one crosses.
6
+ # The bluebook's name for this construct.
10
7
  #
11
- # @return [String] this policy's declared name
8
+ # @return [String]
12
9
  def hecks_name = @name
13
10
 
14
11
  # The domain-and-aggregate prefix of the triggering event's name.
15
12
  #
16
- # @return [String, nil] the part of `on_event` before its first `.`
17
- # (the `"Domain::Aggregate"` prefix), or `nil` when `on_event`
18
- # carries no dot
13
+ # @return [String, nil] the part of `on_event` before its first `.`, or `nil` if none
19
14
  def event_qualifier = Naming.qualifier(@on_event)
20
15
 
21
- # The bare name of the triggering event, without its domain/aggregate
22
- # prefix.
16
+ # The triggering event's bare name, without its prefix.
23
17
  #
24
- # @return [String] the part of `on_event` after its first `.` (the
25
- # bare event name), or the whole string when it carries no dot
18
+ # @return [String]
26
19
  def event_name = Naming.unqualified(@on_event)
27
20
 
28
- # Whether this policy fans out — `for_each` names a query, and a
29
- # non-empty one turns a single reaction into one dispatch per row
30
- # the query answers. Read by the interpreter that runs the fan-out
31
- # and by the property that checks it dispatched once per row.
21
+ # Whether `for_each` names a query, turning one reaction into a dispatch per row.
32
22
  #
33
- # @return [Boolean] whether `for_each` names a query
23
+ # @return [Boolean]
34
24
  def fans_out? = !@for_each.to_s.empty?
35
25
 
36
- # Whether this policy is guarded — a non-empty `where` decides
37
- # whether the policy fires at all, read against the triggering
38
- # event's own payload.
26
+ # Whether a non-empty `where` decides if the policy fires at all.
39
27
  #
40
- # @return [Boolean] whether `where` is declared and non-empty
28
+ # @return [Boolean]
41
29
  def guarded? = !@where.to_s.empty?
42
30
 
43
- # The structured form of `where`, derived once — the same tree
44
- # `AstJson.emit_predicate` spells for every rule row, memoized
45
- # here because a policy is consulted once per event, not once per
46
- # boot. Nil when there is no `where`, exactly as the wire carries
47
- # it.
31
+ # The structured form of `where`, memoized because a policy is consulted once per event.
48
32
  #
49
- # @return [Hash, nil] the JSON-shaped boolean AST for `where`, or
50
- # `nil` when this policy is not guarded
33
+ # @return [Hash, nil] `nil` when the policy is not guarded
51
34
  def where_ast
52
35
  if defined?(@where_ast)
53
36
  @where_ast
@@ -56,39 +39,27 @@ module Hecks
56
39
  end
57
40
  end
58
41
 
59
- # The rule-shaped reading of the guard, for `Evaluator.call_rule`
60
- # — a policy's `where` has no description (nothing refuses with
61
- # it; an unmet where is a silent skip).
42
+ # The guard as a rule for `Evaluator.call_rule`; it has no description because an
43
+ # unmet `where` is a silent skip.
62
44
  #
63
- # @return [Bluebook::Given] the guard as a rule, with no description
64
- # and its `ast` already resolved via `where_ast`
45
+ # @return [Bluebook::Given]
65
46
  def where_rule = @where_rule ||= Given.new(description: nil, canonical: @where, ast: where_ast)
66
47
 
67
- # The fan-out query's route, split the way the runtime runs it:
68
- # `[query_domain, aggregate_name, query_name]`. The query runs
69
- # against the triggering event's own domain unless `for_each`
70
- # names one ("Domain::Aggregate.query"). Deliberately independent
71
- # of `across`/`target_domain`, which name where `trigger` fires,
72
- # not where the fan-out's own query runs.
48
+ # The fan-out query's route, split the way the runtime runs it.
73
49
  #
74
- # @param default_domain [String, Symbol] the triggering event's own
75
- # domain, used when `for_each` names no domain of its own
76
- # @return [Array(String, String, String)] `[domain, aggregate_name,
77
- # query_name]` the fan-out query resolves against
50
+ # The query runs in the triggering event's domain unless `for_each` names one
51
+ # ("Domain::Aggregate.query"); it is independent of `across`/`target_domain`.
52
+ #
53
+ # @param default_domain [String, Symbol] the triggering event's domain
54
+ # @return [Array(String, String, String)] `[domain, aggregate_name, query_name]`
78
55
  def for_each_route(default_domain)
79
56
  path, query_name = @for_each.to_s.split(".", 2)
80
57
  domain, aggregate = path.to_s.include?("::") ? path.split("::", 2) : [default_domain.to_s, path]
81
58
  [domain, aggregate, query_name]
82
59
  end
83
60
 
84
- # The argument name a fan-out dispatch mints each matched row's id
85
- # under is not minted here — it depends on the target command's own
86
- # declared shape (a target command declared on the very aggregate it
87
- # self-references, such as `Account.Freeze`, is addressed by its own
88
- # identity field's name, not a synthetic foreign key), not on the
89
- # aggregate name alone, so it lives on
90
- # `Behaviour::Command#addressing_key_for`, asked of the resolved
91
- # target command by `PolicyInterpreter#addressing_key_for`.
61
+ # The argument name for each fan-out row's id is not minted here: it depends on the
62
+ # target command's declared shape, so it lives on `Behaviour::Command#addressing_key_for`.
92
63
  end
93
64
  end
94
65
  end
@@ -1,96 +1,69 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # **What a process manager does**. Its declared half is the trigger,
5
- # the states and the handlers; the compensation half — `saga` — is
6
- # derived from the handler that answers a refusal, not declared.
4
+ # Readings over a process manager's trigger, states and handlers.
5
+ # Its `saga` is derived from the handler that answers a refusal, not declared.
7
6
  module ProcessManager
8
7
  # The bluebook's name for this construct.
9
8
  #
10
- # @return [String, nil] the process manager's declared name, or `nil` before it
11
- # is set
9
+ # @return [String, nil]
12
10
  def hecks_name = @name
13
11
 
14
- # The leg that answers — selected by (event, current state), C10.3
15
- # (docs/semantics/bluebook-semantics.md). Two legs may answer the
16
- # same event from different states; which one runs is decided by
17
- # the state the instance is in, never by declaration order. With
18
- # no `state` the reading is declarative — "does any leg answer this
19
- # event, and what is it" — for callers that ask about the
20
- # procedure rather than an instance (`saga`, the outbox's consumer
21
- # selection). Build refuses two legs on one (event, state) pair
22
- # (`ProcessManagerBuilder#validate!`), so a stated lookup is
23
- # unambiguous by construction.
12
+ # The leg that answers an event from a state (C10.3, docs/semantics/bluebook-semantics.md).
24
13
  #
25
- # @param event [String, Symbol] the triggering event's name
26
- # @param state [String, Symbol, nil] the instance's current state; `nil` asks
27
- # declaratively, ignoring state
28
- # @return [Bluebook::ProcessManagerHandler, nil] the matching handler row, or `nil`
29
- # if no declared leg answers this (event, state) pair
14
+ # State, never declaration order, picks between legs; build refuses two legs on one
15
+ # (event, state) pair. With no `state` the lookup is declarative: does any leg answer.
16
+ #
17
+ # @param event [String, Symbol]
18
+ # @param state [String, Symbol, nil] the instance's current state; `nil` ignores state
19
+ # @return [Bluebook::ProcessManagerHandler, nil]
30
20
  def handler_for(event, state = nil)
31
21
  @handlers.find { |h| h.event_type == event.to_s && (state.nil? || h.from_state == state.to_s) }
32
22
  end
33
23
 
34
- # Finds every declared leg for an event, regardless of source state.
24
+ # Every declared leg for an event, regardless of source state.
35
25
  #
36
- # @param event [String, Symbol] the triggering event's name
37
- # @return [Array<Bluebook::ProcessManagerHandler>] every handler row declared for
38
- # `event`; `[]` if none is declared
26
+ # @param event [String, Symbol]
27
+ # @return [Array<Bluebook::ProcessManagerHandler>]
39
28
  def handlers_for(event) = @handlers.select { |h| h.event_type == event.to_s }
40
29
 
41
- # Says whether any declared leg answers an event.
30
+ # Whether any declared leg answers an event.
42
31
  #
43
- # @param event [String, Symbol] the triggering event's name
44
- # @return [Boolean] whether any handler row is declared for `event`
32
+ # @param event [String, Symbol]
33
+ # @return [Boolean]
45
34
  def handles?(event) = @handlers.any? { |h| h.event_type == event.to_s }
46
35
 
47
- # Whether a state is one this procedure declares — asked of a value
48
- # a real run left a saga instance holding (its live or rehydrated
49
- # state), the way `Lifecycle#states` is asked of an aggregate's
50
- # resting field. A rehydrated instance in a state no handler could
51
- # have reached is corruption the durable round-trip introduced.
36
+ # Whether a state is one this procedure declares. A rehydrated instance in an
37
+ # undeclared state is corruption from the durable round-trip.
52
38
  #
53
- # @param state [String, Symbol] the state to check
54
- # @return [Boolean] whether `state` is one of this procedure's declared states
39
+ # @param state [String, Symbol]
40
+ # @return [Boolean]
55
41
  def declares_state?(state) = @states.map(&:to_s).include?(state.to_s)
56
42
 
57
- # Names the payload field a triggering event's instances are correlated by.
43
+ # The payload field a triggering event's instances are correlated by.
58
44
  #
59
- # @return [Symbol] the head of `correlates_by` — the part before the first `.`
45
+ # @return [Symbol] the part of `correlates_by` before the first `.`
60
46
  def correlation_head = @correlates_by.to_s.split(".").first.to_sym
61
47
 
62
- # The compensation half of a procedure, read off the handler that
63
- # answers `REFUSED`.
64
- #
65
- # nil for a procedure with no answer to a refusal, which is a legitimate
66
- # thing to be — a hiring pipeline cannot un-interview anybody.
48
+ # The compensation half, read off the handler that answers `REFUSED`.
67
49
  #
68
- # @return [Bluebook::Saga, nil] the derived saga, or `nil` if no handler answers
69
- # `REFUSED`
50
+ # @return [Bluebook::Saga, nil] `nil` when no handler answers a refusal, which is
51
+ # legitimate: a hiring pipeline cannot un-interview anybody
70
52
  def saga
71
53
  leg = handler_for(Bluebook::ProcessManager::REFUSED)
72
54
  return nil unless leg
73
55
 
74
- # `compensations` — a static preview, declaration order, not
75
- # one instance's own runtime history (which legs a given
76
- # instance actually completed is per-instance state,
77
- # `SagaInterpreter`'s own `completed_compensations`, not a
78
- # fact `Saga` — a pure declaration reading — could ever hold).
79
- # Every `compensates` any handler's own dispatch declares,
80
- # forward declaration order, then whatever this leg's own
81
- # hand-written body still lists — coexistence, not replacement
82
- # (`ProcessManagerBuilder::HandlerBuilder#dispatch_impl`'s own
83
- # comment): a saga can derive some of its compensation and
84
- # still hand-write the rest for what isn't expressible as
85
- # "undo command X".
56
+ # A static preview in declaration order, not one instance's runtime history.
57
+ # Derived `compensates` come first, then the leg's hand-written body, so a saga
58
+ # can derive some compensation and hand-write the rest.
86
59
  derived = handlers.flat_map { |handler| handler.dispatches.filter_map(&:compensates) }
87
60
  Bluebook::Saga.new(trigger: Bluebook::ProcessManager::REFUSED, from_state: leg.from_state,
88
61
  to_state: leg.to_state, compensations: derived + leg.dispatches)
89
62
  end
90
63
 
91
- # Says whether this procedure declares a handler for `REFUSED`.
64
+ # Whether this procedure declares a handler for `REFUSED`.
92
65
  #
93
- # @return [Boolean] whether this procedure has a derivable saga
66
+ # @return [Boolean]
94
67
  def saga? = !saga.nil?
95
68
  end
96
69
  end
@@ -1,20 +1,31 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # **What a read model does**. Its declared half is the gathered heads
4
+ # What a read model does. Its declared half is the gathered heads
5
5
  # and the query shape; these are readings taken off them.
6
6
  module ReadModel
7
+ # Every reduction a read model may declare over its one eligible collection, each
8
+ # naming the ivar that holds its declared value and the word it reads back as in a
9
+ # refusal message. A read model reports one shape, so at most one of these is ever set.
10
+ REDUCTION_FIELDS = {
11
+ count: "count", median_field: "median", sum_field: "sum", avg_field: "avg",
12
+ min_field: "min", max_field: "max", percentile_field: "percentile",
13
+ any_field: "any", all_field: "all"
14
+ }.freeze
15
+
16
+ # @return [Boolean] whether this read model declares any reduction (`REDUCTION_FIELDS`)
17
+ def reducing? = REDUCTION_FIELDS.each_key.any? { |ivar| instance_variable_get(:"@#{ivar}") }
18
+
7
19
  # Lists the fields this read model groups rows by.
8
20
  #
9
21
  # @return [Array<Symbol>] each declared `group_by` field's name, in declaration order
10
22
  def group_by_fields = @group_by.map { |row| row[:field].to_sym }
11
23
 
12
- # Reports whether this read model's `group_by` names every identity head
13
- # of the aggregate it groups (ADR 0061, decision D1).
24
+ # Reports whether this read model's `group_by` names every identity
25
+ # head of the aggregate it groups (ADR 0061).
14
26
  #
15
- # Such a key path cannot be shared by two rows, so it is accepted from the
16
- # declaration alone and never checked for a collision at dispatch. Any
17
- # other key path is checked per request.
27
+ # Such a key path can't be shared by two rows, so uniqueness is accepted
28
+ # from the declaration alone rather than checked per request.
18
29
  #
19
30
  # @param aggregate [Bluebook::Aggregate, nil] the aggregate of this read
20
31
  # model's one many-side head
@@ -27,10 +38,8 @@ module Hecks
27
38
  !identity.empty? && (identity - group_by_fields).empty?
28
39
  end
29
40
 
30
- # `!!` rather than a bare `@count` — the DSL/reconstruction
31
- # boundary (ReadModel#initialize) already normalises to
32
- # `true`/`nil`, so this is belt and braces against a future
33
- # caller constructing a ReadModel by hand with `count: false`.
41
+ # `!!` guards against a future caller constructing a ReadModel by
42
+ # hand with `count: false` rather than the normalised `nil`.
34
43
  #
35
44
  # @return [Boolean] whether this read model reduces to a row count
36
45
  def count? = !!@count
@@ -40,14 +49,9 @@ module Hecks
40
49
  # @return [String] this read model's name in `snake_case`
41
50
  def query_name = Naming.snake(@name)
42
51
 
43
- # Which gathered heads the filtering applies to (ADR 0055) — plural,
44
- # since `where`/`order_by`/`limit`/`offset` can now each independently
45
- # name a many-side head via `on:` once there's more than one. A read
46
- # model with a single many-side head keeps the old reading: every
47
- # untargeted option (plus `group_by`/`count`/`median`, still
48
- # single-head-only — ADR 0055) applies to it, same as before `on:`
49
- # existed. With several many-side heads, only the ones actually named
50
- # by a targeted option are eligible.
52
+ # Which gathered heads the filtering applies to (ADR 0055): with one
53
+ # many-side head every untargeted option applies to it; with several,
54
+ # only the ones a targeted option names via `on:` are eligible.
51
55
  #
52
56
  # @return [Array<Symbol>] the `:as` name of each many-side head that filtering
53
57
  # applies to; `[]` if this read model has no many-side head
@@ -61,10 +65,7 @@ module Hecks
61
65
  targets.filter_map { |target| many.find { |head| head[:aggregate] == target.to_s } }.map { |head| head[:as] }
62
66
  end
63
67
 
64
- # The pre-`on:` reading (ADR 0055), unchanged: with exactly one
65
- # many-side head, every untargeted option (plus `group_by`/`count`/
66
- # `median`, still single-head-only) applies to it — split out only
67
- # to keep `filtered_head_names` itself under this file's own
68
+ # Split out only to keep `filtered_head_names` under this file's own
68
69
  # complexity budget, not because the two questions differ in kind.
69
70
  #
70
71
  # @param many [Array<Hash{Symbol => Object}>] the read model's many-side
@@ -73,18 +74,11 @@ module Hecks
73
74
  # declared, else `[]`
74
75
  def single_filtered_head_name(many)
75
76
  declared = wheres.any? || order_by || limit || offset || authorization&.tenant ||
76
- @group_by.any? || count? || @median_field
77
+ @group_by.any? || reducing?
77
78
  declared ? [many.first[:as]] : []
78
79
  end
79
80
 
80
- # The where/order_by/limit/offset that apply to one eligible head
81
- # (ADR 0055) — a small view `Ports::Query::InMemory.execute` reads
82
- # exactly the way it already reads a whole `Query`/`ReadModel`
83
- # (`.wheres`/`.order_by`/`.limit`/`.offset`/`.null_semantics`), scoped
84
- # to `head_as`'s own aggregate: an untargeted option applies when
85
- # `head_as` is the read model's one many-side head (the pre-`on:`
86
- # reading, unchanged) ; a targeted one applies when its `target`
87
- # resolves to `head_as`'s own aggregate.
81
+ # Filtering options scoped to one included aggregate head (ADR 0055).
88
82
  FilteredOptions = Struct.new(:wheres, :order_by, :limit, :offset, :null_semantics)
89
83
 
90
84
  # Scopes this read model's filtering options down to one included head.
@@ -1,35 +1,17 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # The behaviour more than one construct shares.
5
- #
6
- # None of this is new duplication. `attribute(named)` was written
7
- # out four separate times — on Aggregate, Entity, Command and
8
- # PortOperation — and the identity derivation twice, byte for byte,
9
- # for as long as those constructs have existed. Splitting holding
10
- # from doing is what made them visible: the same method in four
11
- # files reads as four methods, and the same method in four modules
12
- # named `Behaviour::*` reads as one repeated.
13
- #
14
- # Written to work whether the construct is included into (an
15
- # ordinary object like Aggregate) or extended into (a class-shaped
16
- # one like Command), because every one of them reads instance
17
- # variables and nothing else.
4
+ # Behaviour shared by more than one construct. Each module works whether it is included
5
+ # (an ordinary object like Aggregate) or extended (a class-shaped one like Command),
6
+ # because it reads only instance variables.
18
7
 
19
8
  # A construct whose identity is a join of declared paths.
20
9
  #
21
- # The paths, in declaration order, because the identity is their join.
22
- # "number.value" says which field carries the identity ; several paths
23
- # say the identity is made of several facts, which is what anything
24
- # named beneath another thing needs. `identity_heads` are the attributes
25
- # those paths start at — what every reader that looks up or coerces an
26
- # attribute actually wants — and `identified_by` is the single head,
27
- # offered only when there is one path to have a head of. A composite has
28
- # no single head, and answering with the first would be a guess ; the
29
- # readers that need all of them ask for `identity_heads`.
10
+ # Several paths mean the identity is made of several facts. `identity_heads` are the
11
+ # attributes those paths start at; `identified_by` is the single head, set only when there
12
+ # is exactly one, since a composite has no single head and the first would be a guess.
30
13
  module Identified
31
- # Derives `identity_paths`, `identity_heads` and the single-head form of
32
- # `identified_by` from the declared `identified_by` path(s).
14
+ # Derives `identity_paths`, `identity_heads` and the single-head `identified_by`.
33
15
  #
34
16
  # @return [void]
35
17
  def derive_identity
@@ -41,72 +23,53 @@ module Hecks
41
23
 
42
24
  # A construct that answers for its own declarations by name.
43
25
  #
44
- # Indexed once, since the declarations are final by the time the
45
- # construct exists — every dispatch asks these finders by name, and a
46
- # linear scan repeated on every call was doing work the declared shape
47
- # had already settled at boot.
48
- #
49
- # `index_by_name` takes the collections to index rather than naming
50
- # them, because which collections a construct has is exactly the part
51
- # that differs: an aggregate has five, an entity three, a command one.
26
+ # Indexed once because declarations are final when the construct exists. `index_by_name`
27
+ # takes the collections to index since which ones a construct has differs per construct.
52
28
  module Indexed
53
- # Keyed by symbol — an attribute is asked for by its declared
54
- # symbol name everywhere in the runtime.
29
+ # Keyed by symbol, the way the runtime asks for an attribute.
55
30
  #
56
- # @param attributes [Array<Bluebook::Attribute>] the construct's declared
57
- # attributes
31
+ # @param attributes [Array<Bluebook::Attribute>]
58
32
  # @return [void]
59
33
  def index_attributes(attributes)
60
34
  @attributes_by_name = attributes.to_h { |held| [held.name, held] }
61
35
  end
62
36
 
63
- # Keyed by string and by `hecks_name` — a command, query or value
64
- # object is a construct whose Ruby `name` is something else
65
- # entirely (a constant path, or nothing at all for an anonymous
66
- # class), so the declared name is the only one worth indexing.
37
+ # Keyed by string and by `hecks_name`, since such a construct's Ruby `name` is a
38
+ # constant path or nothing at all for an anonymous class.
67
39
  #
68
- # @param collection [Array<#hecks_name>] declared constructs to index —
69
- # value objects, commands or queries, each answering `hecks_name`
70
- # @return [Hash{String => Object}] the collection keyed by each member's
71
- # `hecks_name`
40
+ # @param collection [Array<#hecks_name>] value objects, commands or queries
41
+ # @return [Hash{String => Object}]
72
42
  def index_by_hecks_name(collection)
73
43
  collection.to_h { |held| [held.hecks_name, held] }
74
44
  end
75
45
 
76
- # Finds a declared attribute by its declared name.
46
+ # Finds a declared attribute by name.
77
47
  #
78
- # @param named [String, Symbol] the attribute's declared name
79
- # @return [Bluebook::Attribute, nil] the attribute named `named`, or `nil`
80
- # if none is declared under that name
48
+ # @param named [String, Symbol]
49
+ # @return [Bluebook::Attribute, nil]
81
50
  def attribute(named) = @attributes_by_name[named.to_sym]
82
51
 
83
- # Finds a declared command by its declared name.
52
+ # Finds a declared command by name.
84
53
  #
85
- # @param named [String, Symbol] the command's declared name
86
- # @return [Class, nil] the command class (a `Bluebook::Command` subclass)
87
- # named `named`, or `nil` if none is declared under that name
54
+ # @param named [String, Symbol]
55
+ # @return [Class, nil] a `Bluebook::Command` subclass
88
56
  def command(named) = @commands_by_name[named.to_s]
89
57
 
90
- # Finds a declared query by its declared name.
58
+ # Finds a declared query by name.
91
59
  #
92
- # @param named [String, Symbol] the query's declared name
93
- # @return [Bluebook::Query, nil] the query named `named`, or `nil` if none
94
- # is declared under that name
60
+ # @param named [String, Symbol]
61
+ # @return [Bluebook::Query, nil]
95
62
  def query(named) = @queries_by_name[named.to_s]
96
63
  end
97
64
 
98
65
  # A construct that owns what it declares.
99
66
  #
100
- # Owner links are only ever read lazily — hecks_fqn at ask time,
101
- # Reference#resolve at dispatch time — so the moment the construct
102
- # is complete is the right stamping point: its declarations are
103
- # final, and nothing outside needs to remember to stamp them.
67
+ # Owner links are read lazily (hecks_fqn, Reference#resolve), so stamping when the
68
+ # construct is complete is early enough and needs no help from outside.
104
69
  module Owns
105
70
  # Stamps each of `children` as owned by this construct.
106
71
  #
107
- # @param children [Array<Object>] the construct's own declared children —
108
- # arrays or bare objects, flattened before stamping — each answering
109
- # `hecks_owner=`
72
+ # @param children [Array<#hecks_owner=>] arrays or bare objects, flattened first
110
73
  # @return [void]
111
74
  def stamp(*children)
112
75
  children.flatten.each { |child| child.hecks_owner = self }
@@ -1,17 +1,10 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # **What a value object does**. Extended, not included — a value object
5
- # is a class (`Class.new(self)`, one per declared shape), so its
6
- # behaviour is singleton behaviour, and the holding half's `absorb`
7
- # is what a generated constructor would be.
4
+ # Behaviour of a value object; extended rather than included, since each shape is
5
+ # its own class.
8
6
  module ValueObject
9
- # Recorded as its own fact (`closed_set`), not left to be inferred from
10
- # `members: []` alone — an empty `one_of` and no `one_of` at all would
11
- # otherwise be indistinguishable, which would leave the rule about it
12
- # only livable in the builder. Recording the declaration lets the
13
- # language judge it instead, the same way an empty attribute name
14
- # survives into the IR and is judged there.
7
+ # Recorded as its own fact so an empty `one_of` differs from no `one_of` at all.
15
8
  #
16
9
  # @return [Boolean] whether this value object declares `one_of`, even
17
10
  # if left empty
@@ -24,21 +17,9 @@ module Hecks
24
17
  # `nil` if none is declared under that name
25
18
  def attribute(named) = attributes.find { |held| held.name == named.to_sym }
26
19
 
27
- # A single-attribute value object (EmailAddress{address},
28
- # CustomerNumber{value}) is a name for a scalar, not a genuine
29
- # group — [[feedback_name_the_scalar_field]]. `adapters/driven/
30
- # sql_query_builder.rb` and `fuzzing/invalid_value_generator.rb`
31
- # now read through this rather than inlining the check.
20
+ # A single-attribute value object (EmailAddress{address}) names a scalar, not a group.
32
21
  #
33
- # `forms/field_shape.rb`'s own two `attributes.first.name` sites
34
- # (`closed_set_options`/`closed_set_field`) look identical but are
35
- # not the same question — they pick a closed set's discriminant
36
- # column, and a closed set can be genuinely multi-attribute
37
- # (`Runtime::Value::Admission#member_matches?`'s own comment
38
- # names a real one: `StatementFrequency`'s `cadence`/
39
- # `retention_months`/`paper_fee_cents`). `sole_attribute` would
40
- # return `nil` for that shape and break the discriminant lookup —
41
- # left as `.first` on purpose, not a missed migration.
22
+ # A closed set's discriminant column is a different question and may span attributes.
42
23
  #
43
24
  # @return [Bluebook::Attribute, nil] this value object's only
44
25
  # attribute, or `nil` when it has zero or more than one