hecks 2.9.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 (600) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +51 -6
  3. data/lib/hecks/adapters/driven/heki/journal.rb +1 -1
  4. data/lib/hecks/adapters/driven/lambda/client.rb +1 -1
  5. data/lib/hecks/adapters/driven/lambda.rb +1 -1
  6. data/lib/hecks/adapters/driven/memory.rb +16 -3
  7. data/lib/hecks/adapters/driven/postgres/reconnect.rb +6 -2
  8. data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
  9. data/lib/hecks/adapters/driven/postgres.rb +4 -2
  10. data/lib/hecks/adapters/driven/prism.rb +41 -8
  11. data/lib/hecks/adapters/driven/tenant_provisioner.rb +73 -16
  12. data/lib/hecks/behaviors/expectations.rb +1 -1
  13. data/lib/hecks/behaviors.rb +1 -1
  14. data/lib/hecks/bench/cli.rb +62 -0
  15. data/lib/hecks/bench/environment.rb +71 -0
  16. data/lib/hecks/bench/postgres_probe.rb +30 -0
  17. data/lib/hecks/bench/report.rb +76 -0
  18. data/lib/hecks/bench/ruby_runner.rb +93 -0
  19. data/lib/hecks/bench/run.rb +55 -0
  20. data/lib/hecks/bench/rust_runner.rb +101 -0
  21. data/lib/hecks/bench/stats.rb +46 -0
  22. data/lib/hecks/bench/suite.rb +98 -0
  23. data/lib/hecks/bench/workload.rb +89 -0
  24. data/lib/hecks/bench.rb +17 -0
  25. data/lib/hecks/bluebook/assembly/contracts.rb +2 -0
  26. data/lib/hecks/bluebook/attribute.rb +1 -1
  27. data/lib/hecks/bluebook/behaviour/aggregate.rb +30 -1
  28. data/lib/hecks/bluebook/behaviour/domain_port.rb +7 -0
  29. data/lib/hecks/bluebook/chapter.rb +6 -2
  30. data/lib/hecks/bluebook/domain_port.rb +36 -5
  31. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +10 -0
  32. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +8 -0
  33. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -1
  34. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +31 -3
  35. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +122 -3
  36. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +1 -1
  37. data/lib/hecks/bluebook/dsl/query_builder.rb +27 -1
  38. data/lib/hecks/bluebook/dsl/rule_reference.rb +1 -1
  39. data/lib/hecks/bluebook/dsl/world_builder.rb +29 -2
  40. data/lib/hecks/bluebook/expression/canonical_form.rb +1 -1
  41. data/lib/hecks/bluebook/expression/resolver.rb +3 -2
  42. data/lib/hecks/bluebook/hexagon.rb +13 -5
  43. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +1 -0
  44. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +4 -1
  45. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
  46. data/lib/hecks/bluebook/meta_validator.rb +9 -4
  47. data/lib/hecks/bluebook/model_check.rb +23 -0
  48. data/lib/hecks/bluebook/pattern_subset.rb +38 -0
  49. data/lib/hecks/bluebook/query.rb +20 -5
  50. data/lib/hecks/bluebook/smoke_test.rb +1 -1
  51. data/lib/hecks/canonical_json.rb +30 -0
  52. data/lib/hecks/chapters.rb +102 -0
  53. data/lib/hecks/cli/behaviors.rb +61 -0
  54. data/lib/hecks/cli/canonicalise.rb +25 -0
  55. data/lib/hecks/cli/check_engine_agreement.rb +32 -0
  56. data/lib/hecks/cli/check_era.rb +88 -0
  57. data/lib/hecks/cli/console.rb +66 -0
  58. data/lib/hecks/cli/deploy_template_diff.rb +40 -0
  59. data/lib/hecks/cli/doc_coverage.rb +32 -0
  60. data/lib/hecks/cli/document.rb +2 -2
  61. data/lib/hecks/cli/expression_projection.rb +41 -0
  62. data/lib/hecks/cli/follow.rb +88 -0
  63. data/lib/hecks/cli/history.rb +44 -0
  64. data/lib/hecks/cli/ir.rb +1 -1
  65. data/lib/hecks/cli/mcp.rb +3 -3
  66. data/lib/hecks/cli/model_check.rb +7 -4
  67. data/lib/hecks/cli/pattern_cases.rb +47 -0
  68. data/lib/hecks/cli/present.rb +39 -0
  69. data/lib/hecks/cli/project_cli.rb +224 -32
  70. data/lib/hecks/cli/project_diagrams.rb +4 -3
  71. data/lib/hecks/cli/project_glossary.rb +44 -0
  72. data/lib/hecks/cli/reference.rb +46 -0
  73. data/lib/hecks/cli/refresh_projections.rb +44 -0
  74. data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +150 -0
  75. data/lib/hecks/cli/release.rb +70 -0
  76. data/lib/hecks/cli/release_gem.rb +59 -0
  77. data/lib/hecks/cli/rspec_io_parallel_files.rb +137 -0
  78. data/lib/hecks/cli/rspec_shard_files.rb +66 -0
  79. data/lib/hecks/cli/run.rb +3 -3
  80. data/lib/hecks/cli/seed_semantics_corpus.rb +71 -0
  81. data/lib/hecks/cli/serve_query_ir_mcp.rb +30 -0
  82. data/lib/hecks/cli/shape.rb +70 -0
  83. data/lib/hecks/cli/smoke_http.rb +230 -0
  84. data/lib/hecks/cli/smoke_test.rb +5 -3
  85. data/lib/hecks/cli/spec_example.rb +27 -0
  86. data/lib/hecks/cli/statements.rb +32 -0
  87. data/lib/hecks/cli/stores.rb +4 -5
  88. data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
  89. data/lib/hecks/cli.rb +201 -52
  90. data/lib/hecks/codemod.rb +324 -0
  91. data/lib/hecks/corpus.rb +423 -0
  92. data/lib/hecks/deploy/bluebook/deploy.bluebook +591 -23
  93. data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -4
  94. data/lib/hecks/deploy/oidc.json +82 -2
  95. data/lib/hecks/doc/reference.rb +351 -0
  96. data/lib/hecks/doors/cli_door.rb +196 -0
  97. data/lib/hecks/doors/cli_runner.rb +297 -0
  98. data/lib/hecks/{facade → doors}/command_request.rb +1 -1
  99. data/lib/hecks/{facade → doors}/handle.rb +2 -2
  100. data/lib/hecks/{facade → doors}/json_door.rb +4 -4
  101. data/lib/hecks/doors/launcher_options.rb +129 -0
  102. data/lib/hecks/{cli → doors}/mcp_door.rb +7 -7
  103. data/lib/hecks/doors/mcp_door_scope.rb +97 -0
  104. data/lib/hecks/{facade/surface → doors/ruby_door}/aggregate_door.rb +8 -3
  105. data/lib/hecks/{facade/surface → doors/ruby_door}/chapter.rb +3 -3
  106. data/lib/hecks/{facade/surface.rb → doors/ruby_door.rb} +36 -5
  107. data/lib/hecks/doors.rb +61 -0
  108. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +1 -1
  109. data/lib/hecks/embryonaut_bluebook.rb +1 -1
  110. data/lib/hecks/engine_agreement.rb +156 -0
  111. data/lib/hecks/facade.rb +24 -37
  112. data/lib/hecks/forms/app.rb +6 -6
  113. data/lib/hecks/forms/banking_presentation.rb +50 -0
  114. data/lib/hecks/forms/field_shape.rb +2 -1
  115. data/lib/hecks/forms/port_argument.rb +1 -1
  116. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +393 -0
  117. data/lib/hecks/fuzzing/combination_miner.rb +86 -0
  118. data/lib/hecks/fuzzing/concurrent_dispatch.rb +214 -0
  119. data/lib/hecks/fuzzing/coverage_campaign.rb +143 -0
  120. data/lib/hecks/fuzzing/differential.rb +156 -0
  121. data/lib/hecks/fuzzing/domain_generator.rb +615 -0
  122. data/lib/hecks/fuzzing/era_boundary.rb +71 -0
  123. data/lib/hecks/fuzzing/form_census.rb +136 -0
  124. data/lib/hecks/fuzzing/generated_domain_check.rb +93 -0
  125. data/lib/hecks/fuzzing/invalid_value_generator.rb +64 -0
  126. data/lib/hecks/fuzzing/isolated_boot.rb +301 -0
  127. data/lib/hecks/fuzzing/nondeterministic.rb +51 -0
  128. data/lib/hecks/fuzzing/outside_world.rb +45 -0
  129. data/lib/hecks/fuzzing/persistence_parity.rb +102 -0
  130. data/lib/hecks/fuzzing/properties/corrections.rb +88 -0
  131. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +314 -0
  132. data/lib/hecks/fuzzing/properties/guards.rb +190 -0
  133. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +300 -0
  134. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +93 -0
  135. data/lib/hecks/fuzzing/properties/outbox.rb +89 -0
  136. data/lib/hecks/fuzzing/properties/querying.rb +175 -0
  137. data/lib/hecks/fuzzing/properties.rb +162 -0
  138. data/lib/hecks/fuzzing/qa_settings.rb +123 -0
  139. data/lib/hecks/fuzzing/replay.rb +505 -0
  140. data/lib/hecks/fuzzing/rotation_priority.rb +48 -0
  141. data/lib/hecks/fuzzing/rust_gap_manifest.rb +108 -0
  142. data/lib/hecks/fuzzing/self_consistency.rb +339 -0
  143. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +385 -0
  144. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +132 -0
  145. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +95 -0
  146. data/lib/hecks/fuzzing/sequence_generator/picker.rb +77 -0
  147. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +109 -0
  148. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +237 -0
  149. data/lib/hecks/fuzzing/sequence_generator.rb +189 -0
  150. data/lib/hecks/fuzzing/shrinker.rb +166 -0
  151. data/lib/hecks/fuzzing/structural_skips.rb +33 -0
  152. data/lib/hecks/fuzzing/sweep_depth.rb +43 -0
  153. data/lib/hecks/fuzzing/target_capabilities.rb +163 -0
  154. data/lib/hecks/fuzzing/value_generator.rb +216 -0
  155. data/lib/hecks/fuzzing.rb +23 -0
  156. data/lib/hecks/grammar/evolve.rb +336 -0
  157. data/lib/hecks/hecks/adapters/codebase/codemods.rb +45 -0
  158. data/lib/hecks/hecks/adapters/codebase/conformance.rb +71 -0
  159. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +202 -0
  160. data/lib/hecks/hecks/adapters/codebase/gem_registry.rb +80 -0
  161. data/lib/hecks/hecks/adapters/codebase/kernel_tables.rb +54 -0
  162. data/lib/hecks/hecks/adapters/codebase/language.rb +240 -0
  163. data/lib/hecks/hecks/adapters/codebase/npm_registry.rb +102 -0
  164. data/lib/hecks/hecks/adapters/codebase/publishing.rb +142 -0
  165. data/lib/hecks/hecks/adapters/codebase/regeneration.rb +67 -0
  166. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +90 -0
  167. data/lib/hecks/hecks/adapters/codebase/ruby_child.rb +83 -0
  168. data/lib/hecks/hecks/adapters/codebase/secret_vault.rb +36 -0
  169. data/lib/hecks/hecks/adapters/codebase/source_tree.adapter +7 -0
  170. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +189 -0
  171. data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +71 -0
  172. data/lib/hecks/hecks/adapters/codebase/style.rb +171 -0
  173. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +55 -0
  174. data/lib/hecks/hecks/adapters/codebase/test_suite.rb +165 -0
  175. data/lib/hecks/hecks/adapters/codebase/tree.rb +111 -0
  176. data/lib/hecks/hecks/adapters/console_capture.rb +79 -0
  177. data/lib/hecks/hecks/adapters/deploy_toolchain.adapter +7 -0
  178. data/lib/hecks/hecks/adapters/deploy_toolchain.rb +108 -0
  179. data/lib/hecks/hecks/adapters/git.adapter +7 -0
  180. data/lib/hecks/hecks/adapters/git.rb +102 -0
  181. data/lib/hecks/hecks/adapters/host_http.adapter +7 -0
  182. data/lib/hecks/hecks/adapters/host_http.rb +65 -0
  183. data/lib/hecks/hecks/adapters/in_process_boot.adapter +7 -0
  184. data/lib/hecks/hecks/adapters/in_process_boot.rb +197 -0
  185. data/lib/hecks/hecks/adapters/in_process_operations.rb +202 -0
  186. data/lib/hecks/hecks/adapters/journal_store/changes.rb +143 -0
  187. data/lib/hecks/hecks/adapters/journal_store/compaction.rb +145 -0
  188. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +132 -0
  189. data/lib/hecks/hecks/adapters/journal_store/examination.rb +135 -0
  190. data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +163 -0
  191. data/lib/hecks/hecks/adapters/journal_store/readings.rb +187 -0
  192. data/lib/hecks/hecks/adapters/journal_store.adapter +7 -0
  193. data/lib/hecks/hecks/adapters/journal_store.rb +64 -0
  194. data/lib/hecks/hecks/adapters/local_files.adapter +7 -0
  195. data/lib/hecks/hecks/adapters/local_files.rb +46 -0
  196. data/lib/hecks/hecks/adapters/pg_admin.adapter +7 -0
  197. data/lib/hecks/hecks/adapters/pg_admin.rb +245 -0
  198. data/lib/hecks/hecks/adapters/process_pool.adapter +7 -0
  199. data/lib/hecks/hecks/adapters/process_pool.rb +119 -0
  200. data/lib/hecks/hecks/adapters/rust_toolchain.adapter +7 -0
  201. data/lib/hecks/hecks/adapters/rust_toolchain.rb +179 -0
  202. data/lib/hecks/hecks/adapters/rust_workspace.rb +150 -0
  203. data/lib/hecks/hecks/adapters/shell.adapter +7 -0
  204. data/lib/hecks/hecks/adapters/shell.rb +49 -0
  205. data/lib/hecks/hecks/adapters/terminal.adapter +7 -0
  206. data/lib/hecks/hecks/adapters/terminal.rb +74 -0
  207. data/lib/hecks/hecks/codebase.behaviors +172 -0
  208. data/lib/hecks/hecks/codebase.bluebook +2453 -0
  209. data/lib/hecks/hecks/context_map.hecksagon +13 -0
  210. data/lib/hecks/hecks/custodian.behaviors +179 -0
  211. data/lib/hecks/hecks/custodian.bluebook +1847 -0
  212. data/lib/hecks/hecks/deploy.behaviors +74 -0
  213. data/lib/hecks/hecks/deploy.world +12 -0
  214. data/lib/hecks/hecks/environments/memory.world +10 -0
  215. data/lib/hecks/hecks/governance.world +7 -0
  216. data/lib/hecks/hecks/hecks.behaviors +62 -0
  217. data/lib/hecks/hecks/hecks.bluebook +124 -0
  218. data/lib/hecks/hecks/hecks.hecksagon +390 -0
  219. data/lib/hecks/hecks/hecks.world +42 -0
  220. data/lib/hecks/kernel_capabilities.rb +194 -0
  221. data/lib/hecks/language/bluebook/bluebook.bluebook +11 -0
  222. data/lib/hecks/language/bluebook/query.bluebook +7 -0
  223. data/lib/hecks/language/bluebook/vocabulary.bluebook +4 -4
  224. data/lib/hecks/language/hecksagon/domain_port.bluebook +10 -0
  225. data/lib/hecks/language/hecksagon/hecksagon.bluebook +20 -0
  226. data/lib/hecks/mcp_stdio_guard.rb +2 -2
  227. data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
  228. data/lib/hecks/persistence_legacy_fixture.rb +113 -0
  229. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +8 -5
  230. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +4 -1
  231. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +15 -2
  232. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +1 -1
  233. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +1 -1
  234. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +1 -1
  235. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +32 -15
  236. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +6 -3
  237. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +227 -0
  238. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +1 -1
  239. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +43 -24
  240. data/lib/hecks/ports/persistence/plugins/era/translation.rb +1 -0
  241. data/lib/hecks/ports/persistence/state_codec.rb +24 -5
  242. data/lib/hecks/projection_files.rb +285 -0
  243. data/lib/hecks/projections/bootstrap_table.rb +1 -1
  244. data/lib/hecks/projections/deploy/fargate.rb +5 -5
  245. data/lib/hecks/projections/deploy/lambda.rb +43 -32
  246. data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
  247. data/lib/hecks/projections/deploy/preview/template.rb +1 -1
  248. data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +1 -1
  249. data/lib/hecks/projections/deploy/scripts/expected-era.header +1 -1
  250. data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +3 -3
  251. data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +1 -1
  252. data/lib/hecks/projections/deploy/shared.rb +1 -1
  253. data/lib/hecks/projections/diagrams.rb +3 -3
  254. data/lib/hecks/projections/model/deviations.rb +1 -1
  255. data/lib/hecks/projections/parser_table.rb +4 -4
  256. data/lib/hecks/projections/reference.rb +2 -3
  257. data/lib/hecks/projections/rust_vocabulary.rb +1 -1
  258. data/lib/hecks/projector/cli_projector.rb +106 -37
  259. data/lib/hecks/projector.rb +1 -1
  260. data/lib/hecks/quality_control/adapters/agent.adapter +7 -0
  261. data/lib/hecks/quality_control/adapters/agent.rb +58 -0
  262. data/lib/hecks/quality_control/adapters/angle_tools.adapter +7 -0
  263. data/lib/hecks/quality_control/adapters/angle_tools.rb +15 -0
  264. data/lib/hecks/quality_control/adapters/clearance_recorder.rb +36 -0
  265. data/lib/hecks/quality_control/adapters/clearance_tools.adapter +7 -0
  266. data/lib/hecks/quality_control/adapters/clearance_tools.rb +17 -0
  267. data/lib/hecks/quality_control/adapters/git_pr.adapter +7 -0
  268. data/lib/hecks/quality_control/adapters/git_pr.rb +226 -0
  269. data/lib/hecks/quality_control/adapters/github_checks.adapter +9 -0
  270. data/lib/hecks/quality_control/adapters/github_checks.rb +83 -0
  271. data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +56 -0
  272. data/lib/hecks/quality_control/adapters/github_issues.adapter +7 -0
  273. data/lib/hecks/quality_control/adapters/github_issues.rb +49 -0
  274. data/lib/hecks/quality_control/adapters/qa_tool.rb +59 -0
  275. data/lib/hecks/quality_control/adapters/sweep_tools.adapter +7 -0
  276. data/lib/hecks/quality_control/adapters/sweep_tools.rb +51 -0
  277. data/lib/hecks/quality_control/adapters/target_tools.adapter +7 -0
  278. data/lib/hecks/quality_control/adapters/target_tools.rb +43 -0
  279. data/lib/hecks/quality_control/cli/child.rb +45 -0
  280. data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +45 -0
  281. data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +248 -0
  282. data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +163 -0
  283. data/lib/hecks/quality_control/cli/qa_generated_domains.rb +450 -0
  284. data/lib/hecks/quality_control/cli/qa_log_bug.rb +195 -0
  285. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +220 -0
  286. data/lib/hecks/quality_control/cli/qa_open_pr.rb +305 -0
  287. data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +154 -0
  288. data/lib/hecks/quality_control/cli/qa_postgres_role.rb +159 -0
  289. data/lib/hecks/quality_control/cli/qa_pr_check.rb +232 -0
  290. data/lib/hecks/quality_control/cli/qa_seed_angles.rb +142 -0
  291. data/lib/hecks/quality_control/cli/qa_seed_targets.rb +69 -0
  292. data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +280 -0
  293. data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +329 -0
  294. data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +92 -0
  295. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +117 -0
  296. data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +175 -0
  297. data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +60 -0
  298. data/lib/hecks/quality_control/cli/qa_sweep.rb +611 -0
  299. data/lib/hecks/quality_control/cli/qa_tick.rb +274 -0
  300. data/lib/hecks/quality_control/quality_control.bluebook +2224 -0
  301. data/lib/hecks/quality_control/quality_control.hecksagon +13 -0
  302. data/lib/hecks/quality_control/quality_control.ports.hecksagon +54 -0
  303. data/lib/hecks/query_ir.rb +346 -0
  304. data/lib/hecks/query_ir_mcp.rb +198 -0
  305. data/lib/hecks/release/runner/ci_publisher.rb +2 -2
  306. data/lib/hecks/release/runner/clean_tree.rb +42 -0
  307. data/lib/hecks/release/runner/console.rb +6 -0
  308. data/lib/hecks/release/runner/gem_publisher.rb +14 -7
  309. data/lib/hecks/release/runner/npm_publisher.rb +6 -36
  310. data/lib/hecks/release/runner/preflight.rb +26 -2
  311. data/lib/hecks/release/runner/published.rb +8 -26
  312. data/lib/hecks/release/runner/tagger.rb +30 -15
  313. data/lib/hecks/release/runner.rb +57 -6
  314. data/lib/hecks/router/namespace_installer.rb +3 -3
  315. data/lib/hecks/runtime/adapter_lookup.rb +124 -0
  316. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +4 -0
  317. data/lib/hecks/runtime/dependency_planning.rb +20 -2
  318. data/lib/hecks/runtime/dispatcher.rb +53 -3
  319. data/lib/hecks/runtime/interpreting.rb +3 -0
  320. data/lib/hecks/runtime/loader.rb +65 -12
  321. data/lib/hecks/runtime/outbox.rb +1 -1
  322. data/lib/hecks/runtime/policy_interpreter.rb +5 -2
  323. data/lib/hecks/runtime/port_operation_interpreter.rb +2 -10
  324. data/lib/hecks/runtime/query_interpreter.rb +77 -0
  325. data/lib/hecks/runtime/reaction_outcome.rb +89 -0
  326. data/lib/hecks/runtime/refusal_wording.rb +23 -1
  327. data/lib/hecks/runtime/registry/verification.rb +163 -4
  328. data/lib/hecks/runtime/registry.rb +57 -3
  329. data/lib/hecks/runtime/remote_dispatcher.rb +31 -2
  330. data/lib/hecks/runtime/value/coercion.rb +23 -135
  331. data/lib/hecks/runtime/value/field_checks.rb +172 -0
  332. data/lib/hecks/runtime/value.rb +4 -1
  333. data/lib/hecks/runtime.rb +20 -6
  334. data/lib/hecks/rust_build/conformance.rb +158 -0
  335. data/lib/hecks/rust_build/conformance_fuzz.rb +71 -0
  336. data/lib/hecks/rust_build/coverage.rb +218 -0
  337. data/lib/hecks/rust_build/native_build.rb +124 -0
  338. data/lib/hecks/rust_build/project_rust/root_mod.rb +120 -0
  339. data/lib/hecks/rust_build/project_rust.rb +332 -0
  340. data/lib/hecks/rust_build/wasm.rb +105 -0
  341. data/lib/hecks/rust_build/wasm_browser.rb +113 -0
  342. data/lib/hecks/rust_build.rb +144 -0
  343. data/lib/hecks/storehouse.rb +16 -16
  344. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +2 -2
  345. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +1 -1
  346. data/lib/hecks/three_zero/forms.yml +127 -0
  347. data/lib/hecks/three_zero.rb +12 -0
  348. data/lib/hecks/tools/argument_gate_matrix.rb +316 -0
  349. data/lib/hecks/tools/comment_style.rb +1070 -0
  350. data/lib/hecks/tools/corpus_report.rb +87 -0
  351. data/lib/hecks/tools/deploy_recipe.rb +255 -0
  352. data/lib/hecks/tools/deploy_recipe_lint.rb +282 -0
  353. data/lib/hecks/tools/drop_implicit_append_fields.rb +95 -0
  354. data/lib/hecks/tools/era_projection_backfill.rb +94 -0
  355. data/lib/hecks/tools/era_reattest.rb +146 -0
  356. data/lib/hecks/tools/evolve_run.rb +189 -0
  357. data/lib/hecks/tools/fuzz_sweep.rb +373 -0
  358. data/lib/hecks/tools/heki_compaction.rb +100 -0
  359. data/lib/hecks/tools/hoist_local_givens.rb +246 -0
  360. data/lib/hecks/tools/journal_compaction.rb +89 -0
  361. data/lib/hecks/tools/oidc_manifests.rb +70 -0
  362. data/lib/hecks/tools/query_ir_run.rb +81 -0
  363. data/lib/hecks/tools/regeneration_run.rb +166 -0
  364. data/lib/hecks/tools/rust_comment_style.rb +642 -0
  365. data/lib/hecks/tools/sequence_script.rb +62 -0
  366. data/lib/hecks/tools/tail_merge.rb +117 -0
  367. data/lib/hecks/tools/tenant_provisioning.rb +142 -0
  368. data/lib/hecks/tools/translation_audit.rb +208 -0
  369. data/lib/hecks/tools/translation_scaffold.rb +131 -0
  370. data/lib/hecks/tools.rb +86 -0
  371. data/lib/hecks/version.rb +1 -1
  372. data/lib/hecks.rb +32 -15
  373. data/qa/settings.yml +66 -0
  374. data/rust/.cargo/config.toml +6 -0
  375. data/rust/.gitignore +2 -0
  376. data/rust/Cargo.lock +54 -0
  377. data/rust/Cargo.toml +61 -0
  378. data/rust/build/.cargo/config.toml +3 -0
  379. data/rust/build/.gitignore +1 -0
  380. data/rust/build/Cargo.lock +7 -0
  381. data/rust/build/Cargo.toml +19 -0
  382. data/rust/build/src/build_artifact.rs +47 -0
  383. data/rust/build/src/cargo_sync.rs +248 -0
  384. data/rust/build/src/json.rs +421 -0
  385. data/rust/build/src/lineage_pass.rs +285 -0
  386. data/rust/build/src/main.rs +51 -0
  387. data/rust/build/src/optional_pass.rs +150 -0
  388. data/rust/build/src/pipeline.rs +264 -0
  389. data/rust/build/src/reserved_names.rs +76 -0
  390. data/rust/build/src/resolve.rs +124 -0
  391. data/rust/build/src/root.rs +25 -0
  392. data/rust/build/src/sidecars.rs +73 -0
  393. data/rust/build/src/subprocess.rs +51 -0
  394. data/rust/build/src/tmp.rs +31 -0
  395. data/rust/codegen/.cargo/config.toml +3 -0
  396. data/rust/codegen/.gitignore +1 -0
  397. data/rust/codegen/Cargo.lock +7 -0
  398. data/rust/codegen/Cargo.toml +20 -0
  399. data/rust/codegen/src/attr.rs +32 -0
  400. data/rust/codegen/src/bridging.rs +481 -0
  401. data/rust/codegen/src/commands.rs +1226 -0
  402. data/rust/codegen/src/constraints.rs +109 -0
  403. data/rust/codegen/src/dependency_planning.rs +209 -0
  404. data/rust/codegen/src/domain_generator.rs +1288 -0
  405. data/rust/codegen/src/exemplar.rs +230 -0
  406. data/rust/codegen/src/expr_emitter.rs +87 -0
  407. data/rust/codegen/src/fielded.rs +192 -0
  408. data/rust/codegen/src/hecks_naming.rs +33 -0
  409. data/rust/codegen/src/json.rs +335 -0
  410. data/rust/codegen/src/json_codec.rs +697 -0
  411. data/rust/codegen/src/literal.rs +207 -0
  412. data/rust/codegen/src/main.rs +290 -0
  413. data/rust/codegen/src/manifest.rs +227 -0
  414. data/rust/codegen/src/mutations.rs +784 -0
  415. data/rust/codegen/src/naming.rs +286 -0
  416. data/rust/codegen/src/ports.rs +208 -0
  417. data/rust/codegen/src/prelude.rs +116 -0
  418. data/rust/codegen/src/queries.rs +786 -0
  419. data/rust/codegen/src/reactions.rs +532 -0
  420. data/rust/codegen/src/read_models.rs +697 -0
  421. data/rust/codegen/src/reference_specs.rs +40 -0
  422. data/rust/codegen/src/registry.rs +966 -0
  423. data/rust/codegen/src/reserved_names.rs +76 -0
  424. data/rust/codegen/src/shared.rs +93 -0
  425. data/rust/codegen/src/skip_reason.rs +25 -0
  426. data/rust/codegen/src/types.rs +362 -0
  427. data/rust/host/.cargo/config.toml +3 -0
  428. data/rust/host/.gitignore +1 -0
  429. data/rust/host/Cargo.lock +4297 -0
  430. data/rust/host/Cargo.toml +61 -0
  431. data/rust/host/HECKS_RELEASE +1 -0
  432. data/rust/host/rds-ca-bundle.pem +2736 -0
  433. data/rust/host/src/api.rs +1596 -0
  434. data/rust/host/src/approval.rs +652 -0
  435. data/rust/host/src/auth.rs +1287 -0
  436. data/rust/host/src/bin/expr_harness.rs +46 -0
  437. data/rust/host/src/bin/lineage_harness.rs +119 -0
  438. data/rust/host/src/bin/mint_harness.rs +135 -0
  439. data/rust/host/src/checkout.rs +265 -0
  440. data/rust/host/src/dispatch.rs +1443 -0
  441. data/rust/host/src/expr_json.rs +1117 -0
  442. data/rust/host/src/field_hints.rs +52 -0
  443. data/rust/host/src/ir.rs +733 -0
  444. data/rust/host/src/journal.rs +874 -0
  445. data/rust/host/src/lambda_client.rs +378 -0
  446. data/rust/host/src/log.rs +147 -0
  447. data/rust/host/src/main.rs +474 -0
  448. data/rust/host/src/mint.rs +1865 -0
  449. data/rust/host/src/payments/keystore.rs +330 -0
  450. data/rust/host/src/payments/tests.rs +1400 -0
  451. data/rust/host/src/payments.rs +767 -0
  452. data/rust/host/src/presentation.rs +698 -0
  453. data/rust/host/src/presentation_write.rs +1431 -0
  454. data/rust/host/src/query_step.rs +149 -0
  455. data/rust/host/src/rate_limit.rs +904 -0
  456. data/rust/host/src/reference_transform.rs +241 -0
  457. data/rust/host/src/reference_validate.rs +338 -0
  458. data/rust/host/src/resend.rs +296 -0
  459. data/rust/host/src/secrets.rs +106 -0
  460. data/rust/host/src/server.rs +663 -0
  461. data/rust/host/src/storage_shape.rs +175 -0
  462. data/rust/host/src/test_pg.rs +40 -0
  463. data/rust/host/src/ui_schema.rs +1351 -0
  464. data/rust/host/src/wasm_runner.rs +191 -0
  465. data/rust/host/src/web/newsletter/cooldown.rs +126 -0
  466. data/rust/host/src/web/newsletter/tests.rs +104 -0
  467. data/rust/host/src/web/newsletter.rs +310 -0
  468. data/rust/host/src/web/newsletter_send.rs +357 -0
  469. data/rust/host/src/web/registrations.rs +1505 -0
  470. data/rust/host/src/web.rs +2937 -0
  471. data/rust/lsp/.gitignore +1 -0
  472. data/rust/lsp/Cargo.lock +7 -0
  473. data/rust/lsp/Cargo.toml +16 -0
  474. data/rust/lsp/README.md +133 -0
  475. data/rust/lsp/src/diagnostics.rs +165 -0
  476. data/rust/lsp/src/json.rs +385 -0
  477. data/rust/lsp/src/main.rs +399 -0
  478. data/rust/lsp/src/outline.rs +177 -0
  479. data/rust/lsp/src/rpc.rs +67 -0
  480. data/rust/parser/.cargo/config.toml +5 -0
  481. data/rust/parser/.gitignore +1 -0
  482. data/rust/parser/Cargo.lock +7 -0
  483. data/rust/parser/Cargo.toml +21 -0
  484. data/rust/parser/src/build/closed_sets.rs +27 -0
  485. data/rust/parser/src/build/identity.rs +276 -0
  486. data/rust/parser/src/build/mod.rs +12 -0
  487. data/rust/parser/src/build/naming.rs +141 -0
  488. data/rust/parser/src/build/pattern_subset.rs +161 -0
  489. data/rust/parser/src/build/query_derive.rs +72 -0
  490. data/rust/parser/src/build/query_inference.rs +269 -0
  491. data/rust/parser/src/build/query_options.rs +100 -0
  492. data/rust/parser/src/build/read_model.rs +94 -0
  493. data/rust/parser/src/build/references.rs +32 -0
  494. data/rust/parser/src/canonical.rs +114 -0
  495. data/rust/parser/src/diag.rs +55 -0
  496. data/rust/parser/src/emit.rs +953 -0
  497. data/rust/parser/src/expr/ast_json.rs +147 -0
  498. data/rust/parser/src/expr/evaluator.rs +81 -0
  499. data/rust/parser/src/expr/mod.rs +84 -0
  500. data/rust/parser/src/expr/resolver.rs +497 -0
  501. data/rust/parser/src/ir.rs +387 -0
  502. data/rust/parser/src/keywords.rs +585 -0
  503. data/rust/parser/src/lex.rs +662 -0
  504. data/rust/parser/src/main.rs +252 -0
  505. data/rust/parser/src/parse/aggregate.rs +612 -0
  506. data/rust/parser/src/parse/chapter.rs +517 -0
  507. data/rust/parser/src/parse/command.rs +637 -0
  508. data/rust/parser/src/parse/domain_port.rs +127 -0
  509. data/rust/parser/src/parse/entity.rs +527 -0
  510. data/rust/parser/src/parse/file.rs +67 -0
  511. data/rust/parser/src/parse/hecksagon.rs +231 -0
  512. data/rust/parser/src/parse/lifecycle.rs +162 -0
  513. data/rust/parser/src/parse/mod.rs +1262 -0
  514. data/rust/parser/src/parse/policy.rs +87 -0
  515. data/rust/parser/src/parse/process_manager.rs +305 -0
  516. data/rust/parser/src/parse/query.rs +100 -0
  517. data/rust/parser/src/parse/read_model.rs +214 -0
  518. data/rust/parser/src/parse/value_object.rs +250 -0
  519. data/rust/parser/src/ruby_value.rs +422 -0
  520. data/rust/project/bridging.rb +257 -0
  521. data/rust/project/commands.rb +877 -0
  522. data/rust/project/constraints.rb +86 -0
  523. data/rust/project/dependency_planning.rb +178 -0
  524. data/rust/project/domain_generator.rb +980 -0
  525. data/rust/project/exemplar.rb +148 -0
  526. data/rust/project/expr_emitter.rb +72 -0
  527. data/rust/project/fielded.rb +141 -0
  528. data/rust/project/json_codec.rb +641 -0
  529. data/rust/project/mutations.rb +721 -0
  530. data/rust/project/naming.rb +205 -0
  531. data/rust/project/ports.rb +65 -0
  532. data/rust/project/queries.rb +493 -0
  533. data/rust/project/reactions.rb +317 -0
  534. data/rust/project/read_models.rb +690 -0
  535. data/rust/project/reference_specs.rb +27 -0
  536. data/rust/project/registry.rb +396 -0
  537. data/rust/project/skip_reason.rb +29 -0
  538. data/rust/project/types.rb +225 -0
  539. data/rust/project/write_if_changed.rb +83 -0
  540. data/rust/project.rb +30 -0
  541. data/rust/project_rust_pipeline.rb +383 -0
  542. data/rust/src/exemplar/commands.rs +279 -0
  543. data/rust/src/exemplar/constraints.rs +18 -0
  544. data/rust/src/exemplar/fielded.rs +280 -0
  545. data/rust/src/exemplar/json.rs +277 -0
  546. data/rust/src/exemplar/mod.rs +17 -0
  547. data/rust/src/exemplar/mutations.rs +80 -0
  548. data/rust/src/exemplar/queries.rs +33 -0
  549. data/rust/src/exemplar/reactions.rs +88 -0
  550. data/rust/src/exemplar/read_models.rs +48 -0
  551. data/rust/src/exemplar/registry.rs +166 -0
  552. data/rust/src/exemplar/types.rs +44 -0
  553. data/rust/src/kernel/attribute_shapes/composite.rs +88 -0
  554. data/rust/src/kernel/attribute_shapes/list.rs +18 -0
  555. data/rust/src/kernel/attribute_shapes/mod.rs +44 -0
  556. data/rust/src/kernel/attribute_shapes/optional.rs +9 -0
  557. data/rust/src/kernel/attribute_shapes/scalar.rs +39 -0
  558. data/rust/src/kernel/cli.rs +585 -0
  559. data/rust/src/kernel/dispatch.rs +1090 -0
  560. data/rust/src/kernel/expr.rs +458 -0
  561. data/rust/src/kernel/expression_operators/arithmetic.rs +128 -0
  562. data/rust/src/kernel/expression_operators/comparison.rs +48 -0
  563. data/rust/src/kernel/expression_operators/enumeration.rs +232 -0
  564. data/rust/src/kernel/expression_operators/logical.rs +13 -0
  565. data/rust/src/kernel/expression_operators/membership.rs +18 -0
  566. data/rust/src/kernel/expression_operators/mod.rs +68 -0
  567. data/rust/src/kernel/expression_operators/pattern_match.rs +73 -0
  568. data/rust/src/kernel/expression_operators/positional.rs +126 -0
  569. data/rust/src/kernel/expression_operators/presence.rs +101 -0
  570. data/rust/src/kernel/expression_operators/sign_test.rs +16 -0
  571. data/rust/src/kernel/expression_operators/sized.rs +35 -0
  572. data/rust/src/kernel/expression_operators/text.rs +79 -0
  573. data/rust/src/kernel/expression_operators/to_string.rs +18 -0
  574. data/rust/src/kernel/json.rs +779 -0
  575. data/rust/src/kernel/mod.rs +133 -0
  576. data/rust/src/kernel/named_query.rs +219 -0
  577. data/rust/src/kernel/orchestrate.rs +1810 -0
  578. data/rust/src/kernel/pattern.rs +307 -0
  579. data/rust/src/kernel/query_comparators.rs +206 -0
  580. data/rust/src/kernel/query_ordering.rs +103 -0
  581. data/rust/src/kernel/read_model.rs +914 -0
  582. data/rust/src/kernel/reference_lookup.rs +149 -0
  583. data/rust/src/kernel/repository.rs +468 -0
  584. data/rust/src/kernel/routing.rs +612 -0
  585. data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +118 -0
  586. data/rust/src/kernel/vocab/entity_dispatch_order.rs +114 -0
  587. data/rust/src/kernel/vocab/field_hint.rs +70 -0
  588. data/rust/src/kernel/vocab/mod.rs +20 -0
  589. data/rust/src/kernel/vocab/query_comparator.rs +65 -0
  590. data/rust/src/kernel/vocab/refusal_template.rs +1592 -0
  591. data/rust/src/lib.rs +8 -0
  592. data/rust/src/main.rs +16 -0
  593. data/rust/web/.gitignore +1 -0
  594. data/rust/web/Cargo.lock +119 -0
  595. data/rust/web/Cargo.toml +18 -0
  596. data/rust/web/src/lib.rs +8 -0
  597. metadata +477 -12
  598. data/lib/hecks/facade/cli_door.rb +0 -96
  599. data/lib/hecks/facade/cli_runner.rb +0 -127
  600. data/lib/hecks/mcp_door_scope.rb +0 -95
@@ -282,7 +282,7 @@ module Hecks
282
282
  end
283
283
 
284
284
  template_yaml = <<~YAML
285
- # GENERATED by bin/project_deploy #{domain} — re-run it to refresh
285
+ # GENERATED by hecks deploy project #{domain} — re-run it to refresh
286
286
  # this file rather than hand-editing. Source: #{world_file}'s own
287
287
  # deployed_to("AwsLambda") block.
288
288
  #
@@ -338,8 +338,8 @@ module Hecks
338
338
  # targets, below) via the SAME `aws cloudformation describe-stacks`
339
339
  # pattern `mint-era` already used for a bastion, one stack over
340
340
  # instead of one sibling stack over. Never a CloudFormation
341
- # Export/ImportValue -- this codebase uses none anywhere (bin/
342
- # project_deploy's own header on why: a live shell lookup keeps
341
+ # Export/ImportValue -- this codebase uses none anywhere (hecks
342
+ # deploy project's own header on why: a live shell lookup keeps
343
343
  # this stack independently deployable/deletable, never coupled to
344
344
  # #{owner_domain_name}'s own stack through CloudFormation itself).
345
345
  OwningVpcId:
@@ -485,13 +485,13 @@ module Hecks
485
485
  " DB_SECRET_ARN: !Sub \"${#{secret_sub}}\""
486
486
  end}
487
487
  # `domain_name`, NOT `infra_name` — this names the actual
488
- # .wasm FILE bin/project_wasm writes (rust/dist/#{domain_name}.wasm,
488
+ # .wasm FILE `hecks build_wasm` writes (rust/dist/#{domain_name}.wasm,
489
489
  # its own target_mod_name convention, a Rust-build-pipeline
490
490
  # concern unrelated to AWS resource identity) and what the
491
491
  # Makefile below actually bundles into the Lambda package
492
492
  # under. Confirmed the hard way: pinning this to infra_name
493
493
  # alongside the real AWS-identity fields left it looking for
494
- # a file bin/project_wasm never produces.
494
+ # a file `hecks build_wasm` never produces.
495
495
  HECKS_WASM_PATH: !Sub "/var/task/#{domain_name}.wasm"
496
496
  # STATIC, not a deploy-time parameter — HECKS_DOMAIN is this
497
497
  # domain's own declared name, known at generation time the
@@ -636,7 +636,7 @@ module Hecks
636
636
  PasswordLength: 64
637
637
  ExcludePunctuation: true
638
638
 
639
- #{webhook_secret_env ? <<-WEBHOOKSECRET : ""}
639
+ #{webhook_secret_env ? <<~WEBHOOKSECRET.rstrip : ""}
640
640
  # Auto-generated, never typed or seen — the SAME
641
641
  # ManageMasterUserPassword/SessionSecret pattern above, applied to
642
642
  # `secret_env`'s own webhook secret instead (deploy_settings' own
@@ -822,7 +822,7 @@ module Hecks
822
822
  Outputs:
823
823
  FunctionUrl:
824
824
  Value: !GetAtt #{logical_id}Url.FunctionUrl#{web_handler_present ? "\n WebFunctionUrl:\n Value: !GetAtt #{web_logical_id}Url.FunctionUrl" : ""}
825
- # stack_outputs (bin/project_deploy, above the heredocs) is the ONE
825
+ # stack_outputs (hecks deploy project, above the heredocs) is the ONE
826
826
  # place these four names live — DatabaseEndpoint/DatabaseSecretArn
827
827
  # feed `make mint-era`'s own boot step directly; VpcId/
828
828
  # DbSecurityGroupId ALSO feed bastion.yaml's own Parameters (a
@@ -831,7 +831,7 @@ module Hecks
831
831
  # network without this main template ever knowing a bastion
832
832
  # exists) and the Makefile's own --parameter-overrides. Rename a
833
833
  # key in that table and every consumer follows; reference one that
834
- # doesn't exist there and bin/project_deploy refuses before
834
+ # doesn't exist there and hecks deploy project refuses before
835
835
  # writing a single file, instead of a bastion.yaml whose Parameter
836
836
  # nothing could ever fill. (`PrivateSubnetId` used to sit here too
837
837
  # — dropped, nothing ever consumed it; bastion.yaml mints its own
@@ -899,7 +899,7 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
899
899
  <<~SHAREDMINT.rstrip
900
900
  # NOT AUTOMATED YET for a Shared-mode domain — it has no RDS/VPC
901
901
  # of its own to stand a temporary bastion next to (bastion.yaml
902
- # itself isn't even generated here — bin/project_deploy's own
902
+ # itself isn't even generated here — hecks deploy project's own
903
903
  # comment on why). Minting era 1 for #{infra_name}'s own schema
904
904
  # needs a tunnel to #{owner_domain_name}'s ALREADY-EXISTING RDS
905
905
  # instance instead -- reuse #{owner_domain_name}'s own deploy
@@ -948,7 +948,7 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
948
948
  else
949
949
  <<~OWNMINT.rstrip
950
950
  \t@echo "Looking up $(STACK)'s VPC/security group..."
951
- # stack_outputs/bastion_parameters (bin/project_deploy) are the ONE
951
+ # stack_outputs/bastion_parameters (hecks deploy project) are the ONE
952
952
  # place these OutputKey strings and parameter names live — this eval
953
953
  # chain and the --parameter-overrides line just below are both
954
954
  # generated from the SAME table template.yaml's Outputs and
@@ -1067,13 +1067,13 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
1067
1067
  \techo "Tearing down the temporary bastion stack..."; \\
1068
1068
  \taws cloudformation delete-stack --stack-name $(BASTION_STACK); \\
1069
1069
  \taws cloudformation wait stack-delete-complete --stack-name $(BASTION_STACK); \\
1070
- \techo "$(BASTION_STACK) deleted. Era 1 should now be held if BOOT_STATUS was 0 — verify with bin/console or a Postgres query against hecks_eras."; \\
1070
+ \techo "$(BASTION_STACK) deleted. Era 1 should now be held if BOOT_STATUS was 0 — verify with hecks console or a Postgres query against hecks_eras."; \\
1071
1071
  \texit $$BOOT_STATUS
1072
1072
  OWNMINT
1073
1073
  end
1074
1074
 
1075
1075
  # Shares mint_era_recipe's bastion/tunnel/retry/teardown chain but
1076
- # runs bin/scaffold_translation or bin/translation_audit over it.
1076
+ # runs `hecks ask scaffold_translation` or `hecks ask audit_translation` over it.
1077
1077
  #
1078
1078
  # Neither script actually reads DATABASE_URL/HECKS_SCHEMA (both call
1079
1079
  # `registry.binding_settings`, a lookup against the literal `database
@@ -1081,7 +1081,8 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
1081
1081
  # recipe would open a real tunnel to production and silently
1082
1082
  # scaffold/audit the local dev database instead, reporting success.
1083
1083
  # `db_env_blind` refuses unless `ALLOW_LOCAL_DB=1` is set.
1084
- translation_recipe = lambda do |verb, script, extra_args = "", cwd: "$(ROOT)", run_prefix: "ruby -Ilib", db_env_blind: false|
1084
+ translation_recipe = lambda do |verb, script, extra_args = "", cwd: "$(ROOT)", run_prefix: "ruby -Ilib", db_env_blind: false,
1085
+ domain_arg: "$(DOMAIN) "|
1085
1086
  if shared
1086
1087
  <<~SHAREDTRANSLATION.rstrip
1087
1088
  \t@echo "#{verb} isn't automated yet for a Shared-mode domain (database \\"Shared\\") -- see mint-era's own comment in the generated Makefile for the manual path through #{owner_domain_name}'s own tunnel."; \\
@@ -1130,7 +1131,7 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
1130
1131
  \t\t\tnc -z localhost 15432 2>/dev/null && break; \\
1131
1132
  \t\t\tsleep 1; \\
1132
1133
  \t\tdone; \\
1133
- \t\tcd #{cwd} && DATABASE_URL="postgres://postgres:$$DB_PASS_URLENC@localhost:15432/#{db_name}" HECKS_SCHEMA="#{hecks_schema}" #{run_prefix} #{script} #{cwd == "$(ROOT)" ? "$(DOMAIN) " : ""}#{extra_args}&& { RUN_STATUS=0; break; }; \\
1134
+ \t\tcd #{cwd} && DATABASE_URL="postgres://postgres:$$DB_PASS_URLENC@localhost:15432/#{db_name}" HECKS_SCHEMA="#{hecks_schema}" #{run_prefix} #{script} #{cwd == "$(ROOT)" ? domain_arg : ""}#{extra_args}&& { RUN_STATUS=0; break; }; \\
1134
1135
  \t\tRUN_STATUS=$$?; \\
1135
1136
  \t\techo "#{verb} attempt $$attempt/5 failed (exit $$RUN_STATUS) -- restarting the tunnel and retrying in 3s..."; \\
1136
1137
  \t\tsleep 3; \\
@@ -1145,12 +1146,22 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
1145
1146
  end
1146
1147
  end
1147
1148
 
1148
- scaffold_translation_recipe = translation_recipe.call("scaffold-translation", "bin/scaffold_translation", db_env_blind: true)
1149
- translation_audit_recipe = translation_recipe.call("translation-audit", "bin/translation_audit", db_env_blind: true)
1149
+ # `hecks ask` answers the scaffold as text, and refuses (exit 1) where the script aborted.
1150
+ scaffold_translation_recipe = translation_recipe.call(
1151
+ "scaffold-translation", "exe/hecks ask scaffold_translation", db_env_blind: true,
1152
+ run_prefix: "HECKS_ENVIRONMENT=memory ruby", domain_arg: "domain=$(DOMAIN) "
1153
+ )
1154
+ # A refused audit is a refused query: `hecks ask` exits 1, so the target fails too.
1155
+ translation_audit_recipe = translation_recipe.call(
1156
+ "translation-audit", "exe/hecks ask audit_translation", db_env_blind: true,
1157
+ run_prefix: "HECKS_ENVIRONMENT=memory ruby", domain_arg: "domain=$(DOMAIN) "
1158
+ )
1150
1159
 
1151
1160
  # Same chain, running an app-owned one-time migration script instead
1152
- # of a hecks bin/ tool. Harmless when the domain has none: `bundle
1153
- # exec ruby` on a missing file just fails loudly.
1161
+ # of a hecks tool. `bin/migrate_console_settings` belongs to the domain's own
1162
+ # application, not to hecks, so it stays a `bin/` path when hecks drops its own.
1163
+ # Harmless when the domain has none: `bundle exec ruby` on a missing file just fails
1164
+ # loudly.
1154
1165
  migrate_console_settings_recipe = translation_recipe.call(
1155
1166
  "migrate-console-settings", "bin/migrate_console_settings", "",
1156
1167
  cwd: "$(DOMAIN)", run_prefix: "bundle exec ruby"
@@ -1354,7 +1365,7 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
1354
1365
  ).map { |l| "\t#{l}" }.join("\n")
1355
1366
 
1356
1367
  makefile_content = <<~MAKE
1357
- # GENERATED by bin/project_deploy #{domain} — re-run it to refresh
1368
+ # GENERATED by hecks deploy project #{domain} — re-run it to refresh
1358
1369
  # this file rather than hand-editing.
1359
1370
  #
1360
1371
  # `sam build` invokes the build-<LogicalId> target below (SAM's own
@@ -1365,7 +1376,7 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
1365
1376
  # `brew install cargo-lambda`.
1366
1377
 
1367
1378
  HOST_DIR := #{File.join(root, "rust", "host")}
1368
- # `domain_name`, matching bin/project_wasm's own target_mod_name
1379
+ # `domain_name`, matching `hecks build_wasm`'s own target_mod_name
1369
1380
  # (a Rust-build-pipeline naming convention, not AWS resource
1370
1381
  # identity — see HECKS_WASM_PATH's own comment above).
1371
1382
  WASM := #{File.join(root, "rust", "dist", "#{domain_name}.wasm")}
@@ -1380,13 +1391,13 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
1380
1391
  # start of a work session silently kept getting deployed through
1381
1392
  # every later kernel change (a real, live bug: this cost a stale
1382
1393
  # deploy against a wasm that predated the kernel's own "mutations"
1383
- # field). `bin/project_wasm` recompiles fast enough that "always
1394
+ # field). `hecks build_wasm` recompiles fast enough that "always
1384
1395
  # rebuild" is the safe default, matching rust/host's own bootstrap
1385
1396
  # build just below, which was never guarded this way to begin with.
1386
- \tcd #{root} && bin/project_wasm #{domain}
1397
+ \tcd #{root} && HECKS_ENVIRONMENT=memory ruby exe/hecks build_wasm domain=#{domain} --wait
1387
1398
  \t@rustup target list --installed 2>/dev/null | grep -qx aarch64-unknown-linux-gnu || rustup target add aarch64-unknown-linux-gnu
1388
1399
  # `rustup run stable`, not a bare `cargo lambda` — same reasoning
1389
- # bin/project_wasm's own Makefile-equivalent line holds itself to: a
1400
+ # `hecks build_wasm`'s own Makefile-equivalent line holds itself to: a
1390
1401
  # `cargo`/`rustc` earlier on PATH than rustup's own shims (Homebrew
1391
1402
  # installs one; common on this kind of machine) is a DIFFERENT
1392
1403
  # toolchain that never saw `rustup target add`, and fails with
@@ -1452,26 +1463,26 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
1452
1463
  # `make verify-parity-#{logical_id}` — closes the exact gap the
1453
1464
  # equivalence-gap plan's own Phase 8 named: parity was checked ONLY
1454
1465
  # against CI's fixed test corpus, completely decoupled from what a
1455
- # real `sam deploy` actually ships — `bin/rust_conformance` (the
1466
+ # real `sam deploy` actually ships — `hecks check_conformance` (the
1456
1467
  # differential harness, docs/decisions/0010-ruby-is-the-reference-
1457
1468
  # implementation.md) had never once been run against a specific
1458
1469
  # compiled deploy artifact. Runs it here, for real, against
1459
1470
  # $(WASM) -- the EXACT file `build-#{logical_id}` (above) just built
1460
1471
  # and `deploy:` (below) is about to ship -- not a corpus-wide `cargo
1461
- # build`'s own separate binary. `bin/rust_conformance` exits non-zero
1472
+ # build`'s own separate binary. `hecks check_conformance --wait` exits non-zero
1462
1473
  # on any mismatch, which this target lets propagate uncaught: a real
1463
1474
  # divergence between THIS artifact and Ruby's own reading of the
1464
1475
  # identical source blocks `make deploy` before `sam deploy` ever
1465
1476
  # runs, the same way a failing build already would.
1466
1477
  #
1467
1478
  # `spec/corpus/#{domain_name}.json` is this domain's OWN pinned
1468
- # fuzzer-replay script (the same shape `bin/fuzz`/`bin/run` already
1479
+ # fuzzer-replay script (the same shape `hecks fuzz`/`hecks run` already
1469
1480
  # use) -- if a domain doesn't have one yet, this warns LOUDLY and
1470
1481
  # continues rather than either silently skipping (this project's own
1471
1482
  # standing rule against a silent gap reading as full coverage) or
1472
1483
  # blocking every deploy of a domain nobody has written one for yet.
1473
1484
  #
1474
- # SECOND HALF, BELOW — `bin/rust_conformance_fuzz`, ADR 0037's own fuzz
1485
+ # SECOND HALF, BELOW — `hecks fuzz_conformance`, ADR 0037's own fuzz
1475
1486
  # bridge pointed at this exact $(WASM). A pinned script only proves
1476
1487
  # "matches Ruby on the cases we thought to write down" (ADR 0039's own
1477
1488
  # honest framing); the fuzz bridge is what actually FOUND Findings 1-6.
@@ -1485,12 +1496,12 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
1485
1496
  .PHONY: verify-parity-#{logical_id}
1486
1497
  verify-parity-#{logical_id}:
1487
1498
  \t@if [ -f #{root}/spec/corpus/#{domain_name}.json ]; then \\
1488
- \t\tcd #{root} && bin/rust_conformance #{domain} spec/corpus/#{domain_name}.json $(WASM); \\
1499
+ \t\tcd #{root} && HECKS_ENVIRONMENT=memory ruby exe/hecks check_conformance domain=#{domain} script=spec/corpus/#{domain_name}.json artifact=$(WASM) --wait; \\
1489
1500
  \telse \\
1490
- \t\techo "verify-parity-#{logical_id}: no spec/corpus/#{domain_name}.json -- SKIPPING the pre-deploy Ruby/Rust parity check, nothing to compare $(WASM) against. Write one (bin/fuzz/bin/run's own script shape) before this domain's next deploy."; \\
1501
+ \t\techo "verify-parity-#{logical_id}: no spec/corpus/#{domain_name}.json -- SKIPPING the pre-deploy Ruby/Rust parity check, nothing to compare $(WASM) against. Write one (hecks fuzz/hecks run's own script shape) before this domain's next deploy."; \\
1491
1502
  \tfi
1492
1503
  \t@echo "verify-parity-#{logical_id}: fuzzing $(WASM) against generated sequences (ADR 0037's bridge, WARN-ONLY -- see this target's own comment)..."
1493
- \t-@cd #{root} && bin/rust_conformance_fuzz #{domain} $(WASM)
1504
+ \t-@cd #{root} && HECKS_ENVIRONMENT=memory ruby exe/hecks fuzz_conformance domain=#{domain} artifact=$(WASM) --wait
1494
1505
 
1495
1506
  # `make mint-era` — takes #{stack_name}'s RDS instance from freshly
1496
1507
  # created to "era 1 minted, ready for HECKS_DOMAIN/HECKS_ERA to
@@ -1713,7 +1724,7 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
1713
1724
  # safe either way, since mint-era's own quiet-reboot path is a
1714
1725
  # no-op the moment nothing has actually changed.
1715
1726
  #
1716
- # See predeploy_bridge_shell's own comment (bin/project_deploy,
1727
+ # See predeploy_bridge_shell's own comment (hecks deploy project,
1717
1728
  # above, right before deploy_recipe_lines) for why this branches
1718
1729
  # on google_oauth_present at all -- the short version: adding
1719
1730
  # Google OAuth to an EXISTING stack would otherwise deadlock this
@@ -1729,7 +1740,7 @@ bastion_yaml = shared ? nil : Shared.bastion_yaml(
1729
1740
  # Everything `sam deploy --guided` would ask interactively is already
1730
1741
  # known from the domain's own `deployed_to("AwsLambda")` block.
1731
1742
  samconfig_toml = <<~TOML
1732
- # GENERATED by bin/project_deploy #{domain} — re-run it to refresh
1743
+ # GENERATED by hecks deploy project #{domain} — re-run it to refresh
1733
1744
  # this file rather than hand-editing.
1734
1745
  version = 0.1
1735
1746
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # GENERATED by bin/project_deploy - re-run it to refresh this file rather than
2
+ # GENERATED by hecks deploy project - re-run it to refresh this file rather than
3
3
  # hand-editing. Source: the `preview` block of the domain's deployed_to("AwsFargate").
4
4
  #
5
5
  # Feature-branch previews of <%= s.infra_name %>: one isolated stack per git branch,
@@ -28,7 +28,7 @@ module Hecks
28
28
 
29
29
  def header(settings)
30
30
  <<~YAML.chomp
31
- # GENERATED by bin/project_deploy - re-run it to refresh this file rather than
31
+ # GENERATED by hecks deploy project - re-run it to refresh this file rather than
32
32
  # hand-editing. Source: the `preview` block of the domain's deployed_to("AwsFargate").
33
33
  #
34
34
  # One stack per git branch, driven by preview.sh. A separate template from the main
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # GENERATED by bin/project_deploy -- re-run it to refresh this file rather
2
+ # GENERATED by hecks deploy project -- re-run it to refresh this file rather
3
3
  # than hand-editing. Settings come from the domain's deployed_to("AwsFargate")
4
4
  # block; see Hecks::Projections::Deploy::Scripts for each key.
5
5
  #
@@ -13,5 +13,5 @@
13
13
  # The id is what the host reports at GET /version, the same id the era mint
14
14
  # prints. Compare a live host with this file:
15
15
  #
16
- # bin/check_era https://host.example expected-era
16
+ # hecks check_era host=https://host.example expected=expected-era --wait
17
17
  # make check-era URL=https://host.example
@@ -1,4 +1,4 @@
1
- # GENERATED by bin/project_deploy -- re-run it to refresh this file rather
1
+ # GENERATED by hecks deploy project -- re-run it to refresh this file rather
2
2
  # than hand-editing. Included by the Makefile beside it; settings come from the
3
3
  # domain's deployed_to("AwsFargate") block (see
4
4
  # Hecks::Projections::Deploy::Scripts for each key).
@@ -24,7 +24,7 @@ build: hecks-release
24
24
  # Fetches the pinned release's tag into HECKS_ROOT unless it is already there,
25
25
  # and refuses a checkout that is not exactly that tag.
26
26
  hecks-release:
27
- @if [ -f "$(HECKS_ROOT)/bin/project_wasm" ]; then \
27
+ @if [ -f "$(HECKS_ROOT)/exe/hecks" ]; then \
28
28
  echo "hecks v$(HECKS_VERSION) is already at $(HECKS_ROOT)"; \
29
29
  else \
30
30
  echo "Fetching hecks v$(HECKS_VERSION) from $(HECKS_SOURCE) into $(HECKS_ROOT)..."; \
@@ -51,4 +51,4 @@ smoke-after-deploy:
51
51
  # Compares the era a live host reports at GET /version with expected-era.
52
52
  check-era:
53
53
  @test -n "$(URL)" || { echo "usage: make check-era URL=https://host.example"; exit 1; }
54
- ruby "$(HECKS_ROOT)/bin/check_era" "$(URL)" expected-era
54
+ HECKS_ENVIRONMENT=memory ruby "$(HECKS_ROOT)/exe/hecks" check_era host="$(URL)" expected=expected-era --wait
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # GENERATED by bin/project_deploy -- re-run it to refresh this file rather
2
+ # GENERATED by hecks deploy project -- re-run it to refresh this file rather
3
3
  # than hand-editing. Settings come from the domain's deployed_to("AwsFargate")
4
4
  # block; see Hecks::Projections::Deploy::Scripts for each key.
5
5
  #
@@ -390,7 +390,7 @@ module Hecks
390
390
  # @return [String] the rendered CloudFormation template
391
391
  def bastion_yaml(domain:, infra_name:, stack_name:, db_id:, google_oauth_present:, bastion_parameters:)
392
392
  <<~YAML
393
- # GENERATED by bin/project_deploy #{domain} — re-run it to refresh
393
+ # GENERATED by hecks deploy project #{domain} — re-run it to refresh
394
394
  # this file rather than hand-editing. Deployed and destroyed by
395
395
  # `make mint-era` (this directory's own Makefile) — never left
396
396
  # running: it exists only long enough for one Ruby boot to reach
@@ -70,12 +70,12 @@ module Hecks
70
70
 
71
71
  def holders_with_lifecycle(bluebook) = holders(bluebook).select(&:lifecycle)
72
72
 
73
- # `chapter_name` drives the re-run hint: `bin/project_diagrams` takes a chapter
73
+ # `chapter_name` drives the re-run hint: `hecks project_diagrams` takes a chapter
74
74
  # name, not the subject's.
75
75
  def header(chapter_name, subject)
76
76
  <<~HEADER
77
- %% GENERATED by bin/project_diagrams from #{subject} — DO NOT EDIT BY HAND.
78
- %% Re-run `bin/project_diagrams <domain-path> #{chapter_name}` after any change.
77
+ %% GENERATED by hecks project_diagrams from #{subject} — DO NOT EDIT BY HAND.
78
+ %% Re-run `hecks project_diagrams <domain-path> #{chapter_name}` after any change.
79
79
  HEADER
80
80
  end
81
81
 
@@ -48,7 +48,7 @@ module Hecks
48
48
  # Fields emitted by `to_h`'s own merge rather than `emits_ir`, for constructs
49
49
  # whose shape is not fixed.
50
50
  DYNAMIC_TAIL = {
51
- "Query" => %i[options],
51
+ "Query" => %i[options returns],
52
52
  "ReadModel" => %i[options group_by aggregate_heads count median_field sum_field avg_field
53
53
  min_field max_field percentile_field percentile_at any_field all_field]
54
54
  }.freeze
@@ -13,7 +13,7 @@ module Hecks
13
13
  # Projects the Rust parser's keyword and closed-set tables for one chapter.
14
14
  #
15
15
  # @param bluebook [Bluebook::Chapter] the chapter to project; the language's own
16
- # for the ordinary `bin/project_parser_table` run
16
+ # for the ordinary `hecks project_parser_table` run
17
17
  # @param options [Hash{Symbol => Object}] ignored; present to satisfy the
18
18
  # `Projector::Target` calling convention
19
19
  # @return [String] the rendered Rust source
@@ -98,14 +98,14 @@ module Hecks
98
98
  arguments = table[:arguments]
99
99
 
100
100
  <<~RUST
101
- // GENERATED by bin/project_parser_table from
101
+ // GENERATED by hecks project_parser_table from
102
102
  // aggregate-local syntax tables under lib/hecks/language/ — DO NOT EDIT BY HAND.
103
103
  //
104
- // Re-run `bin/project_parser_table` after any syntax-table change.
104
+ // Re-run `hecks project_parser_table` after any syntax-table change.
105
105
  // spec/parser_table_spec.rb regenerates this into memory and fails the
106
106
  // normal `bundle exec rspec` suite the moment this file drifts from what
107
107
  // the language currently declares — see that spec and
108
- // bin/project_parser_table's own header for why this file is never
108
+ // hecks project_parser_table's own header for why this file is never
109
109
  // hand-edited.
110
110
 
111
111
  #[derive(Debug, Clone, Copy)]
@@ -1,9 +1,8 @@
1
1
  require_relative "../projector"
2
2
 
3
3
  module Hecks
4
- # Repository-only tooling: `Doc::Reference` reads the committed pages under
5
- # `docs/`, which only a checkout has, so it loads on first use and the
6
- # packaged gem leaves it out (ADR 0066).
4
+ # `Doc::Reference` reads the committed pages under `docs/`, which only a
5
+ # checkout has, so it loads on first use.
7
6
  module Doc
8
7
  autoload :Reference, File.expand_path("../doc/reference", __dir__)
9
8
  end
@@ -14,7 +14,7 @@ module Hecks
14
14
 
15
15
  projects_as :rust_vocabulary, declares: "Vocabulary", emits: :files
16
16
 
17
- GENERATOR = "bin/project_rust_vocabulary".freeze
17
+ GENERATOR = "hecks project_rust_vocabulary".freeze
18
18
  SOURCE = "lib/hecks/language/bluebook/vocabulary.bluebook".freeze
19
19
 
20
20
  # Table name => enum name, variant-naming fields, file stem and kind.
@@ -3,21 +3,21 @@ require_relative "../naming"
3
3
  module Hecks
4
4
  module Projector
5
5
  # Projects a bluebook as its own command-line surface: the verb tree, argument spec
6
- # and usage text. Nothing executes here; the generic runner (`bin/run`) parses against it.
6
+ # and usage text. Nothing executes here; the generic runner (`hecks run`) parses against it.
7
7
  #
8
8
  # Argument types come from the declared field types, never from guessing at the
9
9
  # string: `sequence.value=99` must become 99, and a version "99" must stay a String.
10
10
  module CliProjector
11
11
  module_function
12
12
 
13
- # Projects the verb and question tables and the usage text.
14
- #
15
- # Commands and queries are separate namespaces because a chapter may declare both
16
- # under one name; questions are asked with `ask`.
13
+ # Projects the verb and question tables and the usage text. Commands and queries are
14
+ # separate namespaces (a chapter may declare both under one name); ask a query with `ask`.
17
15
  #
18
16
  # @param bluebook [Bluebook::Chapter] the booted domain to project
19
- # @param options [Hash{Symbol => Object}] `:program` (default `"bin/run"`) for the usage
20
- # text; `:verb` and `:ask` select one verb's `--help` text
17
+ # @param options [Hash{Symbol => Object}] `:program` (default `"hecks run"`) for the usage
18
+ # text; `:verb` and `:ask` select one verb's `--help` text; `:names` maps a launcher
19
+ # name to the command it stands for (`{ "mcp" => "serve_mcp" }`); `:mint_run_keys` makes a
20
+ # creating verb's `run` key optional, since the launcher mints it
21
21
  # @return [Hash{Symbol => Object}] `:verbs`, `:questions`, `:names` (alias tables) and
22
22
  # `:usage` (pre-rendered help text)
23
23
  # @raise [Bluebook::DSL::Malformed] if two verbs project to the same command-line name
@@ -25,24 +25,7 @@ module Hecks
25
25
  verbs = {}
26
26
  questions = {}
27
27
 
28
- bluebook.aggregates.each do |aggregate|
29
- aggregate.commands.each { |c| claim(verbs, name_for(aggregate, c), command_spec(bluebook, aggregate, nil, c)) }
30
- aggregate.queries.each { |q| claim(questions, name_for(aggregate, q), query_spec(bluebook, aggregate, nil, q)) }
31
-
32
- aggregate.entities.each do |entity|
33
- entity.commands.each do |c|
34
- claim(verbs, name_for(aggregate, c, entity), command_spec(bluebook, aggregate, entity, c))
35
- end
36
- entity.queries.each do |q|
37
- claim(questions, name_for(aggregate, q, entity), query_spec(bluebook, aggregate, entity, q))
38
- end
39
- end
40
-
41
- # Port operations dispatch by the same name as a command, so they are verbs too.
42
- aggregate.ports.each do |port|
43
- port.operations.each { |o| claim(verbs, name_for(aggregate, o), port_spec(bluebook, aggregate, port, o)) }
44
- end
45
- end
28
+ bluebook.aggregates.each { |aggregate| claim_aggregate(verbs, questions, bluebook, aggregate) }
46
29
 
47
30
  # A report belongs to the chapter, not an aggregate, so it is addressed
48
31
  # `Chapter.Report` (one dot) where a query is `Chapter::Aggregate.Query`.
@@ -50,15 +33,42 @@ module Hecks
50
33
  claim(questions, Naming.snake(model.hecks_name), report_spec(bluebook, model))
51
34
  end
52
35
 
36
+ mint_run_keys(verbs) if options[:mint_run_keys]
37
+
53
38
  # The display name is the shortest unambiguous one; both spellings are accepted.
54
- shorten(verbs)
55
- shorten(questions)
39
+ display_names([verbs, questions], options[:names])
56
40
 
57
41
  { verbs: verbs, questions: questions,
58
42
  names: { command: aliases(verbs), question: aliases(questions) },
59
43
  usage: usage(bluebook, verbs, questions, options) }
60
44
  end
61
45
 
46
+ # Claims the verbs and questions of one aggregate and its entities and ports.
47
+ #
48
+ # @param verbs [Hash{String => Hash}] the verb map, mutated in place
49
+ # @param questions [Hash{String => Hash}] the question map, mutated in place
50
+ # @param bluebook [Bluebook::Chapter] the booted domain
51
+ # @param aggregate [Bluebook::Aggregate] the aggregate to claim
52
+ # @return [void]
53
+ def claim_aggregate(verbs, questions, bluebook, aggregate)
54
+ aggregate.commands.each { |c| claim(verbs, name_for(aggregate, c), command_spec(bluebook, aggregate, nil, c)) }
55
+ aggregate.queries.each { |q| claim(questions, name_for(aggregate, q), query_spec(bluebook, aggregate, nil, q)) }
56
+
57
+ aggregate.entities.each do |entity|
58
+ entity.commands.each do |c|
59
+ claim(verbs, name_for(aggregate, c, entity), command_spec(bluebook, aggregate, entity, c))
60
+ end
61
+ entity.queries.each do |q|
62
+ claim(questions, name_for(aggregate, q, entity), query_spec(bluebook, aggregate, entity, q))
63
+ end
64
+ end
65
+
66
+ # Port operations dispatch by the same name as a command, so they are verbs too.
67
+ aggregate.ports.each do |port|
68
+ port.operations.each { |o| claim(verbs, name_for(aggregate, o), port_spec(bluebook, aggregate, port, o)) }
69
+ end
70
+ end
71
+
62
72
  # Sets `:short` on each spec: the last segment when exactly one verb ends in it,
63
73
  # else the full name (two aggregates both declaring `Close` keep both spellings).
64
74
  #
@@ -72,11 +82,62 @@ module Hecks
72
82
  end
73
83
  end
74
84
 
75
- # Maps every accepted spelling (full name and `:short`) to the full name.
85
+ # Marks the `run` key of each creating verb `minted`: optional, and never filled by a bare
86
+ # word, since the launcher makes one when it is left out.
87
+ def mint_run_keys(verbs)
88
+ verbs.each_value do |spec|
89
+ next unless spec[:creates]
90
+
91
+ spec[:arguments] = spec[:arguments].map do |argument|
92
+ next argument unless argument[:path] == "run.value"
93
+
94
+ argument.merge(required: false, minted: true, note: "minted when omitted")
95
+ end
96
+ end
97
+ end
98
+
99
+ # Sets the display name of every spec in each map: shortened, then renamed by `names`.
100
+ #
101
+ # @param maps [Array<Hash{String => Hash}>] the verb and question maps, mutated in place
102
+ # @param names [Hash, nil] the chapter's launcher names
103
+ # @return [void]
104
+ def display_names(maps, names)
105
+ maps.each do |specs|
106
+ shorten(specs)
107
+ rename(specs, names)
108
+ end
109
+ end
110
+
111
+ # Gives a command the launcher name a chapter's `names` table assigns it.
112
+ #
113
+ # The alias replaces the short name in help, so it is listed once; the spelling it
114
+ # replaced keeps working (`:short_was`, read by `aliases`). A table entry naming no
115
+ # command in `specs` belongs to the other namespace and is skipped.
116
+ #
117
+ # @param specs [Hash{String => Hash}] the verb or question map, mutated in place
118
+ # @param names [Hash{String, Symbol => String, Symbol}, nil] launcher name to command name
119
+ # @return [void]
120
+ # @raise [Bluebook::DSL::Malformed] if a launcher name is already another command's name
121
+ def rename(specs, names)
122
+ Hash(names).each do |launcher_name, command|
123
+ found = specs.find { |key, spec| [key, spec[:short]].include?(command.to_s) }
124
+ next unless found
125
+
126
+ taken = specs.values.any? { |spec| spec[:short] == launcher_name.to_s }
127
+ raise Bluebook::DSL::Malformed, "launcher name #{launcher_name.to_s.inspect} is already a command" if taken
128
+
129
+ found.last[:short_was] = found.last[:short]
130
+ found.last[:short] = launcher_name.to_s
131
+ end
132
+ end
133
+
134
+ # Maps every accepted spelling (full name, `:short` and a renamed command's old short
135
+ # name) to the full name.
76
136
  def aliases(specs)
77
137
  specs.each_with_object({}) do |(name, spec), map|
78
138
  map[name] = name
79
139
  map[spec[:short]] = name
140
+ map[spec[:short_was]] = name if spec[:short_was]
80
141
  end
81
142
  end
82
143
 
@@ -148,7 +209,8 @@ module Hecks
148
209
  creates: command.creates?,
149
210
  receiver: receiver, legacy_receiver: (receiver == :aggregate ? :id : nil),
150
211
  legacy_arguments: legacy_arguments,
151
- refusals: refusals(command, holder), arguments: arguments }
212
+ refusals: refusals(command, holder), requirements: requirements(command),
213
+ arguments: arguments }
152
214
  end
153
215
 
154
216
  # A port operation reads as a verb but reports as a boundary: it creates no
@@ -202,7 +264,7 @@ module Hecks
202
264
  end
203
265
 
204
266
  { verb: fqn(bluebook, aggregate, query, entity), kind: :query,
205
- summary: query.description, arguments: arguments }
267
+ summary: query.description, arguments: arguments, returns: query.returns }
206
268
  end
207
269
 
208
270
  # Flattens an attribute into one option per leaf field. A value object becomes
@@ -243,8 +305,11 @@ module Hecks
243
305
  note: "id of a #{attribute.type.target_name}" }
244
306
  end
245
307
 
308
+ # A `list_of` scalar carries `list: true, words: true`: the launcher reads a comma-separated
309
+ # value or a repeated name as the list's elements, since the runtime refuses a lone scalar.
246
310
  def scalar_option(path, field, optional, enum: [])
247
311
  option = { path: path, type: field.type.to_s, required: !optional }
312
+ option.merge!(list: true, words: true, note: "list: comma-separated or repeated") if field.list?
248
313
  option[:enum] = enum unless enum.empty?
249
314
  option[:pattern] = field.pattern if field.respond_to?(:pattern) && field.pattern
250
315
  option[:default] = field.default if field.respond_to?(:default) && !field.default.nil?
@@ -270,8 +335,8 @@ module Hecks
270
335
  nil
271
336
  end
272
337
 
273
- # Every way the verb can say no, in the chapter's own words: a lifecycle state
274
- # mismatch, a missing referenced record per `reference_to`, then each `given`.
338
+ # The conditions that refuse the verb when they hold, in the chapter's own words: a
339
+ # lifecycle state mismatch and a missing referenced record per `reference_to`.
275
340
  def refusals(command, holder)
276
341
  out = []
277
342
  lifecycle = holder.lifecycle
@@ -280,13 +345,17 @@ module Hecks
280
345
  end.flatten.uniq
281
346
  out << "#{lifecycle.field} is not #{froms.join(' or ')}" if froms && !froms.empty?
282
347
  out += command.attributes.select(&:reference?).map { |r| "no #{r.type.target_name} has that #{r.name}" }
283
- out + command.givens.map(&:description)
348
+ out
284
349
  end
285
350
 
351
+ # The conditions the verb needs: each `given` states what must hold, so the verb is
352
+ # refused unless it does.
353
+ def requirements(command) = command.givens.map(&:description)
354
+
286
355
  # Renders the full verb/question table, or one verb's `--help` text when
287
356
  # `options[:verb]` names one.
288
357
  def usage(bluebook, verbs, questions, options)
289
- program = options[:program] || "bin/run"
358
+ program = options[:program] || "hecks run"
290
359
  only = options[:verb]
291
360
 
292
361
  # `options[:ask]` picks the namespace when both hold the name; without it a
@@ -366,9 +435,9 @@ module Hecks
366
435
  end
367
436
 
368
437
  def verb_help_refusal_lines(spec)
369
- return [] if Array(spec[:refusals]).empty?
370
-
371
- ["refused when:", *spec[:refusals].map { |refusal| " #{refusal}" }, ""]
438
+ [["refused when:", spec[:refusals]], ["refused unless:", spec[:requirements]]].flat_map do |heading, items|
439
+ Array(items).empty? ? [] : [heading, *items.map { |item| " #{item}" }, ""]
440
+ end
372
441
  end
373
442
  end
374
443
  end
@@ -6,7 +6,7 @@ module Hecks
6
6
  #
7
7
  # A projection is inert and derived from a chapter's declaration. An export
8
8
  # (rust crate, WASM, CloudFormation) also needs `.world` bindings and declares
9
- # `needs_world: true`. State projections (`bin/expression_projection`) and
9
+ # `needs_world: true`. State projections (`hecks project_expression_tables`) and
10
10
  # `Ports::Projection` read-model catch-up are different things and not registered.
11
11
  module Projector
12
12
  class UnknownProjector < StandardError; end