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
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hecks
4
+ # The repository's command-line tools as library code: the comment linters, the regeneration
5
+ # run, the deploy generators and the conformance matrix.
6
+ #
7
+ # Each tool is a module with `main(argv, root:)` that prints to `$stdout` and `$stderr` and
8
+ # refuses with `abort` or `exit`, as the script it replaced did, and answers an exit status. An
9
+ # adapter runs a tool in this process under `Adapters::ConsoleCapture`; `script` runs one as a
10
+ # child's whole program. `require "hecks"` loads none of them: each is required by the command
11
+ # that needs it.
12
+ module Tools
13
+ # The checkout this file lives in, which a tool works on when it is given no other.
14
+ ROOT = File.expand_path("../..", __dir__)
15
+
16
+ # Each tool by the name of the retired script it replaced: the file that defines it, and its
17
+ # constant.
18
+ REGISTRY = {
19
+ "standardize_comments" => ["tools/comment_style", "CommentStyle"],
20
+ "standardize_comments_rust" => ["tools/rust_comment_style", "RustCommentStyle"],
21
+ "regen_codegen_domains" => ["tools/regeneration_run", "RegenerationRun"],
22
+ "argument_gate_matrix" => ["tools/argument_gate_matrix", "ArgumentGateMatrix"],
23
+ "project_deploy" => ["tools/deploy_recipe", "DeployRecipe"],
24
+ "lint_deploy_recipes" => ["tools/deploy_recipe_lint", "DeployRecipeLint"],
25
+ "project_oidc" => ["tools/oidc_manifests", "OidcManifests"],
26
+ "project_tenant" => ["tools/tenant_provisioning", "TenantProvisioning"],
27
+ "translation_audit" => ["tools/translation_audit", "TranslationAudit"],
28
+ "scaffold_translation" => ["tools/translation_scaffold", "TranslationScaffold"],
29
+ "reattest_era" => ["tools/era_reattest", "EraReattest"],
30
+ "merge_tail" => ["tools/tail_merge", "TailMerge"],
31
+ "backfill_era_projections" => ["tools/era_projection_backfill", "EraProjectionBackfill"],
32
+ "compact" => ["tools/journal_compaction", "JournalCompaction"],
33
+ "heki_compact" => ["tools/heki_compaction", "HekiCompaction"],
34
+ "fuzz" => ["tools/fuzz_sweep", "FuzzSweep"],
35
+ "generate" => ["tools/sequence_script", "SequenceScript"],
36
+ "corpus" => ["tools/corpus_report", "CorpusReport"],
37
+ "evolve" => ["tools/evolve_run", "EvolveRun"],
38
+ "query_ir" => ["tools/query_ir_run", "QueryIrRun"],
39
+ "codemod_hoist_local_givens" => ["tools/hoist_local_givens", "HoistLocalGivens"],
40
+ "codemod_implicit_append_fields" => ["tools/drop_implicit_append_fields", "DropImplicitAppendFields"]
41
+ }.freeze
42
+
43
+ module_function
44
+
45
+ # @param name [String] a tool's name, as in `REGISTRY`
46
+ # @return [Boolean] whether the script's body lives here
47
+ def tool?(name) = REGISTRY.key?(name)
48
+
49
+ # Loads a tool and returns it.
50
+ #
51
+ # @param name [String] a tool's name, as in `REGISTRY`
52
+ # @return [Module] the tool, which answers `main(argv, root:)`
53
+ # @raise [KeyError] when no tool replaced a script of that name
54
+ def fetch(name)
55
+ file, constant = REGISTRY.fetch(name)
56
+ require File.join(__dir__, file)
57
+ const_get(constant)
58
+ end
59
+
60
+ # Runs a tool as a program's whole body and exits with its status. Paths in `argv` are read
61
+ # from the directory the caller stands in.
62
+ #
63
+ # @param name [String] a tool's name, as in `REGISTRY`
64
+ # @param argv [Array<String>] the arguments the script took
65
+ # @return [void]
66
+ def script(name, argv)
67
+ exit(fetch(name).main(argv) || 0)
68
+ end
69
+
70
+ # Runs a tool from a checkout's root in this process.
71
+ #
72
+ # @param name [String] a tool's name, as in `REGISTRY`
73
+ # @param argv [Array<String>] the arguments the script took
74
+ # @param root [String] the checkout to work on
75
+ # @return [Integer] the exit status: 0 when the tool ends normally; 1, with the error's class
76
+ # and message on `$stderr`, when the tool raises
77
+ def run(name, argv, root: ROOT)
78
+ Dir.chdir(root) { fetch(name).main(argv, root: root) || 0 }
79
+ rescue SystemExit => e
80
+ e.status
81
+ rescue StandardError, ScriptError => e
82
+ warn "#{name}: #{e.class}: #{e.message}"
83
+ 1
84
+ end
85
+ end
86
+ end
@@ -1,13 +1,7 @@
1
1
  module Hecks
2
2
  module Vendoring
3
- # The environment a `git` subprocess needs so it resolves its repository
4
- # from the directory it is pointed at, not from whoever launched Ruby.
5
- #
6
- # Git exports `GIT_DIR`, `GIT_INDEX_FILE` and their kin to the hooks it
7
- # runs (a push from a linked worktree runs `pre-push` this way). Every
8
- # `git` that a hook's process tree starts inherits them, and they outrank
9
- # both `git -C` and the working directory: a command aimed at a scratch
10
- # repository would read, or commit into, the repository that was pushing.
3
+ # The environment a `git` subprocess needs to target one repository:
4
+ # inherited GIT_DIR variables outrank `-C` and would redirect it elsewhere.
11
5
  module GitEnvironment
12
6
  # The variables that pin git to one repository, work tree or index.
13
7
  INHERITED = %w[
@@ -4,14 +4,8 @@ require_relative "git_environment"
4
4
 
5
5
  module Hecks
6
6
  module Vendoring
7
- # A local git repository read through the `git` executable, never through
8
- # its working tree.
9
- #
10
- # Everything here names a commit and reads what that commit holds, so a
11
- # shared checkout with uncommitted edits, or a different branch checked
12
- # out, cannot leak into what gets vendored. Every command runs under
13
- # {GitEnvironment.clean}, so a `GIT_DIR` inherited from a hook cannot
14
- # redirect it to some other repository.
7
+ # Reads one commit of a local git repository via the `git` executable,
8
+ # under {GitEnvironment.clean} so an inherited `GIT_DIR` can't redirect it.
15
9
  class GitSource
16
10
  # @param path [String] a directory that is a git repository (or a
17
11
  # worktree of one)
@@ -57,8 +51,8 @@ module Hecks
57
51
 
58
52
  # Lists the files directly inside a directory of a commit.
59
53
  #
60
- # Subdirectories are left out on purpose: a vendored package carries the
61
- # top-level files of its subtree and nothing nested beneath.
54
+ # Subdirectories are excluded on purpose; only the subtree's own
55
+ # top-level files are vendored.
62
56
  #
63
57
  # @param ref [String] the commit-ish to read from
64
58
  # @param subtree [String] a repository-relative directory, such as `"payments/bluebook"`
@@ -5,29 +5,7 @@ require_relative "vendoring/git_source"
5
5
 
6
6
  module Hecks
7
7
  # Pins an exact commit of one directory of another repository into a
8
- # project's own tree.
9
- #
10
- # ## What it is
11
- #
12
- # A project that consumes a package from a private repository cannot clone
13
- # that repository when its image builds, and a live pull would make the build
14
- # depend on whatever is checked out. So the files are exported from one
15
- # commit, committed into the consumer, and a marker file beside them records
16
- # which commit they came from. Only the files directly inside the named
17
- # subtree are taken; the source's own specs, ports, adapters and data stay
18
- # where they are.
19
- #
20
- # ## Marker
21
- #
22
- # `VENDORED_COMMIT` holds the full 40-character commit id and a newline, so
23
- # `git -C <source> show <id>:<subtree>` reproduces the vendored files. The
24
- # marker sits in `into`, beside the exported directory.
25
- #
26
- # ## Whole-directory replacement
27
- #
28
- # A pin replaces `into` entirely, so a file the source dropped does not
29
- # linger. Nothing is touched until the export succeeded and the optional
30
- # block accepted it.
8
+ # project's own tree, so a build doesn't depend on a live clone.
31
9
  module Vendoring
32
10
  # Raised when a pin cannot be made or is refused.
33
11
  class Error < StandardError; end
@@ -45,27 +23,17 @@ module Hecks
45
23
  # @return [Array<String>] the exported files' names, sorted
46
24
  Pin = Struct.new(:commit, :dir, :files, keyword_init: true)
47
25
 
48
- # Exports the top-level files of one directory at one commit into `into`.
49
- #
50
- # The exported files land in `into/<last segment of subtree>/`; the marker
51
- # lands in `into` itself. The optional block sees the staged files before
52
- # anything is replaced and may raise to refuse the pin.
26
+ # Exports the top-level files of one directory at one commit into `into`,
27
+ # replacing it wholly; the optional block may refuse before that happens.
53
28
  #
54
29
  # @param from [String] path of the local source repository
55
- # @param ref [String] the commit-ish to export (branch, tag or commit id)
56
- # @param subtree [String] repository-relative directory to export, such as
57
- # `"payments/bluebook"`
30
+ # @param ref [String] the commit-ish to export
31
+ # @param subtree [String] repository-relative directory to export
58
32
  # @param into [String] the directory to replace with the export
59
- # @param glob [String] `File.fnmatch` pattern each exported file's name must match
33
+ # @param glob [String] pattern each exported file's name must match
60
34
  # @param marker [String] name of the file recording the commit
61
- # @yield [staged, commit] the staged files, before `into` is touched
62
- # @yieldparam staged [String] directory holding the exported files
63
- # @yieldparam commit [String] the resolved commit id
64
- # @yieldreturn [Hash{String => String}, nil] extra files to write into `into`,
65
- # keyed by file name; nil for none
66
35
  # @return [Pin] the commit and where the files landed
67
- # @raise [Vendoring::Error] if the source is missing, `ref` names no commit,
68
- # the subtree holds no matching file, or the block refuses
36
+ # @raise [Vendoring::Error] if the source or a matching file is missing
69
37
  def self.pin(from:, ref:, subtree:, into:, glob: "*", marker: MARKER)
70
38
  source = GitSource.new(from)
71
39
  commit = source.commit(ref)
@@ -83,13 +51,6 @@ module Hecks
83
51
  end
84
52
 
85
53
  # Replaces `into` with the staged files, the marker and any extras.
86
- #
87
- # @param staged [String] directory holding the exported files
88
- # @param into [String] the directory to replace
89
- # @param marker [String] marker file name
90
- # @param commit [String] commit id the marker records
91
- # @param extras [Hash{String => String}] more files to write into `into`
92
- # @return [void]
93
54
  def self.install(staged, into, marker, commit, extras)
94
55
  FileUtils.rm_rf(into)
95
56
  FileUtils.mkdir_p(into)
data/lib/hecks/version.rb CHANGED
@@ -1,16 +1,5 @@
1
1
  module Hecks
2
- # **Isolated, on purpose** — the gemspec reads this file directly rather
3
- # than `require_relative "lib/hecks"` (the whole framework),
4
- # specifically so evaluating the gemspec never triggers any of this
5
- # gem's own dependencies (prism among them) before Bundler has even
6
- # resolved what to install. A real, live chicken-and-egg bug caught
7
- # deploying to a Ruby version that doesn't bundle prism for free
8
- # (AWS Lambda's ruby3.2): the gemspec's own `require_relative
9
- # "lib/hecks"` pulled in adapters/driven/prism.rb's
10
- # unconditional `require "prism"`, which failed before Bundler ever
11
- # read what the gemspec itself declared as a dependency — declaring
12
- # it there, or even in the consuming Gemfile, never closed the gap,
13
- # because gemspec evaluation happens before anything Bundler
14
- # resolves is actually loadable yet.
15
- VERSION = "2.8.0".freeze
2
+ # Read directly by the gemspec, so this file must never require the
3
+ # rest of the gem (its dependencies aren't resolved yet at that point).
4
+ VERSION = "3.0.0".freeze
16
5
  end
data/lib/hecks.rb CHANGED
@@ -12,6 +12,7 @@ require_relative "hecks/construct"
12
12
  # extends this to declare what it emits.
13
13
  require_relative "hecks/ir"
14
14
  require_relative "hecks/literal"
15
+ require_relative "hecks/doors"
15
16
  require_relative "hecks/facade"
16
17
  require_relative "hecks/query_specification"
17
18
 
@@ -28,81 +29,65 @@ require_relative "hecks/projector"
28
29
  require_relative "hecks/projections"
29
30
  # After `Projector` (dispatches against the `:cli` projection) and
30
31
  # `Ports::Clock` (fills a staleness rule's `now` at the door) both exist.
31
- require_relative "hecks/facade/cli_door"
32
- require_relative "hecks/facade/cli_runner"
32
+ require_relative "hecks/doors/cli_door"
33
+ require_relative "hecks/doors/cli_runner"
33
34
  require_relative "hecks/storehouse"
34
35
  require_relative "hecks/mcp_stdio_guard"
35
- require_relative "hecks/mcp_door_scope"
36
+ require_relative "hecks/doors/mcp_door_scope"
36
37
  require_relative "hecks/framework"
37
38
  require_relative "hecks/vendoring"
38
39
  require_relative "hecks/embryonaut_bluebook"
39
40
 
40
- # Repository-only tooling: the corpus table walks `examples/`, `qa/` and
41
- # `spec/`, which only a checkout has, so it loads on first use and the
42
- # packaged gem leaves it out (ADR 0066).
41
+ # The corpus table walks `examples/`, `qa/` and `spec/`, which only a checkout
42
+ # has, so it loads on first use.
43
43
  Hecks.autoload(:Corpus, File.expand_path("hecks/corpus", __dir__))
44
44
 
45
- # The root namespace and public facade of the whole DSL/runtime: `Hecks.boot`/
46
- # `.boot_files` assemble a running domain from `.bluebook`/`.hecksagon`/
47
- # `.world` files, and `.bluebook`/`.hecksagon`/`.port`/`.adapter`/`.world`/
48
- # `.data_translation` are the top-level declaration words every such file
49
- # opens with, each collecting its built construct into the currently booting
50
- # Registry (`#collect`, private below).
45
+ # The chapters a hecksagon can `attaches` by name (ADR 0080); loads on first use.
46
+ Hecks.autoload(:Chapters, File.expand_path("hecks/chapters", __dir__))
47
+
48
+ # Root namespace and public facade of the DSL/runtime: `Hecks.boot`/`.boot_files`
49
+ # assemble a running domain from `.bluebook`/`.hecksagon`/`.world` files.
51
50
  module Hecks
52
51
  class LoadOutsideBoot < StandardError; end
53
52
 
54
53
  class << self
55
- # The loading words below collect into the registry the runtime is
56
- # holding open ; booting and that ambient state belong to the runtime
57
- # layer, so this module is their facade and Hecks::Runtime is where
58
- # they live.
59
- # `install_facade:` — see Runtime::Loader.boot. Defaults on; a caller
60
- # that only dispatches by FQN string can skip the global sugar.
61
- #
62
- # `environment:` — recovered, not new: this parameter (and the
63
- # `environments/<name>.hecksagon` / `.world` overlay it loads —
64
- # see Adapters::Folder#load_domain) existed on a prior commit of
65
- # this repo (933d1dd), was vendored out to a real consumer
66
- # (a client site's domain), and was then lost from this repo's own
67
- # history (no branch here reaches that commit). Ported forward
68
- # from the consumer's vendor snapshot — the only surviving copy —
69
- # and generalized: the original only loaded a `.hecksagon`
70
- # overlay; this also loads a same-named `.world` overlay, both
71
- # merged into the base rather than replacing it (Registry#add_hecksagon
72
- # / #add_world). hecks never reads ENV itself — a caller
73
- # resolves its own env var name and passes the resulting string
74
- # straight through, e.g. `Hecks.boot(path, environment:
75
- # ENV.fetch("MYAPP_ENV", "development"))`.
76
- #
54
+ # Boots a domain from `path`, assembling a running dispatcher from its
55
+ # `.bluebook`/`.hecksagon`/`.world` files. `environment` defaults to
56
+ # the `HECKS_ENVIRONMENT` variable; pass a name to choose one, or `nil` for none.
77
57
  # @param path [String] path to a domain directory, or a file inside one
78
58
  # @param shared [String, nil] a shared-root override; see `Runtime::Loader.boot`
79
- # @param install_facade [Boolean] whether to install the `Widget::Item.Add`-style
80
- # Ruby facade constants for this boot
81
- # @param environment [String, nil] the environment name whose
82
- # `environments/<name>.hecksagon`/`.world` overlay, if present, loads after the
83
- # domain's own
84
- # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the dispatcher bound
85
- # to the booted domain
86
- def boot(path, shared: nil, install_facade: true, environment: nil)
87
- Runtime.boot(path, shared: shared, install_facade: install_facade, environment: environment)
59
+ # @param install_doors [Boolean] install the `Widget::Item.Add`-style facade
60
+ # @param install_facade [Boolean, nil] the deprecated spelling of `install_doors`; warns
61
+ # @param environment [String, nil] env name; its `.hecksagon`/`.world` overlay,
62
+ # if present, loads after the domain's own. Defaults to `HECKS_ENVIRONMENT`; nil loads none
63
+ # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] dispatcher bound to the domain
64
+ def boot(path, shared: nil, install_doors: true, install_facade: nil, environment: Runtime::Loader::FROM_ENV)
65
+ Runtime.boot(path, shared: shared, install_doors: install_doors, environment: environment,
66
+ install_facade: install_facade)
88
67
  end
89
68
 
90
- # `paths` — an explicit list of files to boot (a `.bluebook`, its
91
- # `.hecksagon`, optionally a `.world`), loaded in place from wherever
92
- # they actually live — see Runtime::Loader.boot_files's own header for
93
- # why this exists beside `boot` rather than as a special case of it.
69
+ # Loads a domain's declarations without binding any adapter or opening any store.
94
70
  #
71
+ # @param path [String] path to a domain directory, or a file inside one
72
+ # @param shared [String, nil] a shared-root override; see `Runtime::Loader.describe`
73
+ # @param environment [String, nil] env overlay; defaults to `HECKS_ENVIRONMENT`
74
+ # @return [Runtime::Loader::Described] the loaded registry, answering `registry`
75
+ def describe(path, shared: nil, environment: Runtime::Loader::FROM_ENV)
76
+ Runtime.describe(path, shared: shared, environment: environment)
77
+ end
78
+
79
+ # Boots a domain from an explicit list of files (a `.bluebook`, its
80
+ # `.hecksagon`, optionally a `.world`) instead of a whole directory —
81
+ # see `Runtime::Loader.boot_files` for why this exists beside `boot`.
95
82
  # @param paths [String, Array<String>] one or more file paths within the domain
96
- # to load, instead of the whole directory
97
83
  # @param shared [String, nil] a shared-root override; see `Runtime::Loader.boot_files`
98
- # @param install_facade [Boolean] whether to install the `Widget::Item.Add`-style
99
- # Ruby facade constants for this boot
100
- # @param environment [String, nil] the environment name passed through to the
101
- # selected-file loader
102
- # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the dispatcher bound
103
- # to the booted domain
104
- def boot_files(paths, shared: nil, install_facade: true, environment: nil)
105
- Runtime.boot_files(paths, shared: shared, install_facade: install_facade, environment: environment)
84
+ # @param install_doors [Boolean] install the `Widget::Item.Add`-style facade
85
+ # @param install_facade [Boolean, nil] the deprecated spelling of `install_doors`; warns
86
+ # @param environment [String, nil] environment name passed to the selected-file loader
87
+ # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] dispatcher bound to the domain
88
+ def boot_files(paths, shared: nil, install_doors: true, install_facade: nil, environment: Runtime::Loader::FROM_ENV)
89
+ Runtime.boot_files(paths, shared: shared, install_doors: install_doors, environment: environment,
90
+ install_facade: install_facade)
106
91
  end
107
92
 
108
93
  # Binds the ambient registry for the duration of the block.
@@ -117,21 +102,8 @@ module Hecks
117
102
  # @return [Runtime::Registry, nil] the current registry, or nil outside a boot
118
103
  def current_registry = Runtime.current_registry
119
104
 
120
- # Bind who is dispatching for the duration of the block — checked
121
- # against a command's declared `role`, if it has one. Unbound (the
122
- # default), a command's role stays exactly what it is without this:
123
- # decoration.
124
- #
125
- # `actor_id` is optional — a caller naming only a role is checked by
126
- # string equality against the command's own `role`, exactly as
127
- # before. A caller that also names who it is lets the check run
128
- # against a real Governance `RoleAssignment` instead, once the
129
- # command's domain has Governance attached — see
130
- # `CommandRules::Authorization`'s own header.
131
- #
132
- # `as_of` and `scope` are optional too, same shape — see
133
- # `Runtime.as_caller`'s own header for what each does.
134
- #
105
+ # Binds who is dispatching for the duration of the block, checked against
106
+ # a command's declared `role`; unbound (the default) is a no-op.
135
107
  # @param role [String, Symbol] the role to check the caller against
136
108
  # @param actor_id [String, nil] who is calling, checked against a real Governance
137
109
  # `RoleAssignment` when given; string-equality only against `role` when nil
@@ -165,26 +137,16 @@ module Hecks
165
137
  # @return [Bluebook::Hecksagon] the built hecksagon
166
138
  # @raise [LoadOutsideBoot] if called outside `Hecks.boot`/`.boot_files`
167
139
  def hecksagon(name, &) = collect(:add_hecksagon, Bluebook::DSL::HecksagonBuilder.build(name, &))
168
- # Repointed to DomainPortBuilder — the migration DomainPort's own
169
- # class comment names as its goal, now landed for the top-level
170
- # `.port` file callers too (the aggregate-scoped `Thing.port(...)`,
171
- # binding_proxy.rb, already went through this builder). Every real
172
- # `.port` file only ever spells `verb`/`signal` (no `.port` file
173
- # declares operations — that's DomainPort's own newer shape), and
174
- # DomainPortBuilder's own bare-verb branch produces the exact same
175
- # `Port` object PortBuilder itself did (dsl_spec.rb's own byte-
176
- # identity check) — a pure repoint, no behavior change for any
177
- # existing caller reading `.verb`/`.signal` off what comes back.
140
+
141
+ # Declares a port — a `.port` file's top-level word.
142
+ #
143
+ # `legacy_bare_port: true` — only this entry point allows a completely
144
+ # empty port body; see `DomainPortBuilder#initialize`'s own doc.
178
145
  #
179
- # `legacy_bare_port: true` — the one real semantic gap this repoint
180
- # would otherwise open: `PortBuilder#build` never refused a
181
- # completely empty build (no verb, no signal even), a real shape
182
- # dsl_spec.rb's own "a port" tests exercise (`signal`-only, no
183
- # `verb`). `DomainPortBuilder`'s own "declares no verb and no
184
- # operations" refusal is real and correct for its other two callers
185
- # (`BindingProxy#port`, `HecksagonBuilder#port_impl`) — only this,
186
- # the literal top-level `.port` file entry point, keeps the older,
187
- # looser rule (see `DomainPortBuilder#initialize`'s own comment).
146
+ # @param name [String] the port's name
147
+ # @yield the port's body, evaluated against a `Bluebook::DSL::DomainPortBuilder`
148
+ # @return [Bluebook::Port, Bluebook::DomainPort] the built port
149
+ # @raise [LoadOutsideBoot] if called outside `Hecks.boot`/`.boot_files`
188
150
  def port(name, &) = collect(:add_port, Bluebook::DSL::DomainPortBuilder.build(name, legacy_bare_port: true, &))
189
151
 
190
152
  # Declares an adapter — an `.adapter` file's top-level word.
@@ -1,55 +1,15 @@
1
1
  module RuboCop
2
2
  module Cop
3
3
  module Hecks
4
- # Flags the exact shape behind 8+ real bugs already fixed one at a
5
- # time across this codebase (Tiers 1-5): `holder[a] || holder[b]` —
6
- # the same receiver looked up by two different keys, falling back to
7
- # the second lookup whenever the first is falsy. `||` cannot tell a
8
- # genuinely stored `false` from a missing key — both are falsy in
9
- # Ruby — so a real `false` sitting at `holder[a]` is silently
10
- # discarded and `holder[b]` (usually absent, so `nil`) is returned
11
- # instead. Every one of those 8+ instances was the identical
12
- # AST shape with a different pair of keys (most commonly
13
- # `h[k.to_sym] || h[k]`, reading a value that could arrive keyed
14
- # either by symbol or by string off the wire).
4
+ # Flags `holder[a] || holder[b]`: the same receiver looked up by two keys, falling back
5
+ # to the second when the first is falsy.
15
6
  #
16
- # ## The fix
17
- #
18
- # The fix this codebase already converged on — see
19
- # `lib/hecks/query_specification/field_path.rb#read`, the shared
20
- # digger this whole bug class got consolidated behind: check
21
- # `key?` first, never fall back through `||`.
22
- #
23
- # sym = segment.to_sym
24
- # return current.key?(sym) ? current[sym] : current[segment]
25
- #
26
- # That method's own comment says it plainly: "`key?` first, never
27
- # `||`, because `||` falls through a genuinely-stored `false` to
28
- # the other spelling (usually absent) and returns `nil` instead."
29
- # This cop exists so the next `holder[a] || holder[b]` gets caught
30
- # mechanically, before it becomes bug #9, rather than found by
31
- # hand again in a future audit.
32
- #
33
- # ## Scope
34
- #
35
- # Scoped to the `[]`/`[]` shape only, deliberately — a receiver
36
- # method-call is compared by AST structure (`==`, which ignores
37
- # source location), so `hash[a] || hash[b]` is flagged whether
38
- # `hash` is a local variable, a method call, or a constant, but
39
- # `a[k] || b[k]` (different receivers) and `value || default`
40
- # (an ordinary default, not a second lookup at all) are both left
41
- # alone — neither one can silently drop a stored `false` the way
42
- # a same-receiver double-lookup can.
7
+ # `||` cannot tell a stored `false` from a missing key, so a real `false` at `holder[a]` is
8
+ # discarded. Different receivers (`a[k] || b[k]`) and plain defaults are left alone.
43
9
  #
44
10
  # @example
45
- # # bad — a stored `false` at hash[:active] is discarded
46
- # hash[:active] || hash["active"]
47
- #
48
- # # good
49
- # hash.key?(:active) ? hash[:active] : hash["active"]
50
- #
51
- # # good — or the shared digger this codebase already has
52
- # Hecks::QuerySpecification::FieldPath.dig(hash, "active")
11
+ # hash[:active] || hash["active"] # bad
12
+ # hash.key?(:active) ? hash[:active] : hash["active"] # good
53
13
  class FallbackHashLookup < Base
54
14
  MSG = "`%<receiver>s[...] || %<receiver>s[...]` falls back to the second lookup " \
55
15
  "whenever the first is falsy — but `||` cannot tell a genuinely stored `false` " \
@@ -96,3 +56,5 @@ module RuboCop
96
56
  end
97
57
  end
98
58
  end
59
+
60
+ # AST `==` ignores source location, so two parses of the same receiver compare equal.
@@ -1,67 +1,17 @@
1
1
  module RuboCop
2
2
  module Cop
3
3
  module Hecks
4
- # Flags `hash[new] = hash.delete(old)` inside a loop — a method that
5
- # both reads and writes the same hash across a loop's iterations,
6
- # in the specific rename/permutation shape this codebase has
7
- # already lost real data to once.
8
- #
9
- # ## The bug this follows up on
10
- #
11
- # The bug this is the mechanical follow-up to (M27,
12
- # docs/audits/2026-08-10-main-bug-audit.md,
13
- # docs/audits/2026-08-11-bug-triage.md; fixed in
14
- # `Hecks::Ports::Persistence::Lineage#apply_renames`,
15
- # lib/hecks/ports/persistence/plugins/era/lineage.rb): a rename
16
- # rule set applied one rule at a time, `state[new_name] =
17
- # state.delete(old_name)` per rule, against the same hash it was
18
- # reading from — so a swap (`rename :a, to: :b` alongside `rename
19
- # :b, to: :a`) on `{a: 1, b: 2}` collapsed to `{a: 1}`. The first
20
- # rule wrote `b: 1` (clobbering the real `b: 2`) before the second
21
- # rule ever got a chance to read the value that was supposed to
22
- # move to `:a` — sequential edits stepping on each other, not the
23
- # simultaneous permutation a rename set actually means. The same
24
- # shape loses data identically for any chain longer than one link
25
- # (`a->b->c->a`), not just a two-element swap.
26
- #
27
- # ## The fix this cop points at
28
- #
29
- # Snapshot every old key's value
30
- # first, delete all old keys, then write all new keys, so no
31
- # rename in the pass ever reads a key this same pass has already
32
- # written:
33
- #
34
- # snapshot = renames.filter_map { |old_name, new_name| [old_name, new_name, state[old_name]]
35
- # if state.key?(old_name) }
36
- # snapshot.each { |old_name, _new_name, _value| state.delete(old_name) }
37
- # snapshot.each { |_old_name, new_name, value| state[new_name] = value }
38
- #
39
- # ## What this cop does not attempt
40
- #
41
- # The general checklist item is
42
- # broader than any AST pattern can safely automate ("any method
43
- # that both reads and writes the same collection across a loop"
44
- # covers plenty of correct code too — accumulating into a result
45
- # hash, memoizing into a cache). This cop stays narrow and
46
- # precise: only the exact `recv[x] = recv.delete(y)` shape, same
47
- # receiver both sides, inside something that iterates. A single
48
- # rename outside any loop is not this bug (nothing else can have
49
- # run first); `hash.store(...)` instead of `hash[...] =`, or
50
- # `hash.delete(...)` whose result is not immediately written back
51
- # into the same hash, are not this shape either and are left to
52
- # the broader code-review checklist item, not this cop.
4
+ # Flags `hash[new] = hash.delete(old)` inside a loop.
5
+ # Applying renames one at a time to the hash being read loses data on swaps and chains.
53
6
  #
54
7
  # @example
55
- # # bad — one rule at a time against the hash it reads from
56
- # renames.each do |old_name, new_name|
57
- # state[new_name] = state.delete(old_name)
58
- # end
8
+ # # bad
9
+ # renames.each { |old, new| state[new] = state.delete(old) }
59
10
  #
60
- # # good — snapshot first, then delete, then write: one permutation
61
- # snapshot = renames.filter_map { |old_name, new_name| [old_name, new_name, state[old_name]]
62
- # if state.key?(old_name) }
63
- # snapshot.each { |old_name, _new_name, _value| state.delete(old_name) }
64
- # snapshot.each { |_old_name, new_name, value| state[new_name] = value }
11
+ # # good: snapshot the values, delete every old key, then write the new keys
12
+ # pairs = renames.select { |old, _| state.key?(old) }.map { |old, new| [new, state[old]] }
13
+ # renames.each_key { |old| state.delete(old) }
14
+ # pairs.each { |new, value| state[new] = value }
65
15
  class SequentialHashRenameInLoop < Base
66
16
  MSG = "`%<recv>s[new] = %<recv>s.delete(old)` inside a loop applies one rename at a time against the " \
67
17
  "SAME hash it reads from — a swap (`{a: :b, b: :a}`) on `{a: 1, b: 2}` collapses to `{a: 1}` " \
@@ -78,22 +28,12 @@ module RuboCop
78
28
  inject reduce each_slice each_cons
79
29
  ].freeze
80
30
 
81
- # `hash[new_name] = hash.delete(old_name)` parses as a `send`
82
- # node (indexed assignment has no dedicated node type in Ruby's
83
- # own grammar): `(send recv :[]= new_key (send recv2 :delete
84
- # old_key))`. `$_recv`/`$_recv2` are captured (not merely
85
- # matched) so `same_receiver?` below can compare them
86
- # structurally — node-pattern has no built-in "same subtree
87
- # twice" backreference, so the equality check is real Ruby, not
88
- # the pattern itself.
31
+ # Indexed assignment parses as a `send`. Both receivers are captured because node-pattern
32
+ # has no backreference; `same_receiver?` compares them.
89
33
  def_node_matcher :rename_write?, <<~PATTERN
90
34
  (send $_recv :[]= _new_key (send $_recv2 :delete _old_key))
91
35
  PATTERN
92
36
 
93
- # Flags a `recv[new] = recv.delete(old)` write inside a loop, same receiver both sides.
94
- #
95
- # @param node [RuboCop::AST::SendNode] the `[]=` send node being visited
96
- # @return [void]
97
37
  def on_send(node)
98
38
  rename_write?(node) do |recv, recv2|
99
39
  next unless same_receiver?(recv, recv2)
@@ -105,20 +45,11 @@ module RuboCop
105
45
 
106
46
  private
107
47
 
108
- # Structural equality (type + children, recursively) — exactly
109
- # what `Parser::AST::Node#==` already gives, ignoring source
110
- # location, so `state` vs `state` (two separate `send(nil,
111
- # :state)` reader calls) and `@state` vs `@state` both count as
112
- # "the same collection", not just an identical local variable.
113
48
  def same_receiver?(recv, recv2)
114
49
  recv == recv2
115
50
  end
116
51
 
117
- # Walks every ancestor looking for something that iterates —
118
- # not just the immediate parent, since the offending assignment
119
- # may sit one or more non-loop nodes deep inside a loop's block
120
- # (an `if` guarding it, say) and still carries the exact same
121
- # hazard.
52
+ # Checks every ancestor: a guard node may sit between the assignment and the loop block.
122
53
  def in_loop?(node)
123
54
  node.each_ancestor(:block, :numblock, :for, :while, :until, :while_post, :until_post).any? do |ancestor|
124
55
  loop_ancestor?(ancestor)