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
@@ -4,67 +4,14 @@ require_relative "resolver"
4
4
  module Hecks
5
5
  module Bluebook
6
6
  module Expression
7
- # Walks the real Evaluator/Resolver AST (the same objects a live
8
- # dispatch parses `given`/`ensures`/invariant text into — see
9
- # docs/implemented/guides/running-a-runtime.md's "The expression
10
- # grammar") and emits plain, JSON-serializable Ruby Hashes, tagged
11
- # by `"op"`.
12
- #
13
- # ## Why this exists beside `rust/project/expr_emitter.rb`
14
- #
15
- # The same two-method walk `rust/project/expr_emitter.rb`'s own
16
- # `emit_bool`/`emit_resolver` already do, over the same AST — that
17
- # file's own methods build Rust source-code strings for `rust/
18
- # project`'s codegen (`rust/src/kernel::expr::Expr` literals, baked
19
- # into a generated domain's own compiled binary); this builds data
20
- # instead, for a genuinely different consumer with a genuinely
21
- # different constraint: `rust/host` can never link the `rust`
22
- # (kernel) crate at all (a real, load-bearing build constraint —
23
- # `reference_validate.rs`'s own header has the full reasoning: one
24
- # path dependency would statically bake every domain's generated
25
- # dispatch code into every Lambda binary), so a value object's own
26
- # `invariant` predicate has to travel as something `rust/host` can
27
- # deserialize and interpret itself, at runtime, from `ir.json` — the
28
- # exact same relationship `rust/project`'s own `Expr` literals
29
- # already have to the compiled kernel, one layer further out.
30
- #
31
- # ## Why it lives in core `lib/hecks`, not `rust/project/`
32
- #
33
- # `rust/project.rb` is a separate, downstream toolchain
34
- # (`lib/hecks/projector.rb`'s own header: "a whole separate Ruby
35
- # program"), never `require`d by core `lib/hecks/bluebook/*.rb`
36
- # files (confirmed: no core file does). `value_object.rb`'s own
37
- # `invariants:` IR emission needs this for every domain's ordinary
38
- # `to_h`/`ir.json` export — golden fixtures, `hecks-parse`'s parity
39
- # comparisons, and any deploy artifact, not only a `bin/project_rust`
40
- # run — so it belongs beside `Evaluator`/`Resolver` themselves, not
41
- # bolted onto a tool that only sometimes runs.
42
- #
43
- # ## Complete, not corpus-scoped
44
- #
45
- # Every node this grammar admits gets a real arm, the identical
46
- # "raise, don't silently drop" discipline `expr_emitter.rb`'s own
47
- # `emit_bool`/`emit_resolver` already hold to — even though, as of
48
- # this writing, no real corpus value object invariant exercises
49
- # `Include`/`Modulo`/`BlockPredicate`/`Find`/`Array`/`MatchesRegex`/
50
- # `Presence`/`Assignment`/`Split`/`StartsWith`/`EndsWith`/`First`/
51
- # `Last` (only `given`/`ensures` clauses do, elsewhere in the corpus
52
- # — a different consumer of this same grammar). `rust/host/src/
53
- # expr_json.rs`'s own header names exactly which of these its
54
- # interpreter evaluates for real today versus refuses cleanly — a
55
- # narrower, deliberate, documented boundary on the interpreting
56
- # side, not on this emitting side: an author is free to write any
57
- # real expression in a value object's own `invariant`, and this
58
- # always emits it faithfully; whether `rust/host` can yet check it
59
- # at mint time is that file's own question to answer, not this
60
- # one's to pre-empt by refusing to even try.
7
+ # Walks the Evaluator/Resolver AST and emits JSON-serializable Hashes tagged by `"op"`.
8
+ # Lives in core because rust/host cannot link the kernel crate and interprets this from
9
+ # ir.json.
61
10
  module AstJson
62
11
  module_function
63
12
 
64
- # **The closed op roster** — every `"op"` tag the walkers below can
65
- # emit, pinned so a reader (or a spec) can refuse a tag it does
66
- # not know instead of guessing. A new node kind is a new entry
67
- # here, a new arm below, and a new arm in every reader.
13
+ # The closed roster of `"op"` tags. A new node kind needs an entry here and an arm in
14
+ # each walker and reader; unhandled nodes raise rather than being dropped.
68
15
  OPS = %w[
69
16
  or and not compare include
70
17
  int float str bool nil array lookup
@@ -73,48 +20,20 @@ module Hecks
73
20
  matches_regex presence assignment split starts_with ends_with
74
21
  ].freeze
75
22
 
76
- # One rule row, the way every rule site emits it — description and
77
- # canonical text (what every reader has always had) plus the
78
- # structured form, derived from the same text. `ast` is a pure
79
- # function of `canonical`: the IR carries both so a reader that
80
- # only displays keeps the text, and a reader that evaluates never
81
- # re-parses it.
82
- #
83
- # @param rule [Bluebook::Given, Bluebook::Invariant] the rule to
84
- # render; `rule.ast` is used when already computed, otherwise
85
- # `rule.canonical` is parsed and emitted fresh
86
- # @return [Hash{Symbol => Object}] `:description` (`String`),
87
- # `:canonical` (`String`), and `:ast` (`Hash`, the JSON AST)
23
+ # One rule row: description, canonical text, and the AST derived from that text.
88
24
  def rule_row(rule)
89
25
  { description: rule.description, canonical: rule.canonical, ast: rule.ast || emit_predicate(rule.canonical) }
90
26
  end
91
27
 
92
28
  # Parses `canonical` and emits its JSON AST in one step.
93
- #
94
- # @param canonical [String] a canonical predicate source string
95
- # @return [Hash] the JSON-shaped boolean AST, tagged by `"op"`
96
29
  def emit_predicate(canonical)
97
30
  emit_bool(Evaluator.parse(canonical))
98
31
  end
99
32
 
100
- # C3.6 (docs/semantics/bluebook-semantics.md) — every `.match?`
101
- # pattern a rule carries is held to `PatternSubset`, exactly as an
102
- # attribute's own `pattern:` already is (`AttributeCollector#
103
- # refuse_unshared_pattern`): a regex whose meaning depends on the
104
- # engine reading it is a defect in the bluebook, refused at build.
105
- # Walks the emitted AST, so every rule site (givens, ensures,
106
- # invariants, preconditions, a policy's where) gets the one check.
33
+ # Holds every `.match?` pattern a rule carries to `PatternSubset`, as an attribute's
34
+ # `pattern:` is; walking the AST gives every rule site the one check.
107
35
  #
108
- # @param ast [Hash] a JSON AST node, as emitted by `emit_predicate`
109
- # or `emit_bool`
110
- # @param owner [String] the declaring bluebook's name, for the
111
- # refusal message
112
- # @param word [String] the rule's own kind and description
113
- # (such as `"given \"total is positive\""`), for the refusal
114
- # message
115
- # @return [Hash] `ast`, unchanged
116
- # @raise [Bluebook::DSL::Malformed] if any `matches_regex` node's
117
- # pattern uses a construct `PatternSubset` does not admit
36
+ # @raise [Bluebook::DSL::Malformed] if a `matches_regex` pattern is outside `PatternSubset`
118
37
  def refuse_unshared_patterns!(ast, owner:, word:)
119
38
  return ast if Hecks::Bluebook::MetaValidator.shadow_parsing? # frozen era text is history
120
39
 
@@ -132,30 +51,18 @@ module Hecks
132
51
  end
133
52
 
134
53
  # What a `lookup` path can never contain: a call's parentheses, or an argument list's
135
- # commas and spaces. Attribute names carry none of these, so a path that does is a method
136
- # call with arguments that the grammar has no node for.
54
+ # commas and spaces.
137
55
  #
138
- # A bare `?` is deliberately not in the set. `x.nil?` also parses as a lookup, but it loads
139
- # and, on a String, Boolean or `nil` value, evaluates without raising; real bluebooks
140
- # declare it, so refusing it would stop them loading.
56
+ # A bare `?` is deliberately not in the set: `x.nil?` also parses as a lookup, loads, and
57
+ # evaluates without raising, and real bluebooks declare it.
141
58
  UNRESOLVABLE_PATH = /[(),\s]/
142
59
  private_constant :UNRESOLVABLE_PATH
143
60
 
144
- # Refuses a rule that calls a method the expression grammar does not have.
145
- #
146
- # An unrecognised call such as `value.between?(100, 599)` parses as a `lookup` whose path
147
- # names an attribute that can never exist, so it loads and then fails on the first
148
- # dispatch. Refusing it here moves the failure to build time, where the author is looking.
149
- # The supported spellings (comparisons joined with `&&`/`||`, `.positive?`, `.empty?`,
150
- # `.include?`, ...) are the rows of `projection.json`.
61
+ # Refuses a rule that calls a method the grammar lacks, such as `value.between?(100, 599)`.
62
+ # It would parse as a `lookup` of an attribute that cannot exist and fail on first dispatch.
151
63
  #
152
- # @param ast [Hash] a JSON AST node, as emitted by `emit_predicate` or `emit_bool`
153
- # @param owner [String] the declaring bluebook's name, for the refusal message
154
- # @param word [String] the rule's own kind and description (such as
155
- # `"invariant \"a status code\""`), for the refusal message
156
- # @return [Hash] `ast`, unchanged
157
- # @raise [Bluebook::DSL::Malformed] if any `lookup` node's path contains a parenthesis,
158
- # comma or whitespace
64
+ # @raise [Bluebook::DSL::Malformed] if a `lookup` path contains a parenthesis, comma or
65
+ # space
159
66
  def refuse_unresolvable_lookups!(ast, owner:, word:)
160
67
  return ast if Hecks::Bluebook::MetaValidator.shadow_parsing? # frozen era text is history
161
68
 
@@ -174,13 +81,7 @@ module Hecks
174
81
  ast
175
82
  end
176
83
 
177
- # Every name a rule resolves at its root — the first segment of
178
- # each `lookup` path, unique, in first-seen order.
179
- #
180
- # @param ast [Hash] a JSON AST node, as emitted by `emit_predicate`
181
- # or `emit_bool`
182
- # @return [Array<String>] each `lookup` node's root name, unique,
183
- # in first-seen order
84
+ # Every name a rule resolves at its root: the first segment of each `lookup` path, unique.
184
85
  def lookup_heads(ast)
185
86
  heads = []
186
87
  each_node(ast) do |node|
@@ -189,13 +90,7 @@ module Hecks
189
90
  heads.uniq
190
91
  end
191
92
 
192
- # Visits `node` and every Hash node nested inside it, depth-first.
193
- #
194
- # @param node [Hash, Array, Object] a JSON AST node, or an Array or
195
- # scalar value found while walking one; a scalar is a silent no-op
196
- # @yieldparam node [Hash] each Hash node reached, including `node`
197
- # itself
198
- # @return [void]
93
+ # Visits `node` and every Hash nested inside it, depth-first.
199
94
  def each_node(node, &block)
200
95
  case node
201
96
  when ::Hash
@@ -207,16 +102,6 @@ module Hecks
207
102
  end
208
103
 
209
104
  # Emits the JSON form of one boolean-position Evaluator node.
210
- #
211
- # @param node [Bluebook::Expression::Evaluator::Or,
212
- # Bluebook::Expression::Evaluator::And,
213
- # Bluebook::Expression::Evaluator::Not,
214
- # Bluebook::Expression::Evaluator::Compare,
215
- # Bluebook::Expression::Evaluator::Include,
216
- # Bluebook::Expression::Evaluator::Resolve] the boolean-position
217
- # AST node to emit
218
- # @return [Hash] the JSON AST for `node`, tagged by `"op"`
219
- # @raise [RuntimeError] if `node` is not one of the handled classes
220
105
  def emit_bool(node)
221
106
  case node
222
107
  when Evaluator::Or then { "op" => "or", "left" => emit_bool(node.left), "right" => emit_bool(node.right) }
@@ -236,36 +121,16 @@ module Hecks
236
121
  end
237
122
 
238
123
  # Emits the JSON form of one comparison operator.
239
- #
240
- # @param comparator [Bluebook::Expression::Evaluator::Operator] the
241
- # operator to emit
242
- # @return [Hash{String => Boolean}] `"less_than"`, `"equal"`, and
243
- # `"negated"`, exactly as `comparator` carries them
244
124
  def emit_comparison(comparator)
245
125
  { "less_than" => comparator.compares_less_than, "equal" => comparator.compares_equal, "negated" => comparator.negated }
246
126
  end
247
127
 
248
- # The JSON-target sibling of `expr_emitter.rb`'s own
249
- # `emit_include` — see that method's own comment for the full
250
- # reasoning (a literal array haystack has no `Expr::Include`-
251
- # representable shape on either target, kernel or host, so both
252
- # rewrite it identically into an or-of-equalities at emission
253
- # time rather than carrying a shape neither interpreter could
254
- # evaluate). A non-literal haystack still emits `include`
255
- # unchanged.
128
+ # Mirrors `expr_emitter.rb`'s `emit_include`: no target can represent a literal-array
129
+ # haystack in `include`, so it is rewritten to an or of equalities at emission.
256
130
  EQ = Evaluator::OPERATORS.find { |op| op.symbol == "==" }
257
131
  private_constant :EQ
258
132
 
259
- # Emits the JSON form of one `include` node.
260
- #
261
- # @param node [Bluebook::Expression::Evaluator::Include] the
262
- # `include` node to emit
263
- # @return [Hash] the JSON AST: `{"op" => "include", ...}` for a
264
- # non-literal haystack, `{"op" => "bool", "value" => false}` for
265
- # an empty literal array haystack, or an `"or"`-of-`"compare"`
266
- # tree of equalities for a non-empty literal array haystack
267
- # @raise [RuntimeError] if `node.haystack`, `node.needle`, or one of
268
- # the haystack's literal elements is an unhandled resolver node
133
+ # Emits one `include` node; an empty literal haystack is `false`.
269
134
  def emit_include(node)
270
135
  return { "op" => "include", "haystack" => emit_resolver(node.haystack), "needle" => emit_resolver(node.needle) } \
271
136
  unless node.haystack.is_a?(Resolver::ArrayLiteral)
@@ -279,38 +144,8 @@ module Hecks
279
144
  equalities.reduce { |left, right| { "op" => "or", "left" => left, "right" => right } }
280
145
  end
281
146
 
282
- # One case arm per Resolver node type — the class header above is
283
- # explicit that this dispatch must stay complete and in one place
284
- # ("every node this grammar admits gets a real arm"); splitting it
285
- # into several methods would hide whether the set is still
286
- # exhaustive instead of making that visible at a glance.
287
- #
288
- # @param node [Bluebook::Expression::Resolver::IntegerLiteral,
289
- # Bluebook::Expression::Resolver::FloatLiteral,
290
- # Bluebook::Expression::Resolver::StringLiteral,
291
- # Bluebook::Expression::Resolver::BoolLiteral,
292
- # Bluebook::Expression::Resolver::NilLiteral,
293
- # Bluebook::Expression::Resolver::Lookup,
294
- # Bluebook::Expression::Resolver::Addition,
295
- # Bluebook::Expression::Resolver::SignTest,
296
- # Bluebook::Expression::Resolver::Empty,
297
- # Bluebook::Expression::Resolver::ToS,
298
- # Bluebook::Expression::Resolver::Modulo,
299
- # Bluebook::Expression::Resolver::Size,
300
- # Bluebook::Expression::Resolver::BlockPredicate,
301
- # Bluebook::Expression::Resolver::Find,
302
- # Bluebook::Expression::Resolver::ArrayLiteral,
303
- # Bluebook::Expression::Resolver::MatchesRegex,
304
- # Bluebook::Expression::Resolver::Presence,
305
- # Bluebook::Expression::Resolver::Assignment,
306
- # Bluebook::Expression::Resolver::Split,
307
- # Bluebook::Expression::Resolver::StartsWith,
308
- # Bluebook::Expression::Resolver::EndsWith,
309
- # Bluebook::Expression::Resolver::First,
310
- # Bluebook::Expression::Resolver::Last] the value-position AST
311
- # node to emit
312
- # @return [Hash] the JSON AST for `node`, tagged by `"op"`
313
- # @raise [RuntimeError] if `node` is not one of the handled classes
147
+ # One case arm per Resolver node type, kept in one method so exhaustiveness shows at a
148
+ # glance.
314
149
  # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
315
150
  def emit_resolver(node)
316
151
  case node
@@ -319,8 +154,7 @@ module Hecks
319
154
  when Resolver::StringLiteral then { "op" => "str", "value" => node.value }
320
155
  when Resolver::BoolLiteral then { "op" => "bool", "value" => node.value }
321
156
  when Resolver::NilLiteral then { "op" => "nil" }
322
- # `path` is the same shape `find.path` already has — segments, not
323
- # a dotted string a reader would have to split by its own rule.
157
+ # Segments, as `find.path` has, so a reader need not split a dotted string.
324
158
  when Resolver::Lookup then { "op" => "lookup", "path" => node.path.split(".") }
325
159
  when Resolver::Addition then { "op" => "add", "left" => emit_resolver(node.left), "right" => emit_resolver(node.right) }
326
160
  when Resolver::SignTest
@@ -4,41 +4,20 @@ require_relative "resolver"
4
4
  module Hecks
5
5
  module Bluebook
6
6
  module Expression
7
- # The inverse of `AstJson` — reads the `"op"`-tagged JSON a rule row
8
- # carries as `ast` back into the same `Evaluator`/`Resolver` node
9
- # Structs `Evaluator.parse` builds from `canonical`. This is how the
10
- # runtime evaluates a rule without re-parsing its text: the one
11
- # parse happened at DSL-build time, behind `AstJson`; dispatch walks
12
- # the structured form (`Evaluator.call_rule`), and `canonical` stays
13
- # what it always displayed as — text for humans and refusal wording.
14
- #
15
- # Written as the obvious mirror of `ast_json.rb`'s two walkers, arm
16
- # for arm, so a new op there is a new arm here and
17
- # spec/expression_ast_spec.rb's roster contract fails until it
18
- # lands. Promoted from spec/support once the runtime switched —
19
- # the spec proved the round trip first, then the runtime adopted it.
20
- #
21
- # One deliberate asymmetry, inherited: `AstJson` rewrites a
22
- # literal-array `.include?` into an or of equalities (see
23
- # `emit_include`), so reading never produces an `Include` over an
24
- # `ArrayLiteral`. Evaluation is unchanged by that rewrite, which is
25
- # exactly what the equivalence spec pins.
7
+ # The inverse of `AstJson`: reads a rule row's `"op"`-tagged `ast` back into the
8
+ # `Evaluator`/`Resolver` nodes, so dispatch evaluates a rule without re-parsing its text.
26
9
  module AstReader
27
10
  module_function
28
11
 
29
- # Reads a whole predicate's own `"op"`-tagged JSON back into its AST.
30
- #
31
- # @param json [Hash{String => Object}] the `"op"`-tagged JSON a rule row's own
32
- # `ast` carries
33
- # @return [Evaluator::Or, Evaluator::And, Evaluator::Not, Evaluator::Compare,
34
- # Evaluator::Include, Evaluator::Resolve] the boolean/comparison AST node
12
+ # Arm for arm with `AstJson`: a new op there fails spec/expression_ast_spec.rb until added
13
+ # here.
14
+ # A literal-array `.include?` is emitted as an or of equalities, so it never reads back as
15
+ # an `Include` over an `ArrayLiteral`; evaluation is unchanged.
16
+
17
+ # Reads a whole predicate's `"op"`-tagged JSON back into its AST.
35
18
  def read_predicate(json) = read_bool(json)
36
19
 
37
20
  # Reads one boolean/comparison node, recursing into its own children.
38
- #
39
- # @param json [Hash{String => Object}] the `"op"`-tagged JSON for one node
40
- # @return [Evaluator::Or, Evaluator::And, Evaluator::Not, Evaluator::Compare,
41
- # Evaluator::Include, Evaluator::Resolve] the boolean/comparison AST node
42
21
  def read_bool(json)
43
22
  case json.fetch("op")
44
23
  when "or" then Evaluator::Or.new(left: read_bool(json["left"]), right: read_bool(json["right"]))
@@ -53,14 +32,8 @@ module Hecks
53
32
  end
54
33
  end
55
34
 
56
- # The comparator algebra travels as its three-flag triple; the
57
- # `Operator` carrying that exact triple is the one `parse` would
58
- # have chosen, because the roster (`expression/projection.json`)
59
- # holds one symbol per triple.
60
- #
61
- # @param cmp [Hash{String => Boolean}] `{"less_than"=>, "equal"=>, "negated"=>}`
62
- # @return [Evaluator::Operator] the operator carrying that exact triple
63
- # @raise [RuntimeError] if no operator in `Evaluator::OPERATORS` has that triple
35
+ # The roster (`expression/projection.json`) holds one symbol per flag triple,
36
+ # so the triple identifies the operator `parse` would have chosen.
64
37
  def operator(cmp)
65
38
  Evaluator::OPERATORS.find do |op|
66
39
  op.compares_less_than == cmp.fetch("less_than") &&
@@ -70,14 +43,6 @@ module Hecks
70
43
  end
71
44
 
72
45
  # Reads one dotted/arithmetic leaf node, recursing into its own children.
73
- #
74
- # @param json [Hash{String => Object}] the `"op"`-tagged JSON for one leaf node
75
- # @return [Object] a `Resolver` AST node — one of `IntegerLiteral`, `FloatLiteral`,
76
- # `StringLiteral`, `BoolLiteral`, `NilLiteral`, `ArrayLiteral`, `Lookup`,
77
- # `Addition`, `SignTest`, `Empty`, `ToS`, `Modulo`, `Size`, `First`, `Last`,
78
- # `BlockPredicate`, `Find`, `MatchesRegex`, `Presence`, `Assignment`, `Split`,
79
- # `StartsWith`, or `EndsWith`
80
- # @raise [RuntimeError] if `json["op"]` names no known resolver op
81
46
  # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity -- one arm
82
47
  # per AstJson op is the point; splitting the case would hide the roster.
83
48
  def read_resolver(json)
@@ -118,15 +83,8 @@ module Hecks
118
83
  end
119
84
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
120
85
 
121
- # `SignTest#test` is only wording (the refusal names it); the
122
- # triple is what evaluates. Recover the spelling from the
123
- # vocabulary so a rebuilt node refuses with the same message the
124
- # parsed one would.
125
- #
126
- # @param operator [Evaluator::Operator] the comparison operator a sign test's own
127
- # triple resolved to
128
- # @return [String] the sign test's own vocabulary name, or `operator.symbol` when
129
- # no sign test shares its triple
86
+ # `SignTest#test` is only refusal wording; recovering it keeps a rebuilt node's message
87
+ # identical to the parsed one's.
130
88
  def sign_test_name(operator)
131
89
  Resolver::SIGN_TEST_OPERATORS.key(operator.symbol) || operator.symbol
132
90
  end
@@ -4,35 +4,21 @@ require_relative "../../vocabulary"
4
4
  module Hecks
5
5
  module Bluebook
6
6
  module Expression
7
- # Rewrites a predicate's source text into one canonical spelling
8
- # before it's ever parsed or hashed — collapsing whitespace and
9
- # folding admitted synonyms (e.g. `.length` → `.size`) via the
10
- # `RULES` table projected from the grammar chapter, so two byte-
11
- # different but equivalent predicates compare and cache identically.
12
- # Never touches text inside quoted string literals
13
- # (`map_outside_strings`).
7
+ # Rewrites predicate source into one canonical spelling (whitespace, admitted synonyms)
8
+ # so equivalent predicates compare and hash alike. Quoted string literals are left alone.
14
9
  module CanonicalForm
15
10
  Rule = Struct.new(:strategy, :source_token, :replacement, :boundary, :position, keyword_init: true)
16
11
 
17
12
  STRATEGIES = Hecks::Vocabulary.fetch("NormalisationStrategy")
18
13
 
19
- # **Read, not restated** — the admitted normalisation rules, projected
20
- # from the grammar chapter by bin/expression_projection exactly as
21
- # the evaluator's operator table is. See Evaluator::PROJECTION for
22
- # why a projection rather than a boot.
14
+ # Normalisation rules projected from the grammar chapter by hecks project_expression_tables.
23
15
  RULES = JSON.parse(
24
16
  File.read(File.join(__dir__, "projection.json")), symbolize_names: true
25
17
  ).fetch(:normalisations).map { |row| Rule.new(**row) }.freeze
26
18
 
27
19
  module_function
28
20
 
29
- # Returns the admitted normalisation rules as plain Hashes, for
30
- # embedding in a bluebook's read-back contract.
31
- #
32
- # @return [Array<Hash{Symbol => String}>] one hash per rule, in
33
- # declared `position` order, with keys `:strategy`,
34
- # `:source_token`, `:replacement`, `:boundary`, and `:position`
35
- # (stringified)
21
+ # The normalisation rules as plain Hashes, in `position` order, for a read-back contract.
36
22
  def table
37
23
  RULES.sort_by(&:position).map do |rule|
38
24
  {
@@ -45,25 +31,11 @@ module Hecks
45
31
  end
46
32
  end
47
33
 
48
- # Rewrites `source` into its canonical spelling by applying every
49
- # admitted `RULES` entry, in declared `position` order.
50
- #
51
- # @param source [String] the raw predicate source to normalise
52
- # @return [String] the canonicalised text, stripped of leading and
53
- # trailing whitespace
34
+ # Applies every `RULES` entry to `source` in `position` order; returns the stripped result.
54
35
  def apply(source)
55
36
  RULES.sort_by(&:position).reduce(source.to_s) { |text, rule| step(text, rule) }.strip
56
37
  end
57
38
 
58
- # Applies one normalisation `rule` to `text`, dispatching on the
59
- # rule's strategy.
60
- #
61
- # @param text [String] the source text (or string-literal segment) to
62
- # transform
63
- # @param rule [Rule] the normalisation rule to apply
64
- # @return [String] `text` after the rule is applied
65
- # @raise [ArgumentError] if `rule.strategy` names a strategy this
66
- # method does not implement
67
39
  def step(text, rule)
68
40
  case rule.strategy
69
41
  when "collapse_whitespace" then map_outside_strings(text) { |segment| segment.gsub(/\s+/, " ") }
@@ -73,14 +45,6 @@ module Hecks
73
45
  end
74
46
  end
75
47
 
76
- # Substitutes every occurrence of `rule.source_token` in `text` with
77
- # `rule.replacement`, honoring the rule's word-boundary setting.
78
- #
79
- # @param text [String] the source text (or string-literal segment) to
80
- # transform
81
- # @param rule [Rule] the `"replace"`-strategy rule supplying the
82
- # token, replacement, and boundary
83
- # @return [String] `text` with the substitution applied
84
48
  def replace(text, rule)
85
49
  map_outside_strings(text) do |segment|
86
50
  if rule.boundary == "none"
@@ -91,30 +55,9 @@ module Hecks
91
55
  end
92
56
  end
93
57
 
94
- # Applies the given block to the text outside quoted string literals
95
- # only, copying every quoted run through byte-for-byte. Every rule
96
- # here (collapse_whitespace, the `.length`→`.size` fold) must stay
97
- # quote-aware: run it quote-blind and `"a b"` collapses to `"a b"`,
98
- # `"a.length"` folds to `"a.size"`, just as readily as the real
99
- # source outside the quotes — silently rewriting what a predicate
100
- # compares a string attribute against, not merely how the predicate
101
- # itself is spelled. A canonical string literal's contents are data,
102
- # never syntax to normalise.
103
- #
104
- # Handles both `"` and `'` delimiters (this grammar's own
105
- # `Resolver.quoted?` admits either), quote-aware exactly the way
106
- # `Evaluator.top_level_index`/`Resolver.array_elements` already are
107
- # elsewhere in this sublanguage. An unterminated quote (malformed
108
- # input) is passed through raw rather than risk mangling it further.
109
- #
110
- # @param text [String] the source text to scan for quoted string
111
- # literals
112
- # @yieldparam segment [String] a run of `text` outside any quoted
113
- # literal
114
- # @yieldreturn [String] the transformed replacement for `segment`
115
- # @return [String] `text` with the block applied to every unquoted
116
- # run, and every quoted run (`"`- or `'`-delimited) copied through
117
- # unchanged
58
+ # Yields each run of `text` outside quoted literals, copying quoted runs through verbatim.
59
+ # Quote-blind rewriting would change what a predicate compares a string against.
60
+ # Handles `"` and `'`; an unterminated quote is passed through raw.
118
61
  def map_outside_strings(text)
119
62
  result = +""
120
63
  buffer = +""
@@ -130,29 +73,9 @@ module Hecks
130
73
  end
131
74
  elsif ['"', "'"].include?(char)
132
75
  result << yield(buffer)
133
- # `char.dup`, not `char.to_s` (a no-op on a String — always
134
- # returns self, never a copy) and not `+char` either
135
- # (`String#+@` only dups a frozen receiver; `each_char`'s
136
- # yielded strings aren't frozen, so `+char` is just as
137
- # much a no-op here). Without a real copy, `buffer` and
138
- # `quote` alias the same mutable object: the very next
139
- # `buffer << char` grows `quote` right along with it, so
140
- # `char == quote` can only ever compare a single character
141
- # against an ever-lengthening string and never closes the
142
- # literal — everything after a predicate's first quoted
143
- # string silently skipped normalisation for the rest of
144
- # the text, undetected because passing text through
145
- # unnormalised is silent. Masked by every existing spec
146
- # here, which only checks that quoted contents survive
147
- # untouched (the M7 fix this method exists for) — that
148
- # still holds by accident once the bug makes the "outside"
149
- # branch unreachable. Found live: a multi-line `given`/
150
- # `ensures` block whose only quoted literal closes before a
151
- # later line — the newline and that later line's own
152
- # indentation went uncollapsed, diverging from
153
- # `hecks-parse`'s own (correct) single-space join.
154
- # `spec/parser_parity_spec.rb`, roster's "a front-row seat
155
- # takes a member of age".
76
+ # Must be a real copy: aliasing `buffer` and `quote` makes `buffer << char` grow
77
+ # `quote`, so the literal never closes and later text skips normalisation.
78
+ # Pinned by spec/parser_parity_spec.rb (multi-line `given`/`ensures`).
156
79
  buffer = char.dup
157
80
  quote = char.dup
158
81
  else