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
@@ -2,11 +2,8 @@ require_relative "word_gate"
2
2
  module Hecks
3
3
  module Bluebook
4
4
  module DSL
5
- # The `command "Name" do ... end` receiver — collects a command's
6
- # `role`/`goal`/`given`/`ensures`/`sets`/`emits`/`delegates_to`/
7
- # `corrects` declarations, resolves implicit attributes a bare `sets
8
- # :field` or `append:` self-reference imports from the owner
9
- # (`#resolve_implicit_attributes!`), and builds the final `Command`.
5
+ # The `command "Name" do ... end` receiver: collects role/goal/given/ensures/sets/
6
+ # emits/delegates_to/corrects declarations and builds the final `Command`.
10
7
  class CommandBuilder
11
8
  GRAMMAR_CONTEXT = "Command".freeze
12
9
 
@@ -14,34 +11,11 @@ module Hecks
14
11
  include RuleReference
15
12
  include WordGate
16
13
 
17
- # Vendored addition, not (yet) upstream hecks (migration plan
18
- # task 4): a sentinel for "this keyword was never passed", distinct
19
- # from Ruby's own nil/false. `then_set`'s original default (`to:
20
- # nil`) could not tell "not given" apart from "given, and the
21
- # value is false" — `to || from` silently treats `to: false` the
22
- # same as an absent `to:` and falls through to `from` (also
23
- # absent), so `then_set :accepted, to: false` raised "names no
24
- # operation" for the one value most likely to be written that way
25
- # (a boolean flip). Confirmed real, live: an external project's
26
- # dream_interpretation.bluebook (`then_set :accepted, to: false`)
27
- # and transparency.bluebook (`then_set :always, to: false`). TODO
28
- # upstream via bin/evolve.
14
+ # Sentinel for "this keyword was never passed" — distinct from Ruby's own
15
+ # nil/false, so `to: false` doesn't get treated as absent.
29
16
  UNSET = Object.new.freeze
30
17
  private_constant :UNSET
31
18
 
32
- # @param name [String] the command's name, as written after `command`
33
- # @param owner [String, nil] name of the aggregate or entity this command belongs to
34
- # @param from [String, Symbol, Array<String, Symbol>, nil] the lifecycle state(s) this
35
- # command guards from; nil admits from any state
36
- # @param named_givens [Hash{String => Bluebook::Given}] the owner's own given pool, for
37
- # bare `given` references to resolve against
38
- # @param owner_attributes [Array<Bluebook::Attribute>] the owner's own attributes, for
39
- # implicit `sets`/`state` resolution
40
- # @param owner_constructs [Array<Bluebook::ValueObject, Bluebook::Entity>] the owner's
41
- # own value objects and entities, for an `append:` element type to resolve against
42
- # @param entity_shared_givens [Hash{String => Bluebook::Given}] a sibling piece's own
43
- # entity-level given pool, for a piece-owned command's bare reference; empty for an
44
- # aggregate-owned command
45
19
  def initialize(name, owner: nil, from: nil, named_givens: {}, owner_attributes: [], owner_constructs: [],
46
20
  entity_shared_givens: {})
47
21
  @name = name
@@ -70,24 +44,8 @@ module Hecks
70
44
  end
71
45
  end
72
46
 
73
- # A command carries one responsibility role — the language never
74
- # declared an or between two roles, so a second `role` call would
75
- # otherwise silently win while the first still looked declared,
76
- # exactly the failure mode `reference_to`'s own duplicate guard
77
- # (below) already exists to prevent for a command's root.
78
- #
79
47
  # Sets the command's one responsibility role, refusing a second declaration.
80
48
  #
81
- # Answers the `role` word through the table's `calls:` column —
82
- # item #13's full metaprogrammed dispatch
83
- # (slice 4). This is a uniqueness gate on prior state (`@role`
84
- # already set), not a pure function of the argument's own value —
85
- # a genuinely different shape than a plain fill, so it stays
86
- # hand-written and is reached through `calls:` like `attribute`
87
- # was in slice 3. Bootstrap-reachable (every self-hosted command
88
- # declares a role), so also named in
89
- # `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`.
90
- #
91
49
  # @param value [String, Symbol] the role's name
92
50
  # @return [Object] `value` as stored
93
51
  # @raise [Bluebook::DSL::Malformed] if a role is already declared
@@ -110,14 +68,6 @@ module Hecks
110
68
 
111
69
  # Names where a concept adopted from a canonical source came from.
112
70
  #
113
- # See `AggregateBuilder#provenance_impl`'s own comment — identical shape,
114
- # one level down.
115
- #
116
- # Answers the `provenance` word through the table's `calls:`
117
- # column — item #13's full metaprogrammed
118
- # dispatch (slice 4c). Bootstrap-reachable, in
119
- # `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`.
120
- #
121
71
  # @param from [Object] the canonical source, captured exactly as written
122
72
  # @return [Object] `from` as stored
123
73
  def provenance_impl(from:) = @provenance = from
@@ -125,17 +75,6 @@ module Hecks
125
75
  # Declares the aggregate this command acts on (with no `as:`), or a cross-reference to
126
76
  # another aggregate (with `as:`).
127
77
  #
128
- # `optional:` rides here as well as on a plain attribute : `as:` makes a
129
- # reference into a named argument, and a named argument is exactly the kind
130
- # of fact that may or may not be given. The meta-domain's Verb.Declare
131
- # points at the Entity a command belongs to — and most commands belong to no
132
- # entity at all.
133
- #
134
- # Answers the `reference_to` word through the table's `calls:`
135
- # column — item #13's full metaprogrammed
136
- # dispatch (slice 4b). Bootstrap-reachable, in
137
- # `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`.
138
- #
139
78
  # @param type [Module, Symbol, String] the referenced aggregate, written as a bare
140
79
  # constant
141
80
  # @param as [Symbol, nil] the attribute's name for a cross-reference; nil declares the
@@ -147,16 +86,10 @@ module Hecks
147
86
  # cross-reference) `as` is already declared
148
87
  def reference_to_impl(type, as: nil, optional: false)
149
88
  demodulised = Naming.demodulise(type)
150
- # moved to the language: given "a command names what it acts on", on Verb.ActsOn
151
-
152
- # `as:` means "a named attribute", not "the root I act on" — so a command
153
- # can point at another instance of its own kind. Without this,
154
- # `reference_to Aggregate, as: :points_at` on a command owned by Aggregate
155
- # read as a second self-reference and was refused as naming two roots,
156
- # which is how the meta-domain's own Aggregate.Reference could not say the
157
- # one thing it exists to say. Transfer has said
158
- # `reference_to Account, as: :source` for as long as banking has existed;
159
- # this is the same sentence when the target happens to be the owner.
89
+
90
+ # `as:` names an attribute, not "the root I act on" — without this check, a
91
+ # command referencing its own aggregate type via `as:` would misread as a
92
+ # second self-reference and be refused.
160
93
  return cross_reference(demodulised, as, optional: optional) if as || demodulised.to_s != @owner.to_s
161
94
 
162
95
  if @references
@@ -180,21 +113,7 @@ module Hecks
180
113
  # Declares a precondition this command requires, or references one the owning aggregate
181
114
  # (or a sibling piece) already declared.
182
115
  #
183
- # No block is a reference, not a fresh declaration (S10, ADR
184
- # 0025 — "a precondition shared across commands is declared
185
- # once. An aggregate declares it by name and commands
186
- # reference it"): the same word, the same shape
187
- # (`AggregateBuilder#given_impl`, block required there), so naming a
188
- # precondition back is spelled exactly like declaring one would
189
- # be, minus the block — one idea, one word, never a second
190
- # spelling ("requires"/"precondition") for "use the one already
191
- # named". Resolved against whatever the owning aggregate has
192
- # declared so far — see `AggregateBuilder#command_impl`'s own
193
- # comment on why that means declaration order matters here.
194
- #
195
- # Answers the `given` word through the table's `calls:` column —
196
- # item #13's full metaprogrammed dispatch
197
- # (slice 4b), same reasoning as `reference_to_impl` above.
116
+ # No block given means "use the one already declared" rather than a fresh rule (ADR 0025).
198
117
  #
199
118
  # @param description [String] the rule's description; also the name the owning
200
119
  # aggregate's rule is referenced by when no block is given
@@ -206,23 +125,15 @@ module Hecks
206
125
  def given_impl(description, &predicate)
207
126
  return reference_named_given(description) unless predicate
208
127
 
209
- # moved to the language: given "a rule says what it means", on Verb.Rule
210
-
211
128
  @givens << build_rule(Given, description, predicate, owner_name: @name, word: "given",
212
129
  extraction_failure: "its source could not be read, so no other runtime could ever evaluate it")
213
130
  end
214
131
 
215
132
  private
216
133
 
217
- # Primitive 1 (RuleReference#resolve_hash_chain) — first this
218
- # command's own owner (as always), then — only for a piece-owned
219
- # command, where it is real — a sibling piece's own entity-level
220
- # declaration under the same aggregate (`@entity_shared_givens`,
221
- # threaded from `EntityBuilder#given`'s own write-through).
222
- # "customer is active" declared once on `Visit`, referenced bare
223
- # by `KeyIssuance.Return` — two different pieces, same aggregate,
224
- # same predicate — is exactly the shape this second pool exists
225
- # for.
134
+ # Checks the command's own owner first, then — for a piece-owned command only —
135
+ # a sibling piece's entity-level givens, since two pieces under the same
136
+ # aggregate can share a precondition declared on just one of them.
226
137
  def reference_named_given(description)
227
138
  verify_resolves_via!("given", "Command", "hash_chain")
228
139
  named = resolve_hash_chain([@named_givens, @entity_shared_givens], description) ||
@@ -239,13 +150,7 @@ module Hecks
239
150
  public
240
151
 
241
152
  # Declares a postcondition, checked against the settled record after the command's own
242
- # mutations apply.
243
- #
244
- # The postcondition — a given for the far side of the mutations,
245
- # evaluated against the settled record with `old` naming the state
246
- # as it stood before them: `ensures("...") { old.balance.cents ==
247
- # balance.cents + amount.cents }`. Same extraction, same Rule
248
- # shape, same refusal form; `EnsuresNotMet` instead of `GivenNotMet`.
153
+ # mutations apply; `old` names the pre-mutation state.
249
154
  #
250
155
  # @param description [String] the rule's description
251
156
  # @yield the predicate body; evaluated for its extracted source, never called directly
@@ -256,121 +161,26 @@ module Hecks
256
161
  extraction_failure: "a postcondition is carried as text, and this one has none")
257
162
  end
258
163
 
259
- # `sets` is the word; `then_set` is the spelling every existing
260
- # bluebook was written under (Syntax::Keyword carries the rename as
261
- # `was:`), and it stays answered here forever — a renamed word's old
262
- # era keeps booting, which is the whole point of the rename column.
263
- #
264
- # Vendored addition, not (yet) upstream hecks: `then_set
265
- # :target, from: :source_field` (an external project, found
266
- # live in body/doctor/bluebook/doctor.bluebook) -- semantically
267
- # identical to `to:` (copy this argument/field into the target),
268
- # different word. TODO upstream via bin/evolve (migration plan
269
- # task 7): decide whether `from:` or `to:` becomes the canonical
270
- # spelling.
271
- #
272
- # Vendored addition, not (yet) upstream hecks (migration plan
273
- # task 4, i106 in-DSL math): `multiply:`/`clamp:` -- per-tick organ
274
- # math (an external project's organ bluebook: strength decays ×0.98,
275
- # weight/strength clamp to [0, 1]), moved into the bluebook itself
276
- # from shell-side awk. `multiply:` mirrors
277
- # increment/decrement's shape exactly (a Numeric amount, applied
278
- # by CommandRules::Arithmetic -- see that file's own comment on
279
- # the matching Float-support widening this required). `clamp:`
280
- # is a genuinely different shape -- its source is always a literal
281
- # `[min, max]` pair, never an argument reference, and it bounds
282
- # the current value rather than combining it with an amount -- so
283
- # it does not reuse `arithmetic`/`arithmetic_value_object` at all;
284
- # see MutationApplier#apply's own `:clamp` branch.
285
- #
286
- # `remove:` -- vendored addition, not (yet) upstream hecks
287
- # (migration plan task 4): the list-removal counterpart to
288
- # `append:` (plan.bluebook's own RemoveDependency/DeactivateSprint
289
- # commands: "the runtime list-remove primitive (then_set remove:)
290
- # drops it from the list element-wise, with no read-modify-write
291
- # -- so a concurrent Add can never be lost"). Matches an element
292
- # by value equality against `mutation.source` (resolved and
293
- # Value-coerced the same way increment/decrement/multiply already
294
- # coerce their own amount -- see MutationApplier#removed).
295
- #
296
- # `sets :field, true` -- vendored addition, not (yet) upstream
297
- # hecks (migration plan task 8): a bare positional literal
298
- # instead of `to:` -- 14 occurrences across hecks_nursury
299
- # (oceanography.bluebook/volcanology.bluebook and others),
300
- # always a boolean shorthand (`sets :deployed, true`, never
301
- # a string/number positional -- checked directly, zero non-
302
- # boolean occurrences of the bare-positional-second-arg shape
303
- # anywhere in the corpus). Folded into `to:` itself rather than
304
- # given its own mutation op -- semantically identical, same
305
- # `UNSET`-sentinel discipline the `to: false` fix already
306
- # established (a positional `false` must read as "set to
307
- # false," not "absent," same as the keyword form). Only applied
308
- # when `to:` itself was not also given, so an explicit `to:`
309
- # keyword always wins over a stray positional.
310
- #
311
- # `sets` is the word (ADR 0025 reverts `then_set` — the grammar
312
- # already declared `sets`, `was: "then_set"`, and 143 of 143 live
313
- # call sites are `then_set`, so this method was the one thing
314
- # still backwards). `to:` is omittable when it would only repeat
315
- # the target — `sets :number` alone already means `to: :number`
316
- # — and the redundant explicit spelling is refused outright
317
- # (principle 1, "one idea, one spelling": `sets :number, to:
318
- # :number` says nothing `sets :number` doesn't). `from:` — a
319
- # pure synonym for `to:` the language's own refusal message had
320
- # already forgotten about — is gone; write `to:`.
321
- # The op each kwarg selects — `spec/syntax_conformance_spec.rb`'s own
322
- # "selects the same op..." check holds this constant to the self-
323
- # hosted table's own `Argument#selects` column (`"op=set"`,
324
- # `"op=append"`, ...; whole-project table-unification survey, item
325
- # #1), the same field `rust/parser/src/keywords.rs`'s `ArgumentRow.
326
- # selects` already carries. `to:` is the one kwarg whose own name
327
- # differs from the op it selects — every other kwarg selects the op
328
- # of its own name.
164
+ # Maps each `sets` kwarg to the mutation op it selects. `to:` is the one kwarg
165
+ # whose own name differs from the op it selects (`:set`); every other kwarg
166
+ # selects the op of its own name.
329
167
  KWARG_TO_OP = { to: :set, append: :append, increment: :increment, decrement: :decrement,
330
168
  multiply: :multiply, clamp: :clamp, remove: :remove }.freeze
331
169
 
332
- # Declares one mutation this command applies to `target`, its op selected by whichever
333
- # single keyword (or the omitted, self-referential form) names a source.
334
- #
335
- # Answers the `sets` word through the table's `calls:` column —
336
- # item #13's full metaprogrammed dispatch
337
- # (slice 4c). The `KWARG_TO_OP` op-selection mapping is already
338
- # table-verified (`Argument#selects`), but the REST (`UNSET`-
339
- # sentinel discipline, redundant-spelling refusal, omittable-
340
- # `to:` fallback, one-mutation-only refusal, the position-
341
- # preserving `resolve_*!` reinsertion) is keyed off runtime
342
- # state, not a pure function of a static row — stays hand-
343
- # written, reached through `calls:` like everything else here.
344
- # Bootstrap-reachable, in `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`.
170
+ # Declares one mutation this command applies to `target`, its op selected by
171
+ # whichever single keyword names a source; omitting all of them means `to: target`.
345
172
  #
346
- # @param target [Symbol, String] the field this mutation writes
347
- # @param positional_to [Object] a bare positional value, folded into `to:` when `to:`
348
- # itself is not given; the corpus's only real use is a boolean shorthand
349
- # (`sets :deployed, true`)
350
- # @param to [Object] the value or field reference to set `target` to; a Symbol equal to
351
- # `target` is redundant and refused, and omitting `to:` entirely means the same thing
352
- # @param append [Object] a Hash of fields for a new list element, or a bare value for the
353
- # one-field shorthand
354
- # @param increment [Object] the amount to add to `target`'s current value
355
- # @param decrement [Object] the amount to subtract from `target`'s current value
356
- # @param multiply [Object] the amount to multiply `target`'s current value by
357
- # @param clamp [Array(Object, Object)] the `[min, max]` pair to bound `target`'s current
358
- # value to
359
- # @param remove [Object] the value to remove from `target`'s own list, by equality
173
+ # @param to [Object] a Symbol equal to `target` is redundant and refused
174
+ # @param clamp [Array(Object, Object)] the `[min, max]` pair to bound the current value to
360
175
  # @return [void]
361
176
  # @raise [Bluebook::DSL::Malformed] if `to:` redundantly repeats `target`, or more than
362
- # one of `to:`/`append:`/`increment:`/`decrement:`/`multiply:`/`clamp:`/`remove:` (or
363
- # the folded `positional_to`) is given
177
+ # one op-selecting keyword is given
364
178
  def sets_impl(target, positional_to = UNSET, to: UNSET, append: UNSET,
365
179
  increment: UNSET, decrement: UNSET, multiply: UNSET, clamp: UNSET, remove: UNSET)
366
- # moved to the language: given "a mutation names a target", on Verb.Change
367
-
368
180
  to = positional_to if to.equal?(UNSET) && !positional_to.equal?(UNSET)
369
181
 
370
- # `to:` only ever repeats the target when it's a Symbol naming a
371
- # field — a literal (`to: false`, the bare positional-boolean
372
- # shorthand, a String, ...) is a value, never a redundant name,
373
- # so it never has `.to_sym` to compare in the first place.
182
+ # Only a Symbol can repeat the target's name; a literal value (`to: false`,
183
+ # a String, ...) never has `.to_sym` to compare in the first place.
374
184
  if to.is_a?(Symbol) && to == target.to_sym
375
185
  raise Malformed,
376
186
  "#{@name}'s sets :#{target}, to: :#{target} repeats the target — " \
@@ -382,9 +192,7 @@ module Hecks
382
192
  .reject { |_, source| source.equal?(UNSET) }
383
193
  named = given.to_h { |kwarg, source| [KWARG_TO_OP.fetch(kwarg), source] }
384
194
 
385
- # **The omittable case**. No operation was named at all — not even a
386
- # bare `to:` — so this is `sets :field` alone, which means
387
- # exactly what the redundant, refused spelling above would have.
195
+ # No operation named at all (not even bare `to:`) means `sets :field` alone.
388
196
  named = { set: target } if named.empty?
389
197
 
390
198
  if named.size > 1
@@ -397,23 +205,10 @@ module Hecks
397
205
  @mutations << Mutation.new(target: target.to_sym, op: op, source: normalize_append_source(op, source))
398
206
  end
399
207
 
400
- # Refuses the retired `then_set` spelling, except while shadow-parsing frozen era text,
401
- # where it is read as the legacy mutation shape.
208
+ # Refuses the `then_set` spelling outside shadow-parsing; while shadow-parsing frozen
209
+ # era text, reads it via `legacy_then_set` instead.
402
210
  #
403
- # Legacy under shadow-parsing (S0a's own bridge) — frozen era
404
- # text still parses under it; live source refuses it,
405
- # naming the replacement.
406
- #
407
- # Answers the `then_set` word — item #13's full metaprogrammed
408
- # dispatch (slice 5). Not bootstrap-reachable. Has its own
409
- # dedicated, `status: "deprecated"` Keyword row (syntax.bluebook)
410
- # rather than living only as `sets`'s own `was:` — see that
411
- # row's own comment for why.
412
- #
413
- # @param target [Symbol, String] the field this legacy mutation writes
414
- # @param positional_to [Object] the bare second positional argument; `UNSET` when
415
- # omitted, forwarded to `legacy_then_set` verbatim under shadow-parsing, along with
416
- # every keyword argument this call received
211
+ # @param target [Symbol, String] the field this mutation writes
417
212
  # @return [void]
418
213
  # @raise [Bluebook::DSL::Malformed] outside shadow-parsing, always; under
419
214
  # shadow-parsing, if `legacy_then_set` names no operation or more than one
@@ -423,124 +218,26 @@ module Hecks
423
218
  raise Malformed, "#{@name}'s then_set is gone — sets is the word now"
424
219
  end
425
220
 
426
- # Declares one event this command announces to the outside.
427
- #
428
- # No raise here. "an event is named" is declared in the language itself —
429
- # language/bluebook/behavior.bluebook, on Command.Announce — and MetaValidator is what
430
- # enforces it. This is the first rule to move across rather than be
431
- # duplicated : delete the declaration and an unnamed event is accepted,
432
- # which is what makes the meta-domain load-bearing rather than decorative.
433
- #
434
- # Bare constant accepted (ADR 0025, S6 — "events first-class"),
435
- # `emits Account::AccountFrozen`, resolved through `ConstShim` the
436
- # same way `trigger`/`dispatch` already resolve a command
437
- # reference (`Naming.event_ref`, that method's own header). Not
438
- # yet a required spelling, deliberately, unlike `trigger`/
439
- # `dispatch`'s own quoted-text refusal: those were safe to refuse
440
- # only because command references are already 100% migrated
441
- # across the live corpus (verified 2026-08-27) — `emits`/`on`
442
- # are not, so refusing the quoted form here would break every
443
- # live `.bluebook` site this pass didn't touch, not just frozen
444
- # era text `shadow_parse` exists to keep readable. Both forms
445
- # are accepted in live source until a full corpus migration
446
- # lands and the same refusal this file's `reference_to`/
447
- # `trigger_impl` already carry can be added here safely.
221
+ # Declares one event this command announces to the outside. Accepts both quoted
222
+ # text and a bare constant (`emits Account::AccountFrozen`); refusing the quoted
223
+ # form is not yet safe since not every live bluebook has migrated off it.
448
224
  #
449
225
  # @param event_name [String, Symbol, Module] the event, quoted text or a bare constant
450
- # such as `Account::AccountFrozen`
451
226
  # @return [Array<String>] every event declared so far, this one last
452
227
  def emits(event_name)
453
228
  @emits << Naming.event_ref(event_name)
454
229
  end
455
230
 
456
- # The record's own value as a mutation source — `sets :positions,
457
- # append: { ply: state(:ply), knights: state(:knights) }` copies
458
- # what the record holds now into the new element; `sets :last,
459
- # to: state(:current)` copies one field onto another. A bare
460
- # Symbol always names an argument (`resolve_append_fields!`'s own
461
- # comment has the full account),
462
- # so without this a command could not snapshot its own state at
463
- # all. `Literal::StateRef`'s own comment has the wire spelling.
464
- #
465
231
  # References the record's own current field as a mutation source, as opposed to a
466
- # bare Symbol, which names an argument.
232
+ # bare Symbol, which names an argument, e.g. `sets :last, to: state(:current)`.
467
233
  #
468
234
  # @param name [Symbol, String] the field to read from the pre-dispatch record
469
235
  # @return [Literal::StateRef] the wrapped reference
470
236
  def state(name) = StateRef.new(name.to_sym)
471
237
 
472
- # Declares a synchronous, atomic delegation of this command's own dispatch to one
473
- # nested entity command.
474
- #
475
- # The synchronous cousin of `trigger` — an aggregate-level command
476
- # that hands its own dispatch to one nested entity command, checked
477
- # and applied within the same atomic dispatch rather than a second
478
- # one. Built because `trigger`/`saga`'s own dispatch (`Dispatcher
479
- # #reenter`) is a reaction — the triggering command has already
480
- # committed by the time it runs, and both `PolicyInterpreter#deliver`
481
- # and `SagaInterpreter#deliver_saga_dispatch` rescue a target's own
482
- # refusal and record it rather than raising it back to the original
483
- # caller. That is correct for what those two exist for (an
484
- # eventually-consistent process that can compensate), and wrong for
485
- # a caller who needs a synchronous yes/no on whether the thing they
486
- # asked for actually happened — a chess move's own legality, for
487
- # instance, checked live building `domain/chess` in a downstream
488
- # project. `delegates_to` fills exactly that gap: the target
489
- # entity command's own `given`/`ensures` are enforced as real,
490
- # unrescued Ruby exceptions, so a refusal deep in the entity's own
491
- # rules is the delegating command's own refusal too, and nothing
492
- # from either side is saved unless both sides pass.
493
- #
494
- # `target` is always one hop, `"Entity.Command"` — an aggregate
495
- # names the entity it owns directly, same reach a bare `given`
496
- # reference already has (see `Knight`'s own comment on this
497
- # domain's shared givens), not a multi-segment dispatch chain.
498
- # `with:` resolves the same way `sets ..., append: {...}`'s own
499
- # field map and a policy's own `trigger ..., with: {...}` already
500
- # do: each value names one of this command's own declared/implicit
501
- # arguments, read at dispatch time and handed to the target under
502
- # its own key.
503
- #
504
- # Mutually exclusive with `sets`/`emits` on the same command — a
505
- # delegating command is a pure passthrough by design (see this
506
- # method's own header), so it declares no other mutation or event of
507
- # its own; its result is whatever the delegated entity command's own
508
- # `sets`/`emits` produced. Enforced in `build`, once every builder
509
- # call has already run, so declaration order does not matter.
510
- #
511
- # Stored as a mutation, not a new Command field — a real, deliberate
512
- # choice, not a shortcut. `Command`'s own shape (givens/ensures/
513
- # mutations/emits/...) is not just Ruby: it round-trips through this
514
- # language's own self-hosted meta-domain (`Bluebook::MetaValidator`
515
- # dispatches every declaration into a "Bluebook" domain describing
516
- # itself, then rebuilds the real runtime graph from what that domain
517
- # holds — `Hecks.bluebook` registers what `MetaValidator.call`
518
- # returns, never the builder's own object graph directly, confirmed
519
- # by reading `meta_validator.rb`'s own `self.call`/`self.hold`).
520
- # A genuinely new top-level Command field needs the meta-domain's
521
- # own grammar (`language/bluebook/behavior.bluebook` or wherever
522
- # Verb.Rule/Ensure/Change live) taught to carry it too — the same
523
- # scale of change as the real "item #13" migration this file's own
524
- # comments document throughout. A new mutation op does not: `sets`'s
525
- # own `mutations:` field is already a fully round-tripped part of
526
- # that contract (`Assembly::CONTRACTS["Command"].fields[:mutations]`),
527
- # and an append-shaped mutation already carries a multi-key `fields:`
528
- # hash the exact shape `with:` needs — so `delegates_to` rides that
529
- # existing, already-correct wire format under a new `op: :delegate`
530
- # instead of inventing a parallel one. `MutationOp`'s own closed set
531
- # (vocabulary.bluebook) gained `"delegate"` alongside `"append"`
532
- # for exactly this reason, and the three meta-domain touch points
533
- # that hard-coded `op == "append"` for the multi-binding shape
534
- # (`meta_validator/readings.rb#mutation_rows`,
535
- # `meta_validator/shapes.rb#mutation`, `assembly/marks.rb#mutation`)
536
- # now check for `:delegate` alongside it, each with a comment
537
- # pointing back here.
538
- # Answers the `delegates_to` word through the table's `calls:`
539
- # column — matches `sets_impl`/`given_impl`/`reference_to_impl`'s own
540
- # convention (language/bluebook/syntax.bluebook's own Keyword row
541
- # for this word names `calls: "delegates_to_impl"`), the same
542
- # `word`-vs-`_impl` split every hand-written (not yet item-#13-
543
- # generic-dispatch-migrated) DSL word here already follows.
238
+ # Declares a synchronous, atomic delegation of this command's dispatch to one nested
239
+ # entity command; unlike `trigger`/`saga`, the target's given/ensures are enforced as
240
+ # real exceptions, so its refusal is the delegating command's own refusal too.
544
241
  #
545
242
  # @param target [String, Symbol] the delegated command, dotted `"Entity.Command"`
546
243
  # @param with [Hash{Symbol => Symbol, Object}] projects this command's own arguments
@@ -559,57 +256,14 @@ module Hecks
559
256
  @mutations << Mutation.new(target: target.to_s, op: :delegate, source: with)
560
257
  end
561
258
 
562
- # Declares that this command amends a past event, rather than rewriting it.
563
- #
564
- # A command declaring what past fact it amends — the append-only
565
- # answer to "what if this record's history turns out to have been
566
- # wrong": never rewrite the original event (the log stays exactly
567
- # what it was), always append a new fact on top. `event` names the
568
- # event this command corrects; `as:` optionally binds the located
569
- # instance for a `given`/`ensures` to reference, the same shape
570
- # `ensures`'s own `old` binding already has; `reason:` is not
571
- # descriptive-only the way `goal` is — it is carried as data, the
572
- # one thing an audit trail actually needs ("we corrected this, and
573
- # here is why"), refused when blank the same way a `given`'s own
574
- # description is required to say something.
575
- #
576
- # Stored as a mutation, not a new Command field — see the
577
- # KeywordSeed row's own comment (command.bluebook) for why: this
578
- # is the exact same choice `delegates_to` already made, for the
579
- # exact same reason. Rides the same multi-binding wire shape
580
- # `append`/`delegate` use — `as:`/`reason:`/`reverses:` assembled
581
- # by hand into one `source` hash, the way `sets_impl` assembles up
582
- # to seven kwargs into one `named` hash above.
583
- #
584
- # `reverses: true` names an intent to auto-derive the corrective
585
- # `sets` from the original event's own mutations, rather than the
586
- # author writing it — see `AggregateBuilder#seal_correction_targets`,
587
- # where that derivation actually happens (it needs every sibling
588
- # command in the aggregate already known, which this builder alone
589
- # cannot see). Mutually exclusive with an explicit `sets` on the
590
- # same command — two ways of saying the same thing is exactly the
591
- # redundancy `sets`'s own omittable-`to:` rule refuses elsewhere.
592
- #
593
- # `as:` is always stored as text, never left a bare Symbol —
594
- # `Mutation#classified_source`/`#appended_fields` (Behaviour::
595
- # Mutation) classify any bare Symbol field as `kind: "argument"`,
596
- # meaning "resolve this against one of this command's own declared
597
- # attributes at dispatch time" (append/delegate's own meaning for a
598
- # Symbol). `as:` names no such thing — it is a plain label, not yet
599
- # wired into the expression evaluator (a future round's work, once
600
- # a real runtime consumer exists) — so coercing it to a String here
601
- # keeps it out of that machinery entirely rather than silently
602
- # miscategorised as an unresolvable argument reference.
259
+ # Declares that this command amends a past event, rather than rewriting it. `reverses:
260
+ # true` auto-derives the corrective `sets` from the original event's own mutations,
261
+ # and is mutually exclusive with an explicit `sets` on the same command.
603
262
  #
604
- # @param event [String, Symbol, Module] the event this command corrects, quoted text or
605
- # a bare constant
606
- # @param as [Symbol, nil] binds the located instance under this label, for a
607
- # `given`/`ensures` to reference; nil declares no binding
608
- # @param reason [String, nil] why the correction is being made, carried as audit data;
609
- # required, non-blank
610
- # @param reverses [Boolean] true to auto-derive the corrective `sets` from the original
611
- # event's own mutations, checked once every sibling command is known; mutually
612
- # exclusive with an explicit `sets` on the same command
263
+ # @param event [String, Symbol, Module] the event this command corrects
264
+ # @param as [Symbol, nil] binds the located instance for a `given`/`ensures` to reference
265
+ # @param reason [String, nil] why the correction is made, carried as audit data; required
266
+ # @param reverses [Boolean] auto-derive the corrective `sets` from the original mutations
613
267
  # @return [Array<Bluebook::Mutation>] every mutation declared so far, this one last
614
268
  # @raise [Bluebook::DSL::Malformed] if `reason` is nil or blank
615
269
  def corrects_impl(event, as: nil, reason: nil, reverses: false)
@@ -665,15 +319,8 @@ module Hecks
665
319
  # Evaluates a `command` block against a fresh builder and returns what it built.
666
320
  #
667
321
  # @param name [String] the command's name
668
- # @param owner [String, nil] name of the aggregate or entity this command belongs to
669
322
  # @param from [String, Symbol, Array<String, Symbol>, nil] the lifecycle state(s) this
670
323
  # command guards from
671
- # @param named_givens [Hash{String => Bluebook::Given}] the owner's own given pool
672
- # @param owner_attributes [Array<Bluebook::Attribute>] the owner's own attributes
673
- # @param owner_constructs [Array<Bluebook::ValueObject, Bluebook::Entity>] the owner's
674
- # own value objects and entities
675
- # @param entity_shared_givens [Hash{String => Bluebook::Given}] a sibling piece's own
676
- # entity-level given pool
677
324
  # @yield the command body, evaluated with the builder as `self`; may be omitted
678
325
  # @return [Bluebook::Command] the built command
679
326
  # @raise [Bluebook::DSL::Malformed] if the body fails any check `#build` raises
@@ -688,11 +335,8 @@ module Hecks
688
335
 
689
336
  private
690
337
 
691
- # C4.2 (docs/semantics/bluebook-semantics.md) — a command's effects
692
- # are one update set over the pre-dispatch state, so a field
693
- # written twice has no meaning to give: last-wins would make
694
- # declaration order significant, which the update set says it is
695
- # not. Refused here, where the declaration can still be read whole.
338
+ # A command's effects are one update set over the pre-dispatch state — a field
339
+ # written twice would make declaration order silently significant.
696
340
  def refuse_duplicate_targets!
697
341
  return if MetaValidator.shadow_parsing? # frozen era text is history
698
342
 
@@ -709,37 +353,10 @@ module Hecks
709
353
  end
710
354
  end
711
355
 
712
- # **Resolution rules** — see `docs/resolution-rules/README.md` for the
713
- # precise, language-agnostic algorithm each of `resolve_bare_set!`/
714
- # `resolve_append_fields!` implements (`implicit-command-attributes.md`
715
- # / `implicit-append-fields.md`) — the contract a Rust mirror is
716
- # written from, not inferred from this comment.
717
- #
718
- # `sets :field` alone (S5's own bare form — no `to:`, meaning
719
- # `to: :field`) already says the command accepts an argument
720
- # named `:field`; requiring a separate `attribute :field, Type`
721
- # line that retypes what the owning aggregate/entity already
722
- # declared is the same redundancy S10's `given` reference already
723
- # killed for preconditions ("a precondition shared across
724
- # commands is declared once... a command references it by
725
- # name"). Same move here, one level down: when the command
726
- # hasn't declared its own `:field`, import the owner's
727
- # already-built `Attribute` verbatim (same type, pattern,
728
- # optional, admits) instead of retyping it.
729
- #
730
- # Only the exact self-referential shape qualifies — `sets
731
- # :field, to: :other` names a genuinely different source and
732
- # stays exactly as explicit as it always was; `sets :field, to:
733
- # false` (or any other literal) isn't naming an argument at all.
734
- # Comparing as text rather than identity handles both sides
735
- # (`source` carries whatever `target` was passed as; `target`
736
- # itself is always symbolized) without caring which.
737
- #
738
- # Declaration order matters here the same way it already does
739
- # for `identified_by`/`given` — the owner's own attribute must
740
- # exist by the time this builder's `build` runs, which every
741
- # real bluebook already satisfies (the aggregate/entity always
742
- # declares its attributes before the commands that act on them).
356
+ # `sets :field` alone already means the command accepts an argument named `:field` —
357
+ # when the command hasn't declared its own `:field`, imports the owner's already-built
358
+ # `Attribute` verbatim instead of requiring a redundant re-declaration (ADR 0025).
359
+ # Requires the owner's own attributes to already exist by the time `build` runs.
743
360
  def resolve_implicit_attributes!
744
361
  @mutations.each do |mutation|
745
362
  case mutation.op
@@ -748,51 +365,25 @@ module Hecks
748
365
  end
749
366
  refuse_unknown_state_sources!(mutation)
750
367
  end
751
- # A second, separate pass — not folded into the loop above — so
752
- # every mutation's own self-referential import (resolve_bare_set!)
753
- # has already landed before any mutation's source is checked
754
- # against the final `attributes` list. `sets :a, to: :b` declared
755
- # before `sets :b` (bare, importing :b from the owner) is real
756
- # and legal; checking inline, mutation by mutation, would refuse
757
- # it for an ordering accident this language has never required
758
- # authors to avoid. rubocop's Style/CombinableLoops can't see
759
- # that dependency — it only sees two `@mutations.each` calls
760
- # back to back — which is exactly why it's disabled repo-wide
761
- # (see .rubocop.yml) rather than satisfied.
368
+ # A second, separate pass, not folded into the loop above: every mutation's own
369
+ # self-referential import must land before any source is checked against the
370
+ # final `attributes` list, or a legal declaration order gets refused.
762
371
  @mutations.each { |mutation| refuse_unknown_argument_sources!(mutation) }
763
372
  end
764
373
 
765
- # The ones `resolve_source` (CommandRules::Arithmetic) only ever
766
- # reads from `args` — never a fallback to the record's own current
767
- # state the way `append`'s own per-field resolution legitimately
768
- # can (`MutationApplier#resolve_append_source`'s own `instance
769
- # [source]` fallback, a real, intentional second meaning this
770
- # check must not foreclose). For exactly these five ops, a bare
771
- # Symbol source has exactly one legitimate reading — the name of
772
- # a declared argument — so anything else is unreachable at
773
- # runtime, not merely optional: no caller can ever supply a value
774
- # under a name the command never declared (ArgumentGate's own
775
- # `refuse_unknown_arguments` already refuses that), so the source
776
- # resolves to nil forever, indistinguishable from a legitimately
777
- # absent optional argument until this check existed to tell them
778
- # apart. Mirrors `AggregateBuilder#seal_query_argument`'s
779
- # identical shape for a query's own where-clause argument —
780
- # same mistake, one construct over.
374
+ # For exactly these ops, a bare Symbol source has exactly one legitimate reading —
375
+ # a declared argument's name — since `append`'s record-state fallback doesn't apply
376
+ # here; anything else would resolve to nil forever, indistinguishable from an
377
+ # absent optional argument, unless refused explicitly.
781
378
  CHECKED_SYMBOL_SOURCE_OPS = %i[set increment decrement multiply remove].freeze
782
379
  private_constant :CHECKED_SYMBOL_SOURCE_OPS
783
380
 
784
381
  def refuse_unknown_argument_sources!(mutation)
785
382
  return unless CHECKED_SYMBOL_SOURCE_OPS.include?(mutation.op)
786
383
  return unless mutation.source.is_a?(Symbol)
787
- # The bare self-referential shape (`sets :field` alone, `source
788
- # == target`) is `resolve_bare_set!`'s own territory, not this
789
- # check's — when neither the command nor the owner declares
790
- # that name, the more specific, pre-existing refusal one level
791
- # up (`AggregateBuilder#seal_mutation_targets`, checking the
792
- # mutation's target against the aggregate's own fields) is the
793
- # one that should fire, naming the field as a target problem,
794
- # not — confusingly — as a source problem this check would
795
- # otherwise misreport it as.
384
+ # The bare self-referential shape (`source == target`) is `resolve_bare_set!`'s
385
+ # own territory — skipped here so an undeclared field is refused as a target
386
+ # problem, not misreported as a source problem.
796
387
  return if mutation.source.to_s == mutation.target.to_s
797
388
  return if attributes.any? { |attr| attr.name == mutation.source }
798
389
 
@@ -803,10 +394,8 @@ module Hecks
803
394
  "caller actually sent"
804
395
  end
805
396
 
806
- # `state(:name)` names one of the owner's own fields — a snapshot
807
- # of something the record actually holds. Refused at build, by
808
- # name, the way an unknown `given` reference is; nothing here can
809
- # read a field the aggregate never declared.
397
+ # `state(:name)` snapshots one of the owner's own fields; refused at build, the
398
+ # same way an unknown `given` reference is.
810
399
  def refuse_unknown_state_sources!(mutation)
811
400
  sources = mutation.source.is_a?(Hash) ? mutation.source.values : [mutation.source]
812
401
  sources.grep(StateRef).each do |ref|
@@ -818,15 +407,8 @@ module Hecks
818
407
  end
819
408
 
820
409
  def resolve_bare_set!(mutation)
821
- # A symbol naming its own target — never a literal that merely
822
- # spells the same word. `sets :moved, to: "moved"` (a chess rook
823
- # recording that it has moved, into a closed set whose member is
824
- # literally "moved") must not read as the shorthand and import
825
- # the owner's `moved` attribute onto the command — that would add a phantom
826
- # argument nothing ever passes, harmless at runtime only
827
- # because the owner's default filled it, and a real, silent
828
- # divergence for every projection that reads the command's
829
- # declared arguments.
410
+ # Only a Symbol naming its own target qualifies — a literal that merely spells the
411
+ # same word (`sets :moved, to: "moved"`) must not import a phantom argument.
830
412
  return unless mutation.source.is_a?(Symbol) && mutation.source.to_s == mutation.target.to_s
831
413
  return if attributes.any? { |attr| attr.name == mutation.target }
832
414
 
@@ -834,46 +416,13 @@ module Hecks
834
416
  attributes << owner_attr if owner_attr
835
417
  end
836
418
 
837
- # One hop deeper than `resolve_bare_set!` — an `append:` mutation
838
- # (`sets :ledger, append: { narrative: :narrative, ... }`) builds
839
- # a new element of a list field, not the command's own root
840
- # record, so a bare self-referential field inside it (the hash
841
- # key equals its own value, same shorthand `resolve_bare_set!`
842
- # already reads) can't resolve against `@owner_attributes` — the
843
- # aggregate itself never stores `:narrative`, only the list
844
- # element's own construct does (`attribute :ledger,
845
- # list_of(LedgerEntry)`, and `LedgerEntry` is what actually
846
- # declares `:narrative`). Resolves the list field's own element
847
- # type first (`element_type_for`), then that construct's own
848
- # attribute of the same name — same verbatim-import, one level
849
- # further down the same reasoning `resolve_bare_set!`'s own
850
- # comment already gives.
851
- #
852
- # A non-self-referential value (`direction: { value: "credit" }`,
853
- # a nested literal) is untouched — only a bare symbol equal to
854
- # its own key ever qualifies, identical to `resolve_bare_set!`'s
855
- # own target/source text comparison.
419
+ # One hop deeper than `resolve_bare_set!`: an `append:` mutation builds a new list
420
+ # element, so a bare self-referential field inside it resolves against the list's
421
+ # own element type (`element_type_for`), not `@owner_attributes`.
856
422
  #
857
- # Position-preserving, not appended at the end — the exported IR
858
- # is array-order-sensitive (attributes carry their own declared
859
- # order onto the wire), so an append's fields are resolved as
860
- # one contiguous group, in the mutation's own hash order,
861
- # reinserted at whichever position the group's leftmost still-
862
- # declared member already occupies (or the end, if every member
863
- # of the group is resolved). A plain `attributes << owner_attr`
864
- # here would only ever reproduce the original order when the
865
- # missing field happened to already be last — real, live
866
- # evidence: `Keyword#was`/`Argument#variadic` (both genuinely
867
- # last in their own append hash) round-tripped correctly under
868
- # the naive append; every other field in the same hash did not,
869
- # caught by this codemod's own reboot-and-diff safety net rather
870
- # than silently landing wrong.
871
- # `anchor` is a snapshot of `present`'s position, taken before
872
- # `attributes.reject!` mutates the array below it — see this
873
- # method's own header comment for why: a naive append-at-end
874
- # silently scrambled real corpus field order (Keyword#was/
875
- # Argument#variadic). Splitting the snapshot from the mutation it
876
- # guards is exactly the ordering invariant that must not move.
423
+ # Position-preserving, not appended at the end — the exported IR is array-order-
424
+ # sensitive, so resolved fields are reinserted at the position the group's leftmost
425
+ # still-declared member already occupied.
877
426
  # rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
878
427
  def resolve_append_fields!(mutation)
879
428
  return unless mutation.source.is_a?(Hash)
@@ -897,13 +446,8 @@ module Hecks
897
446
  attributes.insert(anchor, *group)
898
447
  end
899
448
 
900
- # The owner's own list attribute names its element type as text
901
- # (`Attribute#type`, unwrapped from `list_of(...)` at declare
902
- # time) — resolved against `@owner_constructs` (the owner's own
903
- # value objects and entities, the only two kinds an element can
904
- # be) by `hecks_name`, the same lookup
905
- # `AttributeCollector#resolve_identity_field!` already uses for
906
- # a value object's own name.
449
+ # The owner's own list attribute names its element type as text; resolved against
450
+ # `@owner_constructs` (the only two kinds an element can be) by `hecks_name`.
907
451
  def element_type_for(list_field)
908
452
  list_attr = @owner_attributes.find { |attr| attr.name == list_field && attr.list? }
909
453
  return nil unless list_attr
@@ -911,12 +455,8 @@ module Hecks
911
455
  @owner_constructs.find { |construct| construct.hecks_name.to_s == list_attr.type.to_s }
912
456
  end
913
457
 
914
- # Legacy — see `then_set`'s own comment. The original implementation,
915
- # verbatim: `from:` still a synonym for `to:`, no omittable-`to:`
916
- # shorthand, no refusal for the redundant `to: target` spelling —
917
- # frozen era text was minted under this reading, and a legacy
918
- # grammar exists precisely so re-parsing it never silently changes
919
- # what it meant.
458
+ # Preserves `then_set`'s exact prior reading (`from:` a synonym for `to:`, no
459
+ # omittable-`to:` shorthand) so frozen era text always re-parses to the same meaning.
920
460
  def legacy_then_set(target, positional_to = UNSET, to: UNSET, from: UNSET, append: UNSET,
921
461
  increment: UNSET, decrement: UNSET, multiply: UNSET, clamp: UNSET, remove: UNSET)
922
462
  to = positional_to if to.equal?(UNSET) && !positional_to.equal?(UNSET)
@@ -942,21 +482,9 @@ module Hecks
942
482
  @mutations << Mutation.new(target: target.to_sym, op: op, source: normalize_append_source(op, source))
943
483
  end
944
484
 
945
- # `append:` normally binds several fields at once (`append: {
946
- # name: :name, amount: :amount }`) — `Mutation#appended_fields`/
947
- # `MutationApplier#appended`/the meta-validator Judge's own
948
- # `mutation_rows` all read `mutation.source` as a Hash
949
- # unconditionally. A bare value (`append: :single_field`, or any
950
- # non-Hash literal) is the one-field shorthand: exactly what an
951
- # explicit `append: { value: :single_field }` would have meant,
952
- # named the same way a single-field value object's own implicit
953
- # member already is (`MutationApplier#appended`'s own `:value`
954
- # scalar-unwrap). Without this, that shorthand built a Mutation
955
- # whose `source` was a bare Symbol, which crashed with a raw
956
- # `NoMethodError` on `#transform_values` the moment anything
957
- # downstream read it — at dispatch (`MutationApplier#appended`),
958
- # at IR emission (`Mutation#appended_fields`), and in the
959
- # meta-validator's own Judge (`Readings#mutation_rows`). #138.
485
+ # `append:` normally binds a Hash of fields; a bare value (`append: :single_field`)
486
+ # is the one-field shorthand for `append: { value: :single_field }` — without this,
487
+ # downstream code that reads `mutation.source` as a Hash unconditionally would crash.
960
488
  def normalize_append_source(oper, source)
961
489
  return source unless oper == :append
962
490
  return source if source.is_a?(::Hash)