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
@@ -3,30 +3,20 @@ require_relative "../../bluebook/hexagon"
3
3
  module Hecks
4
4
  module Runtime
5
5
  class Registry
6
- # The wiring gate: every bind names a declared aggregate, every
7
- # adapter satisfies the verb its port declares, every world setting is
8
- # a field the adapter admits, and the default adapter is usable at
9
- # all. Included into Registry — `verify!` is what a boot calls after
10
- # loading, and the smaller checks are also called piecemeal by the
11
- # repository factory.
6
+ # The wiring gate: every bind names a declared aggregate, every adapter satisfies its
7
+ # port's verb, and every world default is usable. `verify!` runs it all at boot.
12
8
  module Verification
13
- # Runs the whole wiring gate against this registry's loaded bluebooks,
14
- # hexagons, ports and adapters.
15
- #
16
- # @return [Runtime::Registry] self
17
- # @raise [Runtime::WiringError] if a bind names an undeclared aggregate, an
18
- # adapter cannot satisfy its port's verb or declared `answers`, a world
19
- # setting names a field its adapter does not declare, the default adapter
20
- # is unusable, a world's `default_adapter` is not a persistence adapter, a
21
- # command declares a role with no authorization provider attached, or a
22
- # membership chapter is loaded with no identity chapter
9
+ # Runs every wiring check against this registry's loaded bluebooks, hexagons, ports
10
+ # and adapters.
23
11
  def verify!
24
12
  verify_default_adapter!
25
13
  verify_world_defaults!
26
14
  verify_singleton_port_answers!
27
15
  refuse_cross_package_bluebook_merge!
16
+ refuse_reserved_chapter_names!
28
17
  refuse_membership_without_identity!
29
18
  refuse_unresolved_port_operations!
19
+ refuse_unanswerable_queries!
30
20
 
31
21
  @hecksagons.each_value do |hexagon|
32
22
  refuse_ungoverned_roles!(hexagon)
@@ -35,19 +25,9 @@ module Hecks
35
25
  refuse_bounded_without_acl!(hexagon)
36
26
 
37
27
  hexagon.binds.each do |bind|
38
- # A domain-level default (§0) — `persisted_by "Heki"` bare,
39
- # applying to whichever aggregates don't override it — names
40
- # no aggregate of its own, so there's nothing to look up in
41
- # the bluebook for this row specifically. Still validate its
42
- # own adapter/verb shape (the same reason
43
- # `verify_default_adapter!` checks the framework-wide
44
- # default the same way, aggregate-less). Coverage of real
45
- # aggregates that only resolve through this default comes
46
- # from their own dispatch-time `BindingPolicy.resolve` —
47
- # deliberately not required to be exhaustive here, the same
48
- # leniency this method already extended to any aggregate
49
- # left out of an explicit bind list entirely (real test
50
- # fixtures bind only the aggregates they exercise).
28
+ # A domain-level default (§0) names no aggregate of its own; still validate its
29
+ # adapter/verb shape. Real aggregates resolving through it are covered by their
30
+ # own dispatch-time `BindingPolicy.resolve`, not required to be exhaustive here.
51
31
  if bind.aggregate.nil?
52
32
  check_verb(bind)
53
33
  next
@@ -67,13 +47,7 @@ module Hecks
67
47
  self
68
48
  end
69
49
 
70
- # Checks that the framework-wide default persistence adapter (used by any
71
- # aggregate left out of an explicit bind list) is itself wired correctly.
72
- #
73
- # @return [Runtime::Registry] self
74
- # @raise [Runtime::WiringError] if the default adapter cannot satisfy the
75
- # persistence port's verb, is missing a declared `answers` method, or has
76
- # no Ruby implementation
50
+ # Checks that the framework-wide default persistence adapter is itself wired correctly.
77
51
  def verify_default_adapter!
78
52
  name = Ports::Persistence::DEFAULT_ADAPTER
79
53
 
@@ -92,14 +66,7 @@ module Hecks
92
66
  "aggregate with no bind could not be given one: #{e.message}"
93
67
  end
94
68
 
95
- # Checks that `bind`'s adapter implements the port it names and satisfies
96
- # the verb the bind declares.
97
- #
98
- # @param bind [Bluebook::Bind] the bind to check
99
- # @return [void]
100
- # @raise [Runtime::WiringError] if `bind`'s adapter is unknown, declares an
101
- # unknown port, is missing a declared `answers` method, or cannot satisfy
102
- # `bind`'s own verb
69
+ # Checks that `bind`'s adapter implements the port it names and satisfies its verb.
103
70
  def check_verb(bind)
104
71
  port = port_for(bind)
105
72
  check_answers(port, bind.adapter)
@@ -110,20 +77,8 @@ module Hecks
110
77
  "and cannot satisfy #{bind.verb}"
111
78
  end
112
79
 
113
- # The method contract a `.port` file's `verb`/`signal` never
114
- # carried — an adapter can name the right port, satisfy the right
115
- # verb, and admit every `.world` setting `check_settings` checks,
116
- # and still be missing the one method a live dispatch will
117
- # actually call. `answers` is optional per port (an empty list is
118
- # today's pre-existing behavior, unchecked), so this only ever
119
- # tightens a port that opted in.
120
- #
121
- # @param port [Bluebook::Port] the port whose declared `answers` methods
122
- # `adapter_name` must respond to
123
- # @param adapter_name [String] the adapter's declared name to check
124
- # @return [void]
125
- # @raise [Runtime::WiringError] if `adapter_name` has no Ruby implementation,
126
- # or its implementation does not respond to one of `port.answers`
80
+ # `answers` is optional per port, so an adapter can satisfy a port's verb and still
81
+ # miss a method live dispatch will call; this only tightens ports that opt in.
127
82
  def check_answers(port, adapter_name)
128
83
  answers = Array(port.answers)
129
84
  return if answers.empty?
@@ -138,27 +93,19 @@ module Hecks
138
93
  "#{answers.map(&:inspect).join(', ')}"
139
94
  end
140
95
 
141
- # **The nine singleton ports' own gap** — `persistence`, `projection`
142
- # and `loading` are per-aggregate bindings, checked above through
143
- # every real `bind` a hexagon declares; a singleton port
144
- # (`clock`, `authorization`, …) is never bound to an aggregate at
145
- # all, so nothing above ever resolves one and nothing above ever
146
- # ran `check_answers` against it. Each one's own `Ports::*.adapter`
147
- # already refuses zero or multiple implementations, live, at
148
- # first dispatch — that stays exactly as-is here (0 or 2+ is
149
- # ambiguity, not a method-contract question, and asserting every
150
- # declared port must have exactly one adapter would wrongly
151
- # refuse a boot that simply never wires a port it doesn't use).
152
- # This only ever tightens the one case those checks don't cover:
153
- # exactly one adapter, wired, missing a method `answers` names.
96
+ # persistence/projection/loading are per-aggregate bound and already checked via
97
+ # each bind above; a singleton port is never bound to an aggregate at all.
154
98
  PER_AGGREGATE_PORTS = %w[persistence projection loading].freeze
155
99
 
156
- # Checks every singleton port (not per-aggregate-bound) with exactly one
157
- # wired adapter against its own declared `answers` methods.
158
- #
159
- # @return [Runtime::Registry] self
160
- # @raise [Runtime::WiringError] if a singleton port's one wired adapter is
161
- # missing one of its declared `answers` methods
100
+ # The directory holding the gem's own Hecks chapter, the only place a chapter named
101
+ # `Hecks` may be declared from.
102
+ GEM_CHAPTER_DIR = File.expand_path("../../hecks", __dir__).freeze
103
+
104
+ # The chapter names only the gem itself may declare (ADR 0080, section 9).
105
+ RESERVED_CHAPTER_NAMES = %w[Hecks].freeze
106
+
107
+ # Checks every singleton port with exactly one wired adapter against its own
108
+ # declared `answers` methods.
162
109
  def verify_singleton_port_answers!
163
110
  @ports.each_value do |port|
164
111
  next if PER_AGGREGATE_PORTS.include?(port.name)
@@ -172,16 +119,8 @@ module Hecks
172
119
  self
173
120
  end
174
121
 
175
- # Checks that every setting `settings` declares (besides `:adapter`) is a
176
- # field `bind`'s adapter actually admits.
177
- #
178
- # @param bind [Bluebook::Bind] the bind naming the adapter to check against;
179
- # a no-op if its adapter is unknown
180
- # @param settings [Hash{Symbol => Object}] the world's declared settings for
181
- # this bind
182
- # @return [void]
183
- # @raise [Runtime::WiringError] if `settings` declares a field `bind`'s
184
- # adapter does not declare
122
+ # Checks that every setting `settings` declares (besides `:adapter`) is a field
123
+ # `bind`'s adapter actually admits.
185
124
  def check_settings(bind, settings)
186
125
  adapter = @adapters[bind.adapter]
187
126
  return unless adapter
@@ -196,12 +135,6 @@ module Hecks
196
135
  "Add the field to the adapter, or remove it from the world."
197
136
  end
198
137
 
199
- # Finds the port `bind`'s adapter declares.
200
- #
201
- # @param bind [Bluebook::Bind] the bind naming the adapter to look up
202
- # @return [Bluebook::Port] the port `bind`'s adapter declares
203
- # @raise [Runtime::WiringError] if `bind` names an unknown adapter, or one
204
- # declaring an unknown port
205
138
  def port_for(bind)
206
139
  adapter = @adapters[bind.adapter]
207
140
  raise WiringError, "unknown adapter #{bind.adapter.inspect}" unless adapter
@@ -210,12 +143,6 @@ module Hecks
210
143
  raise(WiringError, "adapter #{bind.adapter} declares unknown port #{adapter.port.inspect}")
211
144
  end
212
145
 
213
- # Finds the Ruby module implementing the adapter declared `name`.
214
- #
215
- # @param name [String] the adapter's declared name, such as `"PostgresEra"`
216
- # @return [Module] the adapter module or class under `Hecks::Adapters`
217
- # @raise [Runtime::WiringError] if no Ruby implementation named `name` exists
218
- # under `Hecks::Adapters`
219
146
  def adapter_class(name)
220
147
  Adapters.const_get(name)
221
148
  rescue NameError
@@ -225,33 +152,10 @@ module Hecks
225
152
 
226
153
  private
227
154
 
228
- # `role` is real access control only when governance can check it
229
- # against something — a command that declares a role but whose
230
- # domain never attaches Governance would leave that role forever
231
- # unchecked, exactly the defect ADR 0025 §9 names ("role gates
232
- # access control by exact string equality ... Governance ...
233
- # connected to none of it"). Checked here, at `verify!` — recovered
234
- # and moved, not new: running this per-block, at hecksagon
235
- # build time (Bluebook::DSL::HecksagonBuilder#build), breaks
236
- # the moment a domain is split across multiple hecksagon
237
- # blocks (base + an `environments/<name>.hecksagon` overlay,
238
- # Runtime::Loader.boot's `environment:` — see its own comment for
239
- # the recovery provenance): every block but the one declaring
240
- # `uses_framework "Governance"` would be refused there, even
241
- # though `Registry#add_hecksagon` merges every block for a domain
242
- # into one Hecksagon before anything ever dispatches against it.
243
- # Checking the merged result once, here, after every file for
244
- # this domain has loaded, is both more permissive (no need to
245
- # repeat `uses_framework` in every file) and strictly more
246
- # correct (a check against an incomplete, not-yet-merged
247
- # hecksagon can never see the real final shape).
248
- #
249
- # A provider is recognised by its declaration, not its name —
250
- # `authorization_provider_for` answers for the domain's own
251
- # chapter too, so Governance (which declares `provides
252
- # "authorization"`) passes here because of what it declares, and
253
- # the same rule `CommandRules::Authorization#governance_attached?`
254
- # applies at dispatch time.
155
+ # Checked once against the merged hecksagon so a domain split across multiple
156
+ # hecksagon files sees every uses_framework declaration first. A role is real
157
+ # access control only once an authorization provider exists to check it against
158
+ # (ADR 0025); a provider is recognized by declaring authorization, not by name.
255
159
  def refuse_ungoverned_roles!(hexagon)
256
160
  return if authorization_provider_for(hexagon.domain)
257
161
 
@@ -268,15 +172,9 @@ module Hecks
268
172
  "without that it is silent decoration, the exact defect this refusal exists to catch"
269
173
  end
270
174
 
271
- # A vendored embryonaut bluebook is a bounded context, not a pile of
272
- # types the consumer inlines. `uses_embryonaut_bluebook` only loads
273
- # the package's `.bluebook` files — persistence, Governance, and the
274
- # anti-corruption layer (`translates` field mapping) live on a named
275
- # sibling hecksagon the consumer must declare. Without that hexagon
276
- # the package has no wiring of its own, and cross-context field
277
- # mapping has nowhere to be written. Breaking in 2.0: attaching a
278
- # vendored chapter without `Hecks.hecksagon "PackageName"` refuses
279
- # at boot rather than silently sharing the consumer's hexagon.
175
+ # `uses_embryonaut_bluebook` only loads a package's `.bluebook` files; persistence,
176
+ # Governance and the `translates` ACL live on a sibling hecksagon the consumer must
177
+ # declare, or cross-context field mapping has nowhere to be written.
280
178
  def refuse_unwired_vendored_bluebooks!(hexagon)
281
179
  Array(hexagon.vendored_bluebooks).each do |package|
282
180
  chapter_name = Naming.pascal(package)
@@ -291,16 +189,14 @@ module Hecks
291
189
  end
292
190
  end
293
191
 
294
- # Same gate as vendored packages: `uses_framework` loads a bounded
295
- # context, and the consumer must declare the sibling hecksagon that
296
- # is its ACL. Governance/Identity/Privacy already follow this in
297
- # every real consumer; boot now refuses a silent miss.
192
+ # `uses_framework` and `attaches` load a bounded context; the consumer must declare the
193
+ # sibling hecksagon that is its ACL (Governance/Identity/Privacy already do).
298
194
  def refuse_unwired_framework_members!(hexagon)
299
- Array(hexagon.framework_members).each do |member|
195
+ hexagon.member_chapters.each do |member|
300
196
  next if hecksagon(member)
301
197
 
302
198
  raise WiringError,
303
- "#{hexagon.domain} attaches framework member #{member.inspect} " \
199
+ "#{hexagon.domain} attaches #{member.inspect} " \
304
200
  "(bounded context) but never declared Hecks.hecksagon " \
305
201
  "#{member.inspect} — put that sibling (and any `translates` " \
306
202
  "ACL) in context_map.hecksagon; same-name blocks merge, " \
@@ -308,19 +204,12 @@ module Hecks
308
204
  end
309
205
  end
310
206
 
311
- # An explicit `bounded` mark on a consumer chapter always needs an
312
- # ACL — at least one `translates` block. Any field can be mapped;
313
- # the BC does not list which. `uses_framework` / `uses_embryonaut_bluebook`
314
- # mark the attached chapter bounded (module wrap, no Object shortcut)
315
- # and require the sibling hecksagon above; they do not require a
316
- # `translates` on that sibling unless the consumer also wrote `bounded`.
317
- # rust/host Google sign-in reads `ir.json`'s `membership` and
318
- # `identity` keys (Exporter.membership / Exporter.identity) —
319
- # never a deploy-time env var. Membership without Identity is
320
- # the exact gap that produced a live `google_unlinked` after a
321
- # successful Google handshake: provision cannot Register/Link.
322
- # Refuse at Ruby boot (and project_rust, which exports the same
323
- # pair) so a missing sibling cannot ship.
207
+ # An explicit `bounded` mark on a consumer chapter always needs an ACL. `uses_framework`
208
+ # / `uses_embryonaut_bluebook` mark the attached chapter bounded and require the sibling
209
+ # hecksagon above; they don't require a `translates` on it unless the consumer also
210
+ # wrote `bounded`.
211
+ # rust/host Google sign-in reads ir.json's membership/identity keys, never a deploy-time
212
+ # env var; Membership without Identity means provision cannot Register/Link an identity.
324
213
  def refuse_membership_without_identity!
325
214
  return unless @bluebooks.values.any? { |chapter| chapter.provides?(Bluebook::Capabilities::MEMBERSHIP) }
326
215
  return if @bluebooks.values.any? { |chapter| chapter.provides?(Bluebook::Capabilities::IDENTITY) }
@@ -333,11 +222,8 @@ module Hecks
333
222
  "identity verbs are exported onto ir.json, not guessed at deploy."
334
223
  end
335
224
 
336
- # A `provides` row whose contract kind is `:port_operation` names an
337
- # operation the chapter's hecksagon declares, and the hecksagon
338
- # attaches after the chapter is built, so this is the first point the
339
- # operation can be checked. Without it, a host reading the declared
340
- # verb would dispatch to an operation nothing declares.
225
+ # A hecksagon attaches after its chapter builds, so this is the first point a
226
+ # declared `:port_operation` capability can be checked against it.
341
227
  def refuse_unresolved_port_operations!
342
228
  @bluebooks.each_value do |chapter|
343
229
  chapter.provides.each do |row|
@@ -352,12 +238,130 @@ module Hecks
352
238
  end
353
239
  end
354
240
 
355
- # Says whether a chapter declares the port operation an
356
- # `"Aggregate.Port.Operation"` verb names.
357
- #
358
- # @param chapter [Bluebook::Chapter] the chapter whose aggregates' ports are searched
359
- # @param verb [String] the verb, spelled `"Aggregate.Port.Operation"`
360
- # @return [Boolean] whether that aggregate has that port with that operation
241
+ # A query has exactly one answer path. It is derivable when the bluebook says which of the
242
+ # aggregate's own records it wants (a where, order_by, limit or offset, or no arguments at
243
+ # all: the plain list) and returns no value object of its own; it is bound when it
244
+ # `returns` a value object and the hecksagon names the port whose adapter answers it. None
245
+ # of the two is "no answer path"; both is "two answer paths". A bound query also needs an
246
+ # adapter behind its port that implements it, found here so it fails at boot rather than
247
+ # on the first ask.
248
+ def refuse_unanswerable_queries!
249
+ @bluebooks.each_value do |chapter|
250
+ chapter.aggregates.each do |aggregate|
251
+ refuse_misbound_queries!(chapter, aggregate)
252
+
253
+ aggregate.queries.each { |query| refuse_answer_paths!(chapter, aggregate, query) }
254
+ aggregate.entities.each do |entity|
255
+ entity.queries.each { |query| refuse_entity_answer_path!(chapter, aggregate, entity, query) }
256
+ end
257
+ end
258
+ end
259
+ end
260
+
261
+ # Counts the query's answer paths (the bindings, plus the derived answer when it exists)
262
+ # and refuses any count but one, then checks a bound query's shape and adapter.
263
+ def refuse_answer_paths!(chapter, aggregate, query)
264
+ where = "#{chapter.name}::#{aggregate.hecks_name}.#{query.hecks_name}"
265
+ ports = aggregate.query_bindings(query.hecks_name)
266
+ paths = ports.size + (derivable?(query) ? 1 : 0)
267
+
268
+ if paths > 1
269
+ raise WiringError, "#{where} has two answer paths: #{answer_path_names(query, ports)} — " \
270
+ "a query is answered from records or from outside, not both"
271
+ end
272
+ return check_bound_query!(chapter, aggregate, query, ports.first) if ports.any?
273
+ return if paths == 1
274
+
275
+ raise WiringError, no_answer_path_message(chapter, aggregate, query, where)
276
+ end
277
+
278
+ # A query that returns nothing and says something about which records it wants, or wants
279
+ # all of them. One that takes arguments but filters, orders and bounds nothing reads none
280
+ # of them, so it derives no answer.
281
+ def derivable?(query)
282
+ return false if query.returns
283
+
284
+ filters_records?(query) || query.attributes.empty?
285
+ end
286
+
287
+ def answer_path_names(query, ports)
288
+ names = ports.map { |port| "the #{port.name} port" }
289
+ names.unshift("its records") if derivable?(query)
290
+ names.join(" and ")
291
+ end
292
+
293
+ def no_answer_path_message(chapter, aggregate, query, where)
294
+ if query.returns
295
+ "#{where} has no answer path: it returns #{query.returns}, which only an adapter can " \
296
+ "answer, and no hecksagon port binds it. Bind it: `#{chapter.name}::#{aggregate.hecks_name}" \
297
+ ".port \"Port\" do answers_query \"#{query.hecks_name}\" end`."
298
+ else
299
+ "#{where} has no answer path: it declares no where and returns nothing, and no hecksagon " \
300
+ "binds it — its arguments (#{query.attributes.map(&:name).join(', ')}) select nothing. " \
301
+ "Add a where, or declare what it returns and bind it in the hecksagon."
302
+ end
303
+ end
304
+
305
+ # Checks what a binding needs to be answerable: a returned value object the aggregate
306
+ # declares, and one adapter behind the port that implements the query's method.
307
+ def check_bound_query!(chapter, aggregate, query, port)
308
+ where = "#{chapter.name}::#{aggregate.hecks_name}.#{query.hecks_name}"
309
+ unless query.returns
310
+ raise WiringError, "#{where} is bound to the #{port.name} port but returns nothing — " \
311
+ "declare the value object its answer takes with `returns`"
312
+ end
313
+ if filters_records?(query)
314
+ raise WiringError, "#{where} has two answer paths: it is bound to the #{port.name} port but " \
315
+ "also declares where, order_by or limit over stored records"
316
+ end
317
+ if query.authorization
318
+ raise WiringError, "#{where} is bound to the #{port.name} port but declares authorize — " \
319
+ "an outside answer is never tenant-scoped or authorized, so drop the " \
320
+ "authorize or answer the query from records"
321
+ end
322
+ unless Value.value_object_for(aggregate, query.returns_name)
323
+ raise WiringError, "#{where} returns #{query.returns_name}, but #{aggregate.hecks_name} " \
324
+ "declares no such value object"
325
+ end
326
+
327
+ klass = AdapterLookup.adapter_class(self, port.name, asked: where)
328
+ AdapterLookup.check_answers!(klass, port.name, Naming.snake(query.hecks_name), query, asked: where)
329
+ end
330
+
331
+ # An entity's query reads the elements of its aggregate's list, and nothing outside can
332
+ # be bound to one, so declaring a value object to return leaves it no answer.
333
+ def refuse_entity_answer_path!(chapter, aggregate, entity, query)
334
+ where = "#{chapter.name}::#{aggregate.hecks_name}.#{entity.hecks_name}.#{query.hecks_name}"
335
+ if query.returns
336
+ raise WiringError, "#{where} has no answer path: it returns #{query.returns}, but " \
337
+ "only an aggregate's queries can be bound to a port"
338
+ end
339
+ return if derivable?(query)
340
+
341
+ raise WiringError, "#{where} has no answer path: it declares no where and returns nothing — its " \
342
+ "arguments (#{query.attributes.map(&:name).join(', ')}) select nothing"
343
+ end
344
+
345
+ # Refuses a binding that names a query its aggregate does not declare, or names one twice
346
+ # on a single port (the DSL already refuses that, so this guards a hand-built port).
347
+ def refuse_misbound_queries!(chapter, aggregate)
348
+ aggregate.ports.each do |port|
349
+ names = port.answered_queries.map(&:name)
350
+ names.each do |name|
351
+ where = "#{chapter.name}::#{aggregate.hecks_name}.#{name}"
352
+ unless aggregate.query(name)
353
+ raise WiringError, "the #{port.name} port binds #{where}, which the aggregate does not declare"
354
+ end
355
+ raise WiringError, "#{where} has two answer paths: the #{port.name} port twice" if names.count(name) > 1
356
+ end
357
+ end
358
+ end
359
+
360
+ # A query that says anything about which stored records it wants.
361
+ def filters_records?(query)
362
+ !(query.wheres.empty? && query.order_by.nil? && query.limit.nil? && query.offset.nil?)
363
+ end
364
+
361
365
  def port_operation_declared?(chapter, verb)
362
366
  aggregate_name, port_name, operation_name = verb.split(".", 3)
363
367
  ports = chapter.aggregate(aggregate_name)&.ports || []
@@ -377,8 +381,8 @@ module Hecks
377
381
  "with: { ... } end` (any field) or drop `bounded`."
378
382
  end
379
383
 
380
- # The suggestion, derived from whichever framework members actually
381
- # declare `provides "authorization"` — never a hardcoded name.
384
+ # Derived from whichever framework members actually declare `provides
385
+ # "authorization"` — never a hardcoded name.
382
386
  def authorization_attachment_hint
383
387
  providers = Framework.providers_of(Bluebook::Capabilities::AUTHORIZATION)
384
388
  return "attaches a chapter that provides \"authorization\" (no framework member declares one)" if providers.empty?
@@ -386,30 +390,43 @@ module Hecks
386
390
  providers.map { |name| "uses_framework #{name.inspect}" }.join(" or ")
387
391
  end
388
392
 
389
- # Every command this domain declares, an aggregate's own and every
390
- # entity nested inside one — the same reach `refuse_role_mismatch`
391
- # itself needs at dispatch time, just walked ahead of time here.
393
+ # Every command this domain declares, an aggregate's own and every entity nested
394
+ # inside one — the same reach dispatch-time role checking needs.
392
395
  def commands_in(bluebook_ir)
393
396
  bluebook_ir.aggregates.flat_map { |aggregate| aggregate.commands + aggregate.entities.flat_map(&:commands) }
394
397
  end
395
398
 
396
- # Two unrelated packages, one chapter name by coincidence — the
397
- # real risk `Registry#bluebook_sources` exists to catch (found
398
- # live: a stale `vendor/hecksagain` fork's own copy of Governance/
399
- # Identity/Deploy, still reachable on 4 consuming apps' own load
400
- # paths alongside the real gem). `BluebookBuilder.build`'s own
401
- # accumulation (several files declaring the same chapter name on
402
- # purpose — `lib/hecks/language/bluebook/*.bluebook` all open
403
- # `Hecks.bluebook "Bluebook"`) is never touched here — that merge
404
- # stays unconditional, checked only after every file has loaded,
405
- # the same "check the merged final result once" timing
406
- # `refuse_ungoverned_roles!` already uses and for the same reason
407
- # (a check against an incomplete load can never see the real
408
- # shape). What distinguishes intentional accumulation from
409
- # coincidence is package root, not file identity: files a real
410
- # gemspec or a `vendor/` boundary already treats as one unit are
411
- # expected to share a name; files from two different roots never
412
- # legitimately do.
399
+ # Refuses a chapter whose name is reserved unless every file that declared it sits under
400
+ # the gem's own chapter directory. A rename is the only fix, so the message says so.
401
+ #
402
+ # @raise [WiringError] naming the reserved word and the offending file(s)
403
+ def refuse_reserved_chapter_names!
404
+ RESERVED_CHAPTER_NAMES.each do |reserved|
405
+ next unless @bluebooks.key?(reserved)
406
+
407
+ sources = Array(@bluebook_sources[reserved]).compact
408
+ foreign = sources.reject { |path| gem_chapter_source?(path) }
409
+ next if foreign.empty? && !sources.empty?
410
+
411
+ where = foreign.empty? ? "" : " (declared in #{foreign.join(', ')})"
412
+ raise WiringError,
413
+ "a chapter named #{reserved.inspect} is refused: #{reserved.inspect} is a reserved " \
414
+ "word, the name of the gem's own chapter, and only the gem may declare it#{where}. " \
415
+ "Rename the chapter (for example to your app's name) in its " \
416
+ "`Hecks.bluebook #{reserved.inspect}` line and in its hecksagon."
417
+ end
418
+ end
419
+
420
+ # Whether `path` is a file of the gem's own chapter directory.
421
+ def gem_chapter_source?(path)
422
+ File.expand_path(path.to_s).start_with?("#{GEM_CHAPTER_DIR}/")
423
+ end
424
+
425
+ # Two packages can share a chapter name by coincidence (found live: a stale
426
+ # vendor/hecksagain fork of Governance/Identity/Deploy, still on 4 apps' load
427
+ # paths). Intentional accumulation (several files declaring the same chapter on
428
+ # purpose) is distinguished by package root, not file identity, and is left
429
+ # untouched here — checked once, after every file has loaded.
413
430
  def refuse_cross_package_bluebook_merge!
414
431
  @bluebook_sources.each do |name, paths|
415
432
  roots = paths.map { |path| package_root_for(path) }.uniq
@@ -424,15 +441,9 @@ module Hecks
424
441
  end
425
442
  end
426
443
 
427
- # The nearest boundary a path already belongs to — a real
428
- # gemspec (this is a package, whatever depends on it or vendors
429
- # it), or a bare `vendor/` path component, treated as its own
430
- # root regardless of what gemspec might sit above it: vendored
431
- # code should never be considered "the same package" as whatever
432
- # it's vendored into, even when nothing else marks the boundary.
433
- # Neither found, the path's own directory is the root — two
434
- # files with no closer marker only "belong together" if they are
435
- # literally the same file.
444
+ # The nearest boundary a path belongs to: a real gemspec, or a bare `vendor/`
445
+ # component (vendored code is never "the same package" as what vendors it).
446
+ # Falls back to the path's own directory when neither is found.
436
447
  def package_root_for(path)
437
448
  return path.to_s if path.nil?
438
449
 
@@ -448,37 +459,10 @@ module Hecks
448
459
  end
449
460
  end
450
461
 
451
- # A domain that declares a `process_manager` but whose
452
- # `saga_persistence` resolves to `NULL_SAGA_STORE` (no anchor
453
- # aggregate, a RemoteRuntime-shaped adapter, an adapter that
454
- # doesn't `respond_to?(:save_saga)`, or a rescued WiringError —
455
- # see `SagaPersistence#resolve_saga_persistence`) gets sagas that
456
- # advance correctly in-process and vanish on restart: no
457
- # checkpoint written, nothing for `rehydrate_sagas!` to find, no
458
- # compensation ever replayed. That is silent right up until the
459
- # process actually dies mid-saga — the same "consistency/
460
- # freshness defect applied to access control, failing open" ADR
461
- # 0025 named for an unchecked `role`, here applied to saga
462
- # durability instead.
463
- #
464
- # A warning, not a refusal — unlike `refuse_ungoverned_roles!`,
465
- # running sagas on a store with no `save_saga` is legitimate on
466
- # purpose in a fast in-memory test/dev boot (this project's own
467
- # `saga_durability_spec.rb` boots a process manager on `Memory`
468
- # specifically to exercise the saga_mutex without real I/O), so
469
- # refusing the boot outright would break a choice an author made
470
- # deliberately. What a deploy needs is for the gap to be loud and
471
- # undeniable, not for local dev/test to become impossible.
472
- # The outbox's twin of `warn_undurable_sagas!` — a domain that
473
- # declares anything a commit could owe a reaction to (a policy
474
- # listening to one of its events, or a process manager) but is
475
- # bound to an adapter with no outbox (`AppendOnly#outbox?`) gets
476
- # reactions the pre-outbox way: run inline, lost on a crash
477
- # between commit and reaction. A warning, not a refusal, for the
478
- # reason `warn_undurable_sagas!` gives — and Memory has an outbox
479
- # (in-process, like everything else it holds), so a dev/test
480
- # boot stays quiet; this speaks up for the file/remote adapters
481
- # that persist state durably but hand reactions to nothing.
462
+ # A domain with policies/a process_manager but no outbox on its bound adapter
463
+ # (`AppendOnly#outbox?`) runs reactions inline — lost on a crash between a
464
+ # commit and its reaction. A warning, not a refusal: Memory has an in-process
465
+ # outbox, so dev/test stays quiet, but file/remote adapters need this to be loud.
482
466
  def warn_undurable_outbox!(hexagon)
483
467
  bluebook_ir = bluebook(hexagon.domain)
484
468
  return unless bluebook_ir
@@ -505,6 +489,8 @@ module Hecks
505
489
  @bluebooks.each_value.any? { |candidate| candidate.policies.any? { |policy| emitted.include?(policy.event_name.to_s) } }
506
490
  end
507
491
 
492
+ # A warning, not a refusal: running sagas on a store with no `save_saga` is
493
+ # legitimate on purpose in a fast in-memory test/dev boot.
508
494
  def warn_undurable_sagas!(hexagon)
509
495
  bluebook_ir = bluebook(hexagon.domain)
510
496
  return unless bluebook_ir