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,50 +4,21 @@ require_relative "vocabulary"
4
4
 
5
5
  module Hecks
6
6
  module Projections
7
- # The language's closed sets, projected into the Rust kernel — one
8
- # `rust/src/kernel/vocab/<table>.rs` per Vocabulary table, each a
9
- # `pub enum` plus `match`-based accessors with no wildcard arm, so a
10
- # row the chapter gains is a compile error at every exhaustive match
11
- # over it rather than a silent gap.
7
+ # The language's closed sets as Rust enums, one `rust/src/kernel/vocab/<table>.rs` per table,
8
+ # matched with no wildcard arm so a new row fails to compile until it is handled.
12
9
  #
13
10
  # Projector.call(:rust_vocabulary, bluebook: <the Bluebook chapter>)
14
11
  # # => { "vocab/mod.rs" => "...", "vocab/refusal_template.rs" => "...", ... }
15
- #
16
- # Paths are relative to rust/src/kernel/; bin/project_rust_vocabulary
17
- # writes them. This generalizes the old bin/project_refusal_wording,
18
- # which read Runtime::RefusalWording::TEMPLATES — a hand-typed copy of
19
- # the RefusalTemplate rows. This reads the chapter itself.
20
- #
21
- # ## Only `TABLES` the kernel needs
22
- #
23
- # Each entry in `TABLES` names its enum and its generated extras; a
24
- # table not listed is not projected. The enum names that differ from
25
- # the table name keep existing Rust call sites (`RefusalSite`) and the
26
- # dispatch-step names D1 consumes (`AggregateStep`, `EntityStep`).
27
- #
28
- # ## Typed refusal arguments
29
- #
30
- # The templates table also reads RefusalSiteArgument: every site gets a
31
- # `<Variant>Args` struct whose fields are exactly the site's declared
32
- # arguments (a `&str` per scalar, a `&[&str]` per list) and a
33
- # `render_args` that formats each one by its row. `render` itself stays
34
- # private to the generated module, so no call site can pass an argument
35
- # list by hand — leaving one out does not compile. The generated test
36
- # pins every site's `render_args` output (empty, single and multiple
37
- # unsorted lists) against Runtime::RefusalWording.render_with, computed
38
- # here in Ruby.
39
12
  module RustVocabulary
40
13
  extend Projector::Target
41
14
 
42
15
  projects_as :rust_vocabulary, declares: "Vocabulary", emits: :files
43
16
 
44
- GENERATOR = "bin/project_rust_vocabulary".freeze
17
+ GENERATOR = "hecks project_rust_vocabulary".freeze
45
18
  SOURCE = "lib/hecks/language/bluebook/vocabulary.bluebook".freeze
46
19
 
47
- # table name => enum name, variant-naming fields, file stem, kind.
48
- # `:order` tables also get `ORDER` and `position`; `:templates`
49
- # gets `render`, the typed `<Variant>Args` (read off the `arguments`
50
- # table) and the placeholder and argument-rendering tests.
20
+ # Table name => enum name, variant-naming fields, file stem and kind.
21
+ # `:order` adds `position`; `:templates` adds `render` and the typed `<Variant>Args`.
51
22
  TABLES = {
52
23
  "RefusalTemplate" => { enum: "RefusalSite", variant_from: %w[refusal site], file: "refusal_template",
53
24
  kind: :templates, arguments: "RefusalSiteArgument" },
@@ -65,24 +36,8 @@ module Hecks
65
36
 
66
37
  module_function
67
38
 
68
- # The projector protocol.
69
- #
70
- # @param bluebook [Bluebook::Behaviour::Chapter] the chapter declaring the
71
- # Vocabulary aggregate to project
72
- # @param options [Hash] unused; accepted to satisfy the registry's call shape
73
- # @return [Hash{String => String}] each generated file's path, relative to
74
- # `rust/src/kernel/`, mapped to its full Rust source
75
39
  def call(bluebook:, options: {}) = render(bluebook)
76
40
 
77
- # Renders every file `TABLES` projects: `vocab/mod.rs` plus one `.rs` file
78
- # per table, each an exhaustive enum with accessors and a pinned test module.
79
- #
80
- # @param bluebook [Bluebook::Behaviour::Chapter] the chapter declaring the
81
- # Vocabulary aggregate to render
82
- # @return [Hash{String => String}] each generated file's path, relative to
83
- # `rust/src/kernel/`, mapped to its full Rust source
84
- # @raise [ArgumentError] if `bluebook` does not declare a `TABLES`-named table,
85
- # or the `:arguments` table a `:templates` entry names
86
41
  def render(bluebook)
87
42
  tables = Vocabulary.tables(bluebook)
88
43
  files = TABLES.to_h do |table, spec|
@@ -95,11 +50,6 @@ module Hecks
95
50
  { "vocab/mod.rs" => mod_file }.merge(files)
96
51
  end
97
52
 
98
- # The generated-file banner every projected file opens with.
99
- #
100
- # @param table [String] the Vocabulary table name being projected, such as
101
- # `"RefusalTemplate"`
102
- # @return [String] the banner, as Rust line comments
103
53
  def header(table)
104
54
  <<~RUST
105
55
  // GENERATED by #{GENERATOR} (Hecks::Projections::RustVocabulary,
@@ -109,10 +59,6 @@ module Hecks
109
59
  RUST
110
60
  end
111
61
 
112
- # Renders `vocab/mod.rs`, the entry point that re-exports every projected enum.
113
- #
114
- # @return [String] `vocab/mod.rs`'s full source: one `pub mod` and `pub use`
115
- # per entry in `TABLES`
116
62
  def mod_file
117
63
  mods = TABLES.values.map { |spec| "pub mod #{spec[:file]};" }.join("\n")
118
64
  exports = TABLES.values.map { |spec| "pub use #{spec[:file]}::#{spec[:enum]};" }.join("\n")
@@ -132,18 +78,6 @@ module Hecks
132
78
  RUST
133
79
  end
134
80
 
135
- # One table's full `.rs` source: its exhaustive enum, per-field accessors,
136
- # `from_name`, its `:order`/`:templates` extras, and its `#[cfg(test)]` module.
137
- #
138
- # @param table [String] the Vocabulary table name, such as `"RefusalTemplate"`
139
- # @param spec [Hash] the table's `TABLES` entry (`:enum`, `:variant_from`,
140
- # `:file`, `:kind`, and, for `:templates`, `:arguments`)
141
- # @param rows [Array<Hash{String => String}>] the table's rows, as read off
142
- # the chapter by `Vocabulary.tables`
143
- # @param argument_rows [Array<Hash{String => String}>, nil] the
144
- # `RefusalSiteArgument` rows, only when `spec[:kind] == :templates`
145
- # @return [String] the table's full `.rs` file source
146
- # @raise [ArgumentError] if two rows would generate the same enum variant name
147
81
  def table_file(table, spec, rows, argument_rows = nil)
148
82
  variants = rows.map { |row| variant_name(row, spec[:variant_from]) }
149
83
  duplicates = variants.tally.select { |_, count| count > 1 }.keys
@@ -172,14 +106,6 @@ module Hecks
172
106
  "#{body.flatten.join("\n").rstrip}\n"
173
107
  end
174
108
 
175
- # Renders the enum's declared-order constant: `ORDER` for `:order`, `ALL` otherwise.
176
- #
177
- # @param enum [String] the Rust enum name, such as `"RefusalSite"`
178
- # @param variants [Array<String>] each row's generated variant name, in
179
- # declared order
180
- # @param kind [Symbol] the table's `:kind` (`:order`, `:templates`, or `:set`)
181
- # @return [Array<String>] the lines declaring the enum's `ORDER` constant
182
- # (`:order`) or `ALL` constant (otherwise)
183
109
  def constants(enum, variants, kind)
184
110
  list = variants.map { |variant| " #{enum}::#{variant}," }
185
111
  if kind == :order
@@ -191,16 +117,6 @@ module Hecks
191
117
  end
192
118
  end
193
119
 
194
- # Renders one field's `pub fn` accessor, an exhaustive match over every variant.
195
- #
196
- # @param enum [String] the Rust enum name
197
- # @param field [String] the row field this accessor reads, such as `"name"`
198
- # @param variants [Array<String>] each row's generated variant name, in
199
- # declared order, matching `rows`
200
- # @param rows [Array<Hash{String => String}>] the table's rows, in the same
201
- # order as `variants`
202
- # @return [Array<String>] the lines for the field's `pub fn` accessor, one
203
- # match arm per variant
204
120
  def accessor(enum, field, variants, rows)
205
121
  arms = variants.zip(rows).map { |variant, row| " #{enum}::#{variant} => #{rust_string(row.fetch(field))}," }
206
122
  [" /// The row's declared `#{field}`.",
@@ -212,12 +128,7 @@ module Hecks
212
128
  ""]
213
129
  end
214
130
 
215
- # Built on the enum's own list and name accessor, not a string
216
- # match, so it needs no wildcard arm either.
217
- #
218
- # @param enum [String] the Rust enum name
219
- # @param kind [Symbol] the table's `:kind` (`:order`, `:templates`, or `:set`)
220
- # @return [Array<String>] the lines for the enum's `from_name` associated function
131
+ # Built on the enum's own list and name accessor, not a string match, so no wildcard arm.
221
132
  def from_name(enum, kind)
222
133
  list = kind == :order ? "ORDER" : "ALL"
223
134
  field = kind == :templates ? "site" : name_field(kind)
@@ -228,14 +139,6 @@ module Hecks
228
139
  ""]
229
140
  end
230
141
 
231
- # Renders the extra methods a table's `:kind` adds beyond the shared accessors.
232
- #
233
- # @param enum [String] the Rust enum name
234
- # @param variants [Array<String>] each row's generated variant name, in
235
- # declared order
236
- # @param kind [Symbol] the table's `:kind` (`:order`, `:templates`, or `:set`)
237
- # @return [Array<String>] `:order`'s `position` method, `:templates`'s private
238
- # `render` method, or `[]` for `:set`
239
142
  def extras(enum, variants, kind)
240
143
  case kind
241
144
  when :order
@@ -263,20 +166,8 @@ module Hecks
263
166
  end
264
167
  end
265
168
 
266
- # [refusal, site] => that site's argument rows, in declared order —
267
- # refused unless they name exactly the template's own placeholders,
268
- # in the order each first appears, with only known formatting rules.
269
- #
270
- # @param rows [Array<Hash{String => String}>] the `RefusalTemplate` rows,
271
- # in declared order
272
- # @param argument_rows [Array<Hash{String => String}>] the `RefusalSiteArgument`
273
- # rows for every site
274
- # @return [Hash{Array<String> => Array<Hash{String => String}>}] each
275
- # `[refusal, site]` pair mapped to its declared argument rows, in declared order
276
- # @raise [ArgumentError] if an argument row names a `refusal`/`site` no
277
- # `RefusalTemplate` row declares, if a site's declared arguments do not match
278
- # its template's `{placeholder}`s in order, or if `check_rule!` rejects a
279
- # row's `"shape"`, `"quoting"`, or `"sorted"` value
169
+ # [refusal, site] => that site's argument rows; refused unless they name exactly the
170
+ # template's placeholders, in first-appearance order, with known formatting rules.
280
171
  def site_arguments(rows, argument_rows)
281
172
  grouped = argument_rows.group_by { |row| [row.fetch("refusal"), row.fetch("site")] }
282
173
  orphans = grouped.keys - rows.map { |row| [row.fetch("refusal"), row.fetch("site")] }
@@ -296,18 +187,6 @@ module Hecks
296
187
  end
297
188
  end
298
189
 
299
- # Refuses a `RefusalSiteArgument` row whose formatting fields are not
300
- # recognized rules.
301
- #
302
- # @param key [Array<String>] the `[refusal, site]` pair `spec` belongs to,
303
- # used in the raised message
304
- # @param spec [Hash{String => String}] one `RefusalSiteArgument` row
305
- # (`"shape"`, `"quoting"`, `"sorted"`)
306
- # @return [void]
307
- # @raise [ArgumentError] if `spec`'s `"shape"` is not in
308
- # `Runtime::RefusalWording::SHAPES`, its `"quoting"` is not in
309
- # `Runtime::RefusalWording::QUOTINGS`, or its `"sorted"` is not
310
- # `"true"`/`"false"`
311
190
  def check_rule!(key, spec)
312
191
  where = "#{key.join('/')}.#{spec.fetch('argument')}"
313
192
  unless Runtime::RefusalWording::SHAPES.include?(spec.fetch("shape"))
@@ -321,17 +200,6 @@ module Hecks
321
200
  raise ArgumentError, "#{where}: sorted must be \"true\" or \"false\""
322
201
  end
323
202
 
324
- # Renders every `:templates` variant's typed argument struct, plus the two
325
- # helper functions (`quoted`, `list`) they share.
326
- #
327
- # @param enum [String] the Rust enum name
328
- # @param variants [Array<String>] each row's generated variant name, matching `rows`
329
- # @param rows [Array<Hash{String => String}>] the `RefusalTemplate` rows, in
330
- # the same order as `variants`
331
- # @param by_site [Hash{Array<String> => Array<Hash{String => String}>}] each
332
- # `[refusal, site]` pair's declared argument rows, as built by `site_arguments`
333
- # @return [Array<String>] the shared `quoted`/`list` helper functions, followed
334
- # by every variant's `<Variant>Args` struct and `render_args` implementation
335
203
  def argument_types(enum, variants, rows, by_site)
336
204
  support = [
337
205
  "/// Ruby's `#inspect` of a name, as a refusal quotes it: `{:?}` on a",
@@ -362,15 +230,6 @@ module Hecks
362
230
  end
363
231
  end
364
232
 
365
- # Renders one variant's `<Variant>Args` struct and its `render_args` method.
366
- #
367
- # @param enum [String] the Rust enum name
368
- # @param variant [String] the row's generated variant name
369
- # @param row [Hash{String => String}] the `RefusalTemplate` row this variant projects
370
- # @param specs [Array<Hash{String => String}>] the variant's declared
371
- # `RefusalSiteArgument` rows, in declared order
372
- # @return [Array<String>] the lines for the variant's `<Variant>Args` struct
373
- # and its `render_args` method
374
233
  def args_struct(enum, variant, row, specs)
375
234
  fields = specs.flat_map do |spec|
376
235
  type = spec.fetch("shape") == "list" ? "&'a [&'a str]" : "&'a str"
@@ -401,15 +260,6 @@ module Hecks
401
260
  ""]
402
261
  end
403
262
 
404
- # The `let` binding, if any, `args_struct` inserts before a variant's
405
- # `render_args` computes its argument pairs.
406
- #
407
- # @param spec [Hash{String => String}] one `RefusalSiteArgument` row
408
- # (`"argument"`, `"shape"`, `"quoting"`, and, for a list, `"sorted"`,
409
- # `"separator"`, `"when_empty"`)
410
- # @return [String, nil] the `let` line formatting the argument through
411
- # `list`/`quoted`, or `nil` if the argument needs no formatting local
412
- # (a scalar written as-is)
413
263
  def formatted_local(spec)
414
264
  name = spec.fetch("argument")
415
265
  field = "self.#{rust_field(name)}"
@@ -421,13 +271,6 @@ module Hecks
421
271
  end
422
272
  end
423
273
 
424
- # Describes one argument's formatting rule in English, for its struct field's doc comment.
425
- #
426
- # @param spec [Hash{String => String}] one `RefusalSiteArgument` row
427
- # (`"shape"`, `"quoting"`, and, for a list, `"sorted"`, `"separator"`,
428
- # `"when_empty"`)
429
- # @return [String] a short English reading of the row's formatting rule,
430
- # used as the struct field's own doc comment
431
274
  def rule_reading(spec)
432
275
  quoting = spec.fetch("quoting") == "inspect" ? ", quoted" : ""
433
276
  return "scalar#{quoting}" unless spec.fetch("shape") == "list"
@@ -436,33 +279,10 @@ module Hecks
436
279
  "list#{sorted}#{quoting}, joined #{spec.fetch('separator').inspect}, empty reads #{spec.fetch('when_empty').inspect}"
437
280
  end
438
281
 
439
- # The local variable name `formatted_local` binds an argument's formatted value to.
440
- #
441
- # @param argument [String] the `RefusalSiteArgument` row's `"argument"` name
442
- # @return [String] the Rust local variable name `formatted_local` binds the
443
- # formatted value to
444
282
  def local_name(argument) = "#{argument}_text"
445
283
 
446
- # An argument name, escaped for use as a Rust field/parameter identifier.
447
- #
448
- # @param argument [String] the `RefusalSiteArgument` row's `"argument"` name
449
- # @return [String] `argument`, prefixed with `r#` if it collides with a Rust
450
- # keyword in `RUST_KEYWORDS`
451
284
  def rust_field(argument) = RUST_KEYWORDS.include?(argument) ? "r##{argument}" : argument
452
285
 
453
- # Renders the table's `#[cfg(test)]` module: every kind's `from_name` round-trip
454
- # test, plus `:order`'s and `:templates`' own tests.
455
- #
456
- # @param enum [String] the Rust enum name
457
- # @param kind [Symbol] the table's `:kind` (`:order`, `:templates`, or `:set`)
458
- # @param variants [Array<String>] each row's generated variant name, only
459
- # read when `kind == :templates`
460
- # @param rows [Array<Hash{String => String}>] the table's rows, only read
461
- # when `kind == :templates`
462
- # @param by_site [Hash{Array<String> => Array<Hash{String => String}>}, nil]
463
- # each `[refusal, site]` pair's declared argument rows, only read when
464
- # `kind == :templates`
465
- # @return [Array<String>] the `#[cfg(test)]` module's full source lines
466
286
  def tests(enum, kind, variants = [], rows = [], by_site = nil)
467
287
  list = kind == :order ? "ORDER" : "ALL"
468
288
  name = accessor_name(kind == :templates ? "site" : name_field(kind))
@@ -488,11 +308,6 @@ module Hecks
488
308
  lines + ["}"]
489
309
  end
490
310
 
491
- # The `:order` kind's own test, checked into every order table's test module.
492
- #
493
- # @param enum [String] the Rust enum name
494
- # @return [Array<String>] the test asserting `ORDER`'s index matches each
495
- # variant's `position`
496
311
  def order_test(enum)
497
312
  [" #[test]",
498
313
  " fn position_is_the_index_in_order() {",
@@ -503,12 +318,7 @@ module Hecks
503
318
  ""]
504
319
  end
505
320
 
506
- # Placeholders are read off each template's own text, never a second
507
- # hand-kept list.
508
- #
509
- # @param enum [String] the Rust enum name
510
- # @return [Array<String>] the test asserting every site's `render` leaves
511
- # no `{...}` placeholder unfilled
321
+ # Placeholders are read off each template's own text, never a second hand-kept list.
512
322
  def placeholder_test(enum)
513
323
  [" #[test]",
514
324
  " fn every_site_renders_with_no_leftover_placeholder() {",
@@ -538,21 +348,8 @@ module Hecks
538
348
  " }"]
539
349
  end
540
350
 
541
- # The Ruby oracle, pinned. Every site renders through its typed
542
- # `render_args` for each edge case a list argument has — empty, one
543
- # item, several out of order — and must equal what
544
- # Runtime::RefusalWording.render_with answers for the same values,
545
- # computed here at generation time. Scalars carry a `"` so quoting
546
- # is compared too.
547
- #
548
- # @param variants [Array<String>] each row's generated variant name, matching `rows`
549
- # @param rows [Array<Hash{String => String}>] the `RefusalTemplate` rows, in
550
- # the same order as `variants`
551
- # @param by_site [Hash{Array<String> => Array<Hash{String => String}>}] each
552
- # `[refusal, site]` pair's declared argument rows, as built by `site_arguments`
553
- # @return [Array<String>] the test asserting every variant's `render_args`
554
- # output for each `argument_cases` case matches
555
- # `Runtime::RefusalWording.render_with`, computed here in Ruby
351
+ # Pins each site's typed `render_args` to Runtime::RefusalWording.render_with, computed here,
352
+ # for empty, single and unsorted list arguments; scalars carry a `"` to compare quoting.
556
353
  def render_args_test(variants, rows, by_site)
557
354
  asserts = variants.zip(rows).flat_map do |variant, row|
558
355
  specs = by_site.fetch([row.fetch("refusal"), row.fetch("site")])
@@ -577,14 +374,6 @@ module Hecks
577
374
 
578
375
  LIST_CASES = [[], ["only \"one\""], %w[zeta alpha mid]].freeze
579
376
 
580
- # Builds the argument-value cases `render_args_test` checks a site's
581
- # `render_args` against.
582
- #
583
- # @param specs [Array<Hash{String => String}>] one site's declared
584
- # `RefusalSiteArgument` rows
585
- # @return [Array<Hash{Symbol => Object}>] one argument Hash per test case —
586
- # `LIST_CASES` (empty, one item, several unsorted) if any spec is
587
- # list-shaped, else a single scalar case, each scalar value carrying a `"`
588
377
  def argument_cases(specs)
589
378
  cases = specs.any? { |spec| spec.fetch("shape") == "list" } ? LIST_CASES : [nil]
590
379
  cases.map do |items|
@@ -595,29 +384,11 @@ module Hecks
595
384
  end
596
385
  end
597
386
 
598
- # The row field a table's `from_name`/round-trip test treats as its "name".
599
- #
600
- # @param kind [Symbol] the table's `:kind` (`:order`, `:templates`, or `:set`)
601
- # @return [String] the row field used as this kind's "name" — `"step"` for
602
- # `:order`, `"name"` otherwise
603
387
  def name_field(kind) = kind == :order ? "step" : "name"
604
388
 
605
- # `refusal` is a Rust-safe word but reads ambiguously beside the
606
- # kernel's own `Refusal` enum; the accessor says what it answers.
607
- #
608
- # @param field [String] a row field name, such as `"name"` or `"refusal"`
609
- # @return [String] the Rust accessor method name for `field` —
610
- # `"refusal_class"` for `"refusal"`, `field` otherwise
389
+ # `refusal` reads ambiguously beside the kernel's own `Refusal` enum.
611
390
  def accessor_name(field) = field == "refusal" ? "refusal_class" : field
612
391
 
613
- # Builds one row's Rust enum variant name from its declared `variant_from` fields.
614
- #
615
- # @param row [Hash{String => String}] the table row to name
616
- # @param fields [Array<String>] the row fields, PascalCased and concatenated
617
- # in order to build the variant name
618
- # @return [String] the row's generated Rust enum variant name
619
- # @raise [ArgumentError] if the built name is not a valid Rust variant
620
- # identifier (uppercase first letter, alphanumeric only)
621
392
  def variant_name(row, fields)
622
393
  name = fields.map { |field| pascal(row.fetch(field)) }.join
623
394
  raise ArgumentError, "#{name.inspect} is not a Rust variant name" unless name.match?(/\A[A-Z][A-Za-z0-9]*\z/)
@@ -625,18 +396,9 @@ module Hecks
625
396
  name
626
397
  end
627
398
 
628
- # PascalCases one field value for use inside a generated variant name.
629
- #
630
- # @param text [String, Symbol, nil] the value to PascalCase; each
631
- # `_`-separated part's first letter is upcased
632
- # @return [String] `text` converted to PascalCase, or `""` if `text` is `nil`
633
399
  def pascal(text) = text.to_s.split("_").map { |part| part[0].to_s.upcase + part[1..].to_s }.join
634
400
 
635
- # A Rust string literal: only `\`, `"` and newlines need escaping in
636
- # the text any vocabulary row holds.
637
- #
638
- # @param text [String] the value to render as a Rust string literal
639
- # @return [String] `text`, backslash/quote/newline-escaped and wrapped in `"..."`
401
+ # Only `\`, `"` and newlines need escaping in the text a vocabulary row holds.
640
402
  def rust_string(text)
641
403
  escaped = text.to_s.gsub("\\") { "\\\\" }.gsub('"') { "\\\"" }.gsub("\n") { "\\n" }
642
404
  "\"#{escaped}\""
@@ -3,21 +3,8 @@ require_relative "../projector"
3
3
 
4
4
  module Hecks
5
5
  module Projections
6
- # The storage shape of one bluebook — the same structural form
7
- # `StorageShape.mint_hash` hashes to name an era, which is what makes
8
- # a bump/no-bump question answerable by diffing two of these.
9
- #
10
- # The retrofit, and the point of it: `Runtime::StorageShape.project`
11
- # was written long before this framework existed, and it already
12
- # takes exactly one bluebook, already returns a plain Hash, already
13
- # touches no disk and no live runtime — it even already uses the
14
- # word. Nothing about it was shaped to fit `call(bluebook:, options:)`.
15
- #
16
- # That it fits anyway, by a two-line keyword adapter and no change to
17
- # `StorageShape` itself, is the evidence that the protocol is a real
18
- # description of what projections do here rather than a shape fitted
19
- # around its own first example (`:ir`, whose `call` is `to_h`, proves
20
- # much less on its own).
6
+ # The storage shape of one bluebook, the form `StorageShape.mint_hash` hashes to name an era.
7
+ # Diffing two of these answers whether a change bumps the era.
21
8
  module Shape
22
9
  extend Projector::Target
23
10
 
@@ -25,20 +12,7 @@ module Hecks
25
12
 
26
13
  module_function
27
14
 
28
- # ADR 0033 — `Runtime::StorageShape` lives in the era persistence
29
- # plugin now; the `:shape` projection itself stays registered
30
- # unconditionally (the seam `spec/projector_seam_spec.rb` enforces
31
- # is "every file here registers," not "every projection always
32
- # succeeds") but refuses clearly if asked to run with the plugin
33
- # unloaded, rather than raising on an undefined constant.
34
- # Projects the storage shape of `bluebook` — the structural form an era
35
- # bump/no-bump question is answered by diffing.
36
- #
37
- # @param bluebook [Bluebook::Chapter] the bluebook to reduce to its storage shape
38
- # @param options [Hash] unused; accepted to satisfy the registry's call shape
39
- # @return [Hash{String => Object}] `Runtime::StorageShape.project`'s Hash: `"name"`
40
- # and a sorted `"aggregates"` array
41
- # @raise [RuntimeError] if the era persistence plugin is not loaded
15
+ # Registered even when the era plugin is unloaded; the call then refuses clearly.
42
16
  def call(bluebook:, options: {})
43
17
  unless Ports::Persistence.plugin?(:era)
44
18
  raise "the :shape projection needs the era persistence plugin loaded " \
@@ -2,40 +2,10 @@ require_relative "../projector"
2
2
 
3
3
  module Hecks
4
4
  module Projections
5
- # A domain's own declared facts, projected as plain english sentences
6
- # — one atomic, independently-checkable statement per fact, not a
7
- # flowing document (`Projections::Reference`/`DocsProjector` already
8
- # do that job well; this is a flat list a caller can iterate, diff,
9
- # or hand to something else entirely — a review, a test-plan seed,
10
- # a sanity check that the domain still says what someone thinks it
11
- # says).
5
+ # A domain's declared facts as flat plain-English sentences, one checkable statement per fact.
6
+ # Never invents one: relationships read from shape, invariants use the author's description.
12
7
  #
13
- # ## Never invents a sentence from nothing
14
- #
15
- # `DocsProjector`'s own discipline, held here too: a relationship's
16
- # sentence is built mechanically from its own declared shape (holder,
17
- # target, relationship kind — the same facts `Projections::Diagrams`'s
18
- # own relationship_edge already reads), and an invariant's sentence is
19
- # the domain author's own `description`, capitalized and punctuated,
20
- # never paraphrased. If a fact has no author-written description and
21
- # no unambiguous mechanical phrasing, it doesn't get a sentence here —
22
- # a wrong sentence is worse than a missing one.
23
- #
24
- # ## Reachable like any projection
25
- #
26
- # No new facade wiring needed: `Pizzas.project(Projections::Statements)`
27
- # — `Facade::Surface::Chapter#project`'s own comment already settled
28
- # this ("anything genuinely needing the graph is a projector, and a
29
- # projector is given it"). `bin/statements` is a thin, optional
30
- # convenience for reaching the same call from a shell.
31
- #
32
- # ## MVP scope
33
- #
34
- # "has many"/"has a"/"belongs to"/"references" sentences for every
35
- # list or relationship attribute, and every invariant's own
36
- # description (aggregate-level and every nested value object's),
37
- # verbatim. Lifecycle transitions and command given/ensures read the
38
- # same way and are the natural next sentences — not built yet.
8
+ # Pizzas.project(Projections::Statements) # => ["A Pizza has many toppings.", ...]
39
9
  module Statements
40
10
  extend Hecks::Projector::Target
41
11
 
@@ -54,51 +24,17 @@ module Hecks
54
24
  holders(bluebook).flat_map { |holder| statements_for(holder) }
55
25
  end
56
26
 
57
- # Every construct that can carry its own attributes and invariants — an
58
- # aggregate and each of its entities.
59
- #
60
- # @param bluebook [Bluebook::Chapter] the chapter being walked
61
- # @return [Array<Bluebook::Aggregate, Bluebook::Entity>] every aggregate followed
62
- # by its own entities, in declaration order
63
27
  def holders(bluebook) = bluebook.aggregates.flat_map { |aggregate| [aggregate, *aggregate.entities] }
64
28
 
65
- # All of one holder's sentences: its attribute relationships, then its invariants.
66
- #
67
- # @param holder [Bluebook::Aggregate, Bluebook::Entity] the construct being
68
- # projected
69
- # @return [Array<String>] the holder's sentences
70
29
  def statements_for(holder)
71
30
  attribute_statements(holder) + invariant_statements(holder)
72
31
  end
73
32
 
74
- # "MANY" reads the same way regardless of what's behind it — a
75
- # `has_many` relationship to another aggregate and a plain
76
- # `list_of(Topping)` value-object attribute are the same idea to
77
- # someone reading the domain in English ("an Order has many
78
- # toppings" is true either way), even though they're two
79
- # different IR shapes (a `Reference` versus an ordinary type).
80
- # `attribute.name` carries the noun, not the target's own class
81
- # name, because the field's own name is what the domain author
82
- # actually chose to call the collection — "toppings", not
83
- # "Topping".
84
- # Projects every one of a holder's attributes that says something in plain
85
- # English — a list, or a named relationship.
86
- #
87
- # @param holder [Bluebook::Aggregate, Bluebook::Entity] the construct whose
88
- # attributes are being read
89
- # @return [Array<String>] one sentence per list or relationship attribute; a
90
- # plain scalar attribute contributes none
33
+ # `has_many` and `list_of` read the same in English; `attribute.name` is the author's noun.
91
34
  def attribute_statements(holder)
92
35
  holder.attributes.filter_map { |attribute| attribute_statement(holder, attribute) }
93
36
  end
94
37
 
95
- # Projects one attribute's relationship, if it has one worth stating.
96
- #
97
- # @param holder [Bluebook::Aggregate, Bluebook::Entity] the attribute's owning
98
- # construct, named as the sentence's subject
99
- # @param attribute [Bluebook::Attribute] the attribute being projected
100
- # @return [String, nil] the sentence, or `nil` if `attribute` is neither a list
101
- # nor a `has_one`/`belongs_to`/`reference_to` relationship
102
38
  def attribute_statement(holder, attribute)
103
39
  subject = "#{article(holder.hecks_name)} #{holder.hecks_name}"
104
40
  return "#{subject} has many #{attribute.name}." if attribute.list?
@@ -112,24 +48,12 @@ module Hecks
112
48
  end
113
49
  end
114
50
 
115
- # "An account", not "A ACCOUNT" — every subject/object noun here is
116
- # a bare construct name (`ATMCard`, `ExternalTransfer`, `Account`),
117
- # never free text, so the ordinary "starts with a vowel LETTER"
118
- # heuristic is safe: this language's own naming never produces the
119
- # English exceptions that heuristic gets wrong (an "hour", a
120
- # "university") because a construct name is always spelled as a
121
- # plain word, never an abbreviation read letter-by-letter or a
122
- # word starting with a consonant letter but a vowel sound.
123
- #
51
+ # Vowel-letter heuristic is safe: construct names are plain words, never initialisms.
124
52
  # @param word [String] a construct name to prefix
125
53
  # @return [String] `"An"` if `word` starts with a vowel letter, `"A"` otherwise
126
54
  def article(word) = word.to_s.match?(/\A[AEIOUaeiou]/) ? "An" : "A"
127
55
 
128
- # Invariants live in two places — directly on the holder (an
129
- # aggregate-level rule, checked after every command) and on every
130
- # value object nested inside it — `DocsProjector#rules_of`'s own
131
- # `value_object_for` lookup is the precedent for walking both.
132
- #
56
+ # Invariants sit on the holder and on each nested value object; both are read.
133
57
  # @param holder [Bluebook::Aggregate, Bluebook::Entity] the construct whose
134
58
  # invariants, and whose value objects' invariants, are being read
135
59
  # @return [Array<String>] one sentence per invariant, the holder's own first,
@@ -140,10 +64,7 @@ module Hecks
140
64
  (own + nested).map { |invariant| invariant_statement(invariant) }
141
65
  end
142
66
 
143
- # The domain author's own words, capitalized and punctuated —
144
- # nothing else. `invariant("a pizza is named")` already reads as
145
- # a sentence; this is the entire transformation.
146
- #
67
+ # The author's own description, capitalized and punctuated; no other transformation.
147
68
  # @param invariant [Bluebook::Invariant] the invariant being projected
148
69
  # @return [String] the invariant's `description`, capitalized, ending with `.`,
149
70
  # `!` or `?`