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
@@ -13,10 +13,8 @@ require_relative "rebuild_sweep"
13
13
 
14
14
  module Hecks
15
15
  module Runtime
16
- # The dispatch pipeline for a command on an aggregate head. The payload
17
- # gate lives in command_interpreter/argument_gate.rb, the mutation walk
18
- # in command_interpreter/mutation_applier.rb; what stays here is the
19
- # order of the steps and how a record is addressed.
16
+ # The dispatch pipeline for a command on an aggregate head; the argument
17
+ # gate and mutation walk are mixed in from their own files.
20
18
  class CommandInterpreter
21
19
  include Interpreting
22
20
  include ArgumentGate
@@ -24,27 +22,17 @@ module Hecks
24
22
 
25
23
  attr_reader :registry
26
24
 
27
- # **The declared order** — Vocabulary::AggregateDispatchOrder
28
- # (language/bluebook/vocabulary.bluebook), read off the generated table
29
- # (lib/hecks/vocabulary.rb) rather than typed here. spec/vocabulary_
30
- # conformance_spec.rb holds every step to a real `step_<name>` handler,
31
- # both directions.
25
+ # Read off the generated table (lib/hecks/vocabulary.rb), not typed here.
26
+ # spec/vocabulary_conformance_spec.rb holds every step to a real
27
+ # `step_<name>` handler, both directions.
32
28
  DISPATCH_ORDER = Hecks::Vocabulary.symbols("AggregateDispatchOrder")
33
29
 
34
- # A last-resort safety valve, not the normal outcome path — see
35
- # `Runtime::StaleWrite`'s own comment. Two concurrent writers
36
- # against one aggregate resolve through exactly one retry in the
37
- # ordinary case (the loser's retried hydrate reads the winner's now-
38
- # committed state and its own `given` refuses for real, raising
39
- # `GivenNotMet`, not `StaleWrite`) — this cap exists for pathological
40
- # contention (many concurrent writers on one hot aggregate), not the
41
- # two-writer case.
30
+ # A cap for pathological contention (many concurrent writers on one hot
31
+ # aggregate) — the ordinary two-writer race resolves in a single retry.
42
32
  MAX_STALE_WRITE_RETRIES = 5
43
33
 
44
- # Every cross-step local held in one place, now that the sequence is
45
- # data-driven rather than `call`'s own literal method-call sequence —
46
- # `result` and `transition`/`old_state` default to nil until the step
47
- # that sets them runs, the same as unset locals would be before that point.
34
+ # Every cross-step local held in one place; fields default to nil until
35
+ # the step that sets them runs.
48
36
  Context = Struct.new(:domain, :aggregate, :command, :args, :repository, :instance, :transition, :old_state,
49
37
  :result, :correlation, :route, :plan, :strategy, :persistence_outcome, :pending_delegation,
50
38
  :dry_run, :correction_bindings, :outbox_rows, :invocation)
@@ -57,42 +45,18 @@ module Hecks
57
45
  @rules = rules
58
46
  end
59
47
 
60
- # `dry_run:` — Dispatcher#dry_run?'s own entry point. Every step up
61
- # through enforce_ensures/enforce_invariants runs exactly as a real
62
- # dispatch would (givens checked, mutations applied to `ctx.instance`
63
- # in memory); `step_save`/`step_emit` are the only two that read this
64
- # flag, each skipping its own real work — see their own comments.
65
- # Retries the whole method body on `StaleWrite` — a fresh `ctx`, a
66
- # fresh `step_hydrate` re-reading current state, so `enforce_givens`
67
- # re-evaluates against reality rather than the snapshot that just
68
- # went stale. See `MAX_STALE_WRITE_RETRIES`/`Runtime::StaleWrite`
69
- # for why exhaustion is a pathological-contention signal, not the
70
- # expected shape of a two-writer race.
71
- #
72
- # `invocation` — the `Runtime::Invocation` `Dispatcher` built for this
73
- # call. `ctx.args` is `invocation.to_args` (the same Hash routing
74
- # always handed this method), `ctx.route` its `target`.
48
+ # Dispatches `command` against `aggregate` through the declared step
49
+ # order, retrying once per concurrent-write conflict.
75
50
  #
76
51
  # @param domain [String, Symbol] the domain `aggregate` belongs to
77
52
  # @param aggregate [Bluebook::Aggregate] the aggregate the command acts on
78
53
  # @param command [Class] the command class (`Bluebook::Command` subclass) to dispatch
79
- # @param invocation [Runtime::Invocation] the invocation `Dispatcher` built for
80
- # this call
81
- # @param correlation [Hash{Symbol => Object}, nil] correlation head => value,
82
- # stamped on every emitted event when a saga leg causes this dispatch; nil
83
- # otherwise
84
- # @param dry_run [Boolean] whether to run every step through validation without
85
- # saving, emitting or enqueueing
86
- # @return [Array(Runtime::Instance, Array<Runtime::Event>,
87
- # Runtime::DependencyPlanning::Plan, Ports::Persistence::Execution,
88
- # Array<Runtime::Outbox::Row>)] the settled instance, emitted events,
89
- # execution plan, persistence outcome and outbox rows — the last
90
- # three nil on a dry run, which skips save/emit/outbox
91
- # @raise [StandardError] any class in `Runtime::DOMAIN_REFUSALS` when a
92
- # given/ensures/invariant/authorization/admissibility rule refuses
93
- # @raise [Runtime::StaleWrite] if concurrent writers beat this one through every
94
- # retry (`MAX_STALE_WRITE_RETRIES`)
95
- # @raise [Runtime::WiringError] if the aggregate's repository cannot be resolved
54
+ # @param invocation [Runtime::Invocation] the invocation built for this call
55
+ # @param correlation [Hash, nil] saga correlation stamped on emitted events, if any
56
+ # @param dry_run [Boolean] validate every step without saving, emitting or enqueueing
57
+ # @return [Array] the settled instance, events, plan, persistence outcome, and outbox rows
58
+ # @raise [StandardError] a domain refusal (Runtime::DOMAIN_REFUSALS) when a rule refuses
59
+ # @raise [Runtime::StaleWrite, Runtime::WiringError] every retry loses, or resolve fails
96
60
  def call(domain, aggregate, command, invocation, correlation = nil, dry_run: false)
97
61
  args = invocation.to_args
98
62
  route = invocation.target
@@ -104,11 +68,8 @@ module Hecks
104
68
  ctx.route = route
105
69
  ctx.dry_run = dry_run
106
70
  ctx.plan = DependencyPlanning::Analyzer.call(aggregate: aggregate, command: command)
107
- # **Resolved here, once, before hydration** — `Registry#repository`
108
- # memoizes, so this and `step_hydrate`'s own read of `ctx.repository`
109
- # (no second fetch there) always name the same instance;
110
- # the isolation decision below (lock vs. CAS+retry) needs the
111
- # repository's capabilities before a single step runs.
71
+ # Resolved once here, before hydration: `Registry#repository` memoizes,
72
+ # and the isolation decision below needs its capabilities up front.
112
73
  ctx.repository = @registry.repository(domain, aggregate)
113
74
  lock_id = Identity.best_effort(aggregate, args, route, reference_key: reference_key(command))
114
75
  run_dispatch_order_with_isolation(DISPATCH_ORDER, ctx, lock_key_id: lock_id)
@@ -122,14 +83,9 @@ module Hecks
122
83
 
123
84
  private
124
85
 
125
- # **A no-op, and untraced** — Vocabulary::AggregateDispatchOrder's
126
- # decode_arguments. Routing (`Runtime::Routing`) has already handed
127
- # `call` a decoded argument hash by the time any step runs, so there is
128
- # nothing left to decode here yet; like a conditional step that does
129
- # not fire, it records nothing in `trace`. Declared so the Rust
130
- # kernel's generated step enum carries the step its generated decoder
131
- # will move into (roadmap D2), and so a typed Invocation (I2) has a
132
- # step to be consumed at.
86
+ # No-op: `Routing` has already handed `call` a decoded argument hash,
87
+ # so there is nothing left to decode here yet. Kept as a step so the
88
+ # generated step enum has a slot to move the real decoder into later.
133
89
  def step_decode_arguments(_ctx); end
134
90
 
135
91
  def step_refuse_unknown_arguments(ctx)
@@ -171,14 +127,9 @@ module Hecks
171
127
 
172
128
  def step_enforce_givens(ctx)
173
129
  step(:enforce_givens) do
174
- # Structural, before the declared givens — the same ordering
175
- # NotFound/AlreadyExists already get at hydration: "does the
176
- # fact this command's corrects names even exist" is not a
177
- # domain rule an author wrote, it is a precondition for the
178
- # domain rules to mean anything at all. Also locates the
179
- # correction target itself, if `as:` named one — carried on
180
- # `ctx` so `step_enforce_ensures` (the settled-record half)
181
- # can bind the same name too, not just this pre-mutation half.
130
+ # Structural check before the declared givens (same ordering as
131
+ # NotFound/AlreadyExists at hydration). Also locates the correction
132
+ # target, if `as:` named one, so `step_enforce_ensures` can reuse it.
182
133
  ctx.correction_bindings = @rules.enforce_correction_target(ctx.instance, ctx.aggregate, ctx.command, domain: ctx.domain)
183
134
  @rules.enforce_givens(ctx.instance, ctx.command, ctx.args, domain: ctx.domain,
184
135
  declaring: ctx.aggregate, parent: ctx.instance, correction: ctx.correction_bindings)
@@ -220,61 +171,20 @@ module Hecks
220
171
  step(:advance_lifecycle) { ctx.instance[ctx.aggregate.lifecycle.field] = ctx.transition.target }
221
172
  end
222
173
 
223
- # The synchronous cousin of a policy's own `trigger` — see
224
- # `CommandBuilder#delegates_to`'s own comment for the full reasoning.
225
- # Runs after this command's own mutations/lifecycle (so a delegating
226
- # command could in principle still guard with its own `given`s first,
227
- # though the real use in `domain/chess` declares none) and before
228
- # `enforce_ensures`/`enforce_invariants`/`save`, so a refusal here
229
- # raises a real, unrescued exception and nothing from either side —
230
- # this command's own state, the target element's — has been saved
231
- # yet. `ctx.instance` is the same in-memory record `step_hydrate`
232
- # loaded and `step_save` will persist; `EntityElement.locate_chain`
233
- # mutates it in place exactly the way `EntityInterpreter`'s own
234
- # `step_locate_element`/`step_apply_mutations` mutate their own
235
- # freshly-loaded copy — the only difference is which already-in-
236
- # memory record gets handed in.
237
- #
238
- # Reimplements the entity command pipeline's own order (givens,
239
- # transition, mutations, ensures, emit) inline, deliberately — see
240
- # the comment above on why this must run strictly between this
241
- # command's own mutations and its ensures/invariants/save. Splitting
242
- # it would scatter that exact ordering across method boundaries and
243
- # force threading element/view/transition/old_element/settled
244
- # through as parameters — the `with:` bug documented just below is
245
- # exactly the kind of ordering/plumbing mistake that shape invites.
246
- # rubocop:disable-next Metrics/AbcSize
174
+ # The synchronous cousin of a policy's own `trigger` (see
175
+ # `CommandBuilder#delegates_to`). Runs between this command's own
176
+ # mutations and its ensures/invariants/save, so a refusal here leaves
177
+ # nothing committed on either side. Reimplements the entity pipeline
178
+ # (givens, transition, mutations, ensures, emit) inline, to keep that
179
+ # exact ordering in one place rather than threading state through
180
+ # method boundaries as parameters.
247
181
  def step_delegate_to_entity(ctx)
248
182
  delegation = ctx.command.mutations.find { |mutation| mutation.op == :delegate }
249
183
  return unless delegation
250
184
 
251
185
  step(:delegate_to_entity) do
252
- entity_name, _dot, command_name = delegation.target.to_s.rpartition(".")
253
- entity = ctx.aggregate.entities.find { |e| e.hecks_name == entity_name } ||
254
- raise(WiringError, "#{ctx.command.hecks_name} delegates_to #{entity_name}." \
255
- "#{command_name}, but #{ctx.aggregate.hecks_name} has no " \
256
- "entity named #{entity_name.inspect}")
257
- target_command = entity.command(command_name) ||
258
- raise(WiringError, "#{ctx.command.hecks_name} delegates_to " \
259
- "#{entity_name}.#{command_name}, which " \
260
- "#{entity_name} declares no such command")
261
-
262
- # `with:` remaps, it does not enumerate — starting from a copy
263
- # of this command's own already-resolved args (`ctx.args`) and
264
- # overlaying the explicit mapping on top means ambient context
265
- # the caller never had to think about (the aggregate's own
266
- # identity, addressed the ordinary way to reach `MoveKnight` at
267
- # all) flows through to the target untouched, the same as it
268
- # always would for a caller dispatching the entity command
269
- # directly. Confirmed necessary, not a defensive guess: a real
270
- # downstream domain's own AdvancePly-on-Moved policy silently
271
- # failed to re-locate its own aggregate (`reaction_log`: "no
272
- # Game with label.value ..."), because the emitted event's
273
- # payload — built from `target_args` alone — never carried
274
- # `label` at all when `with:` named only `id`/`to`.
275
- target_args = ctx.args.merge(
276
- delegation.source.to_h { |target_key, source_key| [target_key.to_sym, ctx.args[source_key]] }
277
- )
186
+ entity, target_command, command_name = resolve_delegation_target(ctx, delegation)
187
+ target_args = mapped_and_gated_delegation_args(ctx, delegation, entity, target_command)
278
188
 
279
189
  element = EntityElement.locate_chain(ctx.aggregate, [entity], ctx.instance, target_args, command_name)
280
190
  view = Instance.new(aggregate: entity, id: EntityElement.element_identity(entity, element).to_s, state: element)
@@ -292,18 +202,52 @@ module Hecks
292
202
  settled = Instance.new(aggregate: entity, id: view.id, state: element)
293
203
  @rules.enforce_ensures(settled, target_command, target_args, old: old_element, domain: ctx.domain, parent: ctx.instance)
294
204
 
295
- # Not emitted here — C7.2 (docs/semantics/bluebook-semantics.md):
296
- # a refused command records nothing, and the parent's own
297
- # `ensures`/`enforce_invariants`/`save` steps still run after
298
- # this one. The target's emission is parked and performed by
299
- # `step_emit`, after the parent committed — where every other
300
- # command's events are emitted too. (Without parking it here, the
301
- # entity leg's events would be on the event log and in the adapter
302
- # before the parent could refuse.)
205
+ # Not emitted here — C7.2: a refused command records nothing, and
206
+ # the parent's own ensures/invariants/save steps still run after
207
+ # this one. Parked and emitted by `step_emit`, after the parent
208
+ # commits, alongside every other command's events.
303
209
  ctx.pending_delegation = [target_command, target_args]
304
210
  end
305
211
  end
306
212
 
213
+ # The entity and command a `delegates_to` mutation names, resolved once so
214
+ # `step_delegate_to_entity` can read them as plain locals.
215
+ def resolve_delegation_target(ctx, delegation)
216
+ entity_name, _dot, command_name = delegation.target.to_s.rpartition(".")
217
+ entity = ctx.aggregate.entities.find { |e| e.hecks_name == entity_name } ||
218
+ raise(WiringError, "#{ctx.command.hecks_name} delegates_to #{entity_name}." \
219
+ "#{command_name}, but #{ctx.aggregate.hecks_name} has no " \
220
+ "entity named #{entity_name.inspect}")
221
+ target_command = entity.command(command_name) ||
222
+ raise(WiringError, "#{ctx.command.hecks_name} delegates_to " \
223
+ "#{entity_name}.#{command_name}, which " \
224
+ "#{entity_name} declares no such command")
225
+ [entity, target_command, command_name]
226
+ end
227
+
228
+ # Builds the target command's own args, then runs the same argument gate
229
+ # `EntityInterpreter` runs before a direct dispatch of that command — evaluated
230
+ # against the target command's own declared attributes and the already
231
+ # `with:`-mapped args, not the delegating command's. Without this, a `with:`
232
+ # mapping that omits one of the target's required attributes would silently
233
+ # mutate and persist state that was never validated at all.
234
+ # `extra_identity_heads:` exempts the entity's own identity field (e.g. `id`),
235
+ # which locates the element but is never a declared attribute.
236
+ def mapped_and_gated_delegation_args(ctx, delegation, entity, target_command)
237
+ # `with:` remaps, it does not enumerate — starting from a copy of this command's
238
+ # own resolved args and overlaying the explicit mapping means ambient context the
239
+ # caller never named (the aggregate's own identity) still flows through to the
240
+ # target, the same as a direct dispatch of the entity command would get.
241
+ target_args = ctx.args.merge(
242
+ delegation.source.to_h { |target_key, source_key| [target_key.to_sym, ctx.args[source_key]] }
243
+ )
244
+
245
+ refuse_unknown_arguments(ctx.domain, ctx.aggregate, target_command, target_args,
246
+ extra_identity_heads: entity.identity_heads)
247
+ refuse_absent_arguments(target_command, target_args)
248
+ normalize_args(ctx.aggregate, target_command, target_args)
249
+ end
250
+
307
251
  def step_enforce_ensures(ctx)
308
252
  step(:enforce_ensures) do
309
253
  @rules.enforce_ensures(ctx.instance, ctx.command, ctx.args, old: ctx.old_state,
@@ -315,33 +259,10 @@ module Hecks
315
259
  step(:enforce_invariants) { @rules.enforce_invariants(ctx.instance, ctx.aggregate, domain: ctx.domain) }
316
260
  end
317
261
 
318
- # `dry_run:` skips the write half of this step — see Dispatcher#
319
- # dry_run?'s own comment — but not `resolve_state_references`.
320
- # BUG#127: that check is validation, not persistence — it asks
321
- # whether the settled in-memory state names a reference target that
322
- # actually exists, the same question a real dispatch answers before
323
- # it ever writes anything. Skipping it under `dry_run:` made
324
- # `dry_run?` disagree with what a real dispatch immediately after it
325
- # would do: it answered `true` ("would succeed") for a command whose
326
- # real dispatch refuses with NotFound. Only the persist/raise-on-
327
- # conflict tail is genuinely persistence-only and stays behind the
328
- # early return.
329
- #
330
- # BUG#132 — a second validation-not-persistence check hid in that
331
- # same persist/raise-on-conflict tail: `persist_instance`'s own
332
- # ATOMIC_PUT branch (below) is where `hydrate_complete_state`'s
333
- # comment says a `creates?` command's duplicate check is
334
- # deliberately deferred to, for a strategy this fast — a read
335
- # (`repository.find`) any earlier, before the real write, would be
336
- # exactly the extra read `insert_only:` exists to avoid paying on
337
- # every real dispatch. But that means the check never ran at all under
338
- # `dry_run:` — not eagerly (hydration skips it for this exact
339
- # strategy, on purpose) and not deferred (this whole branch returns
340
- # first). `Roster::Roster.Open` against an already-open name is
341
- # this shape: `dry_run?` answered `true` for a real dispatch
342
- # immediately after it that refuses `AlreadyExists`. Under
343
- # `dry_run:` there is no write to race, so paying for that one read
344
- # is safe here — and only here.
262
+ # `dry_run:` skips persistence, but not `resolve_state_references` or
263
+ # the ATOMIC_PUT duplicate check (`check_dry_run_creates_duplicate`) —
264
+ # both are validation, not persistence, and a real dispatch would
265
+ # refuse on either before ever writing.
345
266
  def step_save(ctx)
346
267
  step(:save) { @rules.resolve_state_references(ctx.domain, ctx.aggregate, ctx.instance.state) }
347
268
 
@@ -357,11 +278,9 @@ module Hecks
357
278
  end
358
279
  end
359
280
 
360
- # See `step_save`'s own BUG#132 comment: the only path, real or dry,
361
- # able to catch a `creates?` command reusing an already-occupied
362
- # identity when `strategy` is `ATOMIC_PUT` — `hydrate_complete_
363
- # state` deliberately skips this exact case (its own comment), and
364
- # a dry run never reaches `persist_instance`'s matching branch.
281
+ # The only path, real or dry, that catches a `creates?` command reusing
282
+ # an occupied identity under ATOMIC_PUT — `hydrate_complete_state`
283
+ # deliberately defers this exact check to here.
365
284
  def check_dry_run_creates_duplicate(ctx)
366
285
  return unless ctx.strategy == DependencyPlanning::ATOMIC_PUT && ctx.command.creates?
367
286
  return unless ctx.repository.find(ctx.instance.id)
@@ -374,23 +293,15 @@ module Hecks
374
293
 
375
294
  def persist_instance(ctx)
376
295
  if ctx.strategy == DependencyPlanning::ATOMIC_PUT
377
- # A second creation is not a fresh one — see
378
- # hydrate_complete_state's own comment; the
379
- # same refusal, on the same terms, for the
380
- # complete-state path. `insert_only:` asks the
381
- # adapter to decide and refuse atomically
382
- # (never writing a `creates?` command over an
383
- # identity that already names a record) rather
384
- # than this interpreter reading the record
385
- # first to check — a `repository.find` before
386
- # every atomic_put would be exactly the read
387
- # this strategy exists to skip.
296
+ # `insert_only:` asks the adapter to refuse atomically rather than
297
+ # this interpreter reading the record first to check — a
298
+ # `repository.find` before every atomic_put would be exactly the
299
+ # read this strategy exists to skip.
388
300
  ctx.repository.atomic_put(ctx.instance, insert_only: ctx.command.creates?)
389
301
  else
390
- # `expected_version:` is `ctx.instance.version` — nil for a
391
- # brand-new record (never read from storage) or when the
392
- # repository isn't CAS-capable, either of which falls straight
393
- # through to a plain, unconditional save inside `AppendOnly#save`.
302
+ # `expected_version:` is nil for a brand-new record or a
303
+ # non-CAS repository, either of which falls through to a
304
+ # plain, unconditional save inside `AppendOnly#save`.
394
305
  ctx.repository.save(ctx.instance, expected_version: ctx.instance.version)
395
306
  end
396
307
  end
@@ -402,10 +313,9 @@ module Hecks
402
313
  identity: identity_reading(ctx.aggregate),
403
314
  offered: Rendering.describe(ctx.instance.id)))
404
315
  elsif ctx.persistence_outcome.status == :stale
405
- # Not a `RefusalWording.render` call — this is not a declared
406
- # vocabulary refusal, just a plain, informative message. See
407
- # `Runtime::StaleWrite`'s own comment: caught by `#call`'s
408
- # retry loop, re-raised only once retries are exhausted.
316
+ # Not a declared vocabulary refusal, just a plain, informative
317
+ # message — caught by `#call`'s retry loop, re-raised only once
318
+ # retries are exhausted.
409
319
  raise(StaleWrite,
410
320
  "#{ctx.command.hecks_name} on #{ctx.aggregate.hecks_name} " \
411
321
  "(#{identity_reading(ctx.aggregate)}: #{Rendering.describe(ctx.instance.id)}) lost a race — " \
@@ -413,28 +323,12 @@ module Hecks
413
323
  end
414
324
  end
415
325
 
416
- # The one-time, synchronous half of `projects` (S12, ADR 0025) —
417
- # `RebuildSweep` (`runtime/rebuild_sweep.rb`) is deliberately the
418
- # only thing that keeps a projected field current against a
419
- # target that changes after this record was written — no reactive
420
- # `Policy#for_each` keeping it live in real time, that stays
421
- # deferred, same as that file's own header explains. But without
422
- # some synchronous population, a projected field never gets an
423
- # initial value at all until an operator remembers to run a
424
- # sweep by hand — every acting command reading it (`given
425
- # ("customer is active") { customer_status == "active" }`, say)
426
- # would refuse a freshly created, genuinely active record for no
427
- # real reason, which is not the eventual-consistency tradeoff the
428
- # ADR accepts, just a bug. So: every time a record with `projects`
429
- # fields is about to save — creating or acting, either can be the
430
- # first time a referenced record resolves — read each one once,
431
- # here, using the exact same `RebuildSweep.remote_value` a sweep
432
- # itself would compute. This is still eventually consistent in
433
- # the sense the ADR means: a change on the target side after this
434
- # save still needs a sweep to reach here. It is only ever
435
- # synchronous with this record's own write, never a live read
436
- # triggered by a `given`/`ensures`/`invariant` mid-dispatch — the
437
- # boundary rule those enforce holds exactly as before.
326
+ # The one-time, synchronous half of `projects` (ADR 0025); `RebuildSweep`
327
+ # is what keeps a projected field current afterward. Without seeding it
328
+ # here, a freshly created record would read a nil projected field until
329
+ # an operator ran a sweep, refusing commands that depend on it for no
330
+ # real reason. Uses the same `RebuildSweep.remote_value` a sweep
331
+ # computes, and runs only at save time, never as a live read mid-dispatch.
438
332
  def seed_projected_fields(ctx)
439
333
  return if ctx.aggregate.projected_fields.empty?
440
334
 
@@ -446,16 +340,11 @@ module Hecks
446
340
  end
447
341
  end
448
342
 
449
- # A delegating command emits nothing of its own (`CommandBuilder#build`'s
450
- # own guard refuses declaring `emits` alongside `delegates_to`) — its
451
- # result is the target entity command's own `emits`, parked by
452
- # `step_delegate_to_entity` and emitted here, after save (C7.2), not
453
- # a second, empty call into `@rules.emit` for a command with no
454
- # announced events at all.
455
- #
456
- # `dry_run:` skips this too, same reasoning as `step_save` — nothing
457
- # was committed, so `ctx.result` stays nil and `Dispatcher#dry_run?`
458
- # never reads it (its own return value is just whether this raised).
343
+ # A delegating command emits nothing of its own; its result is the
344
+ # target entity command's own `emits`, parked by
345
+ # `step_delegate_to_entity` and emitted here, after save (C7.2).
346
+ # `dry_run:` skips this too — nothing was committed, so `ctx.result`
347
+ # stays nil.
459
348
  def step_emit(ctx)
460
349
  return if ctx.dry_run
461
350
 
@@ -500,61 +389,12 @@ module Hecks
500
389
  found.dup
501
390
  end
502
391
 
503
- # Wave 8 (equivalence-gap plan, item 1.6) — not done, and this
504
- # comment now says precisely how far it got, corrected from an
505
- # earlier version of itself that briefly (same PR, never released)
506
- # claimed the inventory was empty and deleted this method outright.
507
- # A full corpus audit (`DependencyPlanning::Analyzer.call` against
508
- # every `creates?`-true command in all 5 example domains — banking,
509
- # pizzas, chess, compliance, roster) found and fixed 4 real
510
- # authoring bugs (`Statement.Generate`, `CreatePizza`, `Chess::
511
- # Game.Start`, `Roster.Open` — each declared an attribute and
512
- # never `sets` it, so the field silently stayed nil on every
513
- # created record regardless of what a caller sent), plus a real
514
- # `DependencyPlanning::Analyzer` bug for entity-owned commands
515
- # (`root_aggregate:`, that class's own header) that surfaced one
516
- # more live corpus bug of its own (`payment_cards.bluebook`'s own
517
- # `Withdrawal.Dispute`, which never actually checked whether the
518
- # card was retired) — all real, all kept.
519
- #
520
- # Deleting this method on that basis turned out to be wrong,
521
- # caught by running the full suite rather than trusting the
522
- # audit's own scope: the 5 example domains are nowhere near the
523
- # whole inventory of `creates?`-true commands this fallback
524
- # actually carries. Dozens of separate, purpose-built spec
525
- # fixtures across the suite (`spec/fixtures/*.bluebook`, and
526
- # inline `Hecks.bluebook` blocks declared directly inside
527
- # individual spec files — governance, mutation ops, ports,
528
- # routing, tenant isolation, sagas, and more) declare their own
529
- # small `creates?`-true commands the same incomplete way, and
530
- # rely on this exact fallback to create anything at all. Deleting
531
- # it produced 218 failures across specs with nothing to do with
532
- # Wave 8's own subject — confirmed, not guessed, by actually
533
- # running `bundle exec rspec` after the deletion, not merely by
534
- # extrapolating from the one audited inventory. `spec/fixtures/
535
- # till.bluebook`'s own `Till.OpenTill` (missing `sets :number`,
536
- # the identical bug shape as the 4 fixed above) was fixed
537
- # alongside the four real corpus ones as one instance of this — but
538
- # it was one of many, not the last one, and finding the rest is
539
- # real, separate, much larger follow-up work this pass does not
540
- # attempt: a suite-wide audit of every declared bluebook fixture,
541
- # not just the 5 example domains the plan's own text named.
542
- #
543
- # Transitional compatibility for live source that has not yet
544
- # acquired explicit effects, same as it always was — deliberately
545
- # isolated from the normal routing and planning path so
546
- # `reference_to` does not choose how a migrated command hydrates
547
- # or persists. A real, future Wave 8 removes this once that wider
548
- # inventory is empty, not before.
549
- #
550
- # `ctx.plan.complete_state?` already claimed every command whose
551
- # plan is fully resolved in the two branches above `step_hydrate`
552
- # tries first, so reaching this check already means the plan is
553
- # incomplete — an un-migrated command still routes here on
554
- # `creates?` alone, the same as the old `hydrate` did, regardless
555
- # of whether it happens to have any mutations (`write_set`).
556
- # Requiring an empty write_set here refused every un-migrated
557
- # creating command that sets even one field.
392
+ # Transitional compatibility for a command that has not yet acquired
393
+ # explicit effects — isolated from the normal routing/planning path so
394
+ # `reference_to` does not choose how a migrated command hydrates. An
395
+ # un-migrated command routes here on `creates?` alone, regardless of
396
+ # whether it has any mutations; requiring an empty write_set here would
397
+ # wrongly exclude one that sets fields.
558
398
  def legacy_implicit_creation?(ctx)
559
399
  ctx.route.nil? && ctx.command.creates?
560
400
  end
@@ -587,19 +427,10 @@ module Hecks
587
427
  aggregate: aggregate.hecks_name,
588
428
  identity: identity_reading(aggregate)))
589
429
 
590
- # A second creation is not a fresh one — `creates?` on an identity
591
- # a record already exists under refuses (`AlreadyExists`) rather
592
- # than silently overwriting it, the same refusal `hydrate_prior_
593
- # or_initial`'s own body gives for its own complete-but-state-
594
- # dependent case, below. Only when `strategy` will not be ATOMIC_PUT:
595
- # an atomic-put-capable adapter enforces this itself, atomically,
596
- # via `insert_only:` in step_save (no read here, no race with the
597
- # write) — but `strategy_for` already fell back to a plain `save`
598
- # for an adapter with no atomic_put capability at all (Heki, today),
599
- # and a plain `save` never refuses an overwrite on its own. Skipping
600
- # this check for that case silently dropped the refusal instead of
601
- # deferring it — the very "no such call — no such check" gap Wave
602
- # 8 exists to close everywhere else.
430
+ # `creates?` on an occupied identity refuses (`AlreadyExists`), except
431
+ # under ATOMIC_PUT: that adapter enforces the same refusal itself,
432
+ # atomically, via `insert_only:` in `step_save` — reading here too
433
+ # would race the write for nothing.
603
434
  if command.creates? && strategy != DependencyPlanning::ATOMIC_PUT && repository.find(id)
604
435
  raise(AlreadyExists, RefusalWording.render_site("AlreadyExists", "creating_duplicate",
605
436
  command: command.hecks_name, aggregate: aggregate.hecks_name,
@@ -610,11 +441,9 @@ module Hecks
610
441
  Instance.new(aggregate: aggregate, id: id, args: args)
611
442
  end
612
443
 
613
- # A complete command may still depend on prior state: lifecycle guards
614
- # are the common case. Read once so an existing record is checked against
615
- # its real state; when no record exists, the aggregate's declared defaults
616
- # are the prior state. Completeness, not a reference marker, proves that
617
- # initializing that missing record is safe.
444
+ # A complete command may still depend on prior state (lifecycle guards
445
+ # are the common case) — read once, so an existing record is checked
446
+ # against its real state rather than assumed defaults.
618
447
  def hydrate_prior_or_initial(repository, aggregate, command, args, route)
619
448
  derived = identity_of(aggregate, args)
620
449
  if route && derived && route.aggregate.to_s != derived.to_s
@@ -629,20 +458,10 @@ module Hecks
629
458
  identity: identity_reading(aggregate)))
630
459
  found = repository.find(id)
631
460
 
632
- # A second creation is not a fresh one — see hydrate_complete_
633
- # state's own comment; the same refusal, on the same terms, for
634
- # a complete-but-state-dependent command (one with a `given`
635
- # reading its own prior state, which is what routes here instead
636
- # of hydrate_complete_state). Gated on `command.creates?`: a
637
- # non-creating command's own complete payload legitimately means
638
- # "act on whatever this identity already holds" (`found` is the
639
- # prior state this branch exists to supply), so only a genuine
640
- # creation reusing an already-occupied identity is a duplicate.
641
- # `SafeDepositBox.Rent` is exactly this shape — `given("box is
642
- # vacant")` makes it state-dependent, so without this check a
643
- # second Rent would silently hydrate the existing box as "prior
644
- # state" and refuse for the wrong reason (not vacant) instead of
645
- # the right one (already exists).
461
+ # Same refusal as `hydrate_complete_state`, for a complete-but-state-
462
+ # dependent command (one with a `given` on its own prior state).
463
+ # Gated on `creates?`: a non-creating command's complete payload just
464
+ # means "act on whatever this identity already holds".
646
465
  if found && command.creates?
647
466
  raise(AlreadyExists, RefusalWording.render_site("AlreadyExists", "creating_duplicate",
648
467
  command: command.hecks_name, aggregate: aggregate.hecks_name,
@@ -653,10 +472,9 @@ module Hecks
653
472
  found ? found.dup : Instance.new(aggregate: aggregate, id: id, args: args)
654
473
  end
655
474
 
656
- # The join, the dig, and the reading — all shared with `EntityInterpreter`
657
- # now, in `Runtime::Identity`, rather than kept as two copies that could
658
- # only ever drift. See that module for the reasoning ; these three stay
659
- # here, at the old names, purely so nothing below has to change.
475
+ # Shared with `EntityInterpreter`, in `Runtime::Identity`, rather than
476
+ # kept as two copies that could only ever drift; these three stay here,
477
+ # under their old names, so nothing below has to change.
660
478
  def identity_of(aggregate, args) = Identity.of(aggregate, args)
661
479
  def identity_from(aggregate, args, key) = Identity.from(aggregate, args, key)
662
480
  def identity_reading(construct) = Identity.reading(construct)