hecks 7.0.0 → 7.1.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 (257) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hecks/adapters/driven/postgres_era/lineage/chain_sql.rb +2 -1
  3. data/lib/hecks/adapters/driven/postgres_era/lineage/provisioning.rb +4 -2
  4. data/lib/hecks/adapters/driven/postgres_era/lineage/split_sql.rb +16 -8
  5. data/lib/hecks/adapters/driven/postgres_era/lineage/transform_sql.rb +7 -3
  6. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolver.rb +2 -1
  7. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/mint_request.rb +2 -1
  8. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/refusals.rb +2 -1
  9. data/lib/hecks/adapters/driving/cli_runner/bang_rule.rb +3 -0
  10. data/lib/hecks/adapters/driving/cli_runner/completion_words.rb +2 -0
  11. data/lib/hecks/adapters/driving/cli_runner/read_context.rb +6 -3
  12. data/lib/hecks/adapters/driving/cli_runner/renamed_names.rb +2 -1
  13. data/lib/hecks/adapters/driving/cli_runner/resolution.rb +2 -2
  14. data/lib/hecks/adapters/driving/cli_runner/resume_words.rb +1 -0
  15. data/lib/hecks/adapters/driving/cli_runner/run_reference.rb +6 -3
  16. data/lib/hecks/adapters/driving/cli_runner/search_words.rb +2 -0
  17. data/lib/hecks/adapters/driving/cli_runner/tour_words.rb +1 -0
  18. data/lib/hecks/adapters/driving/cli_runner/verb_names.rb +2 -1
  19. data/lib/hecks/adapters/driving/cli_runner/verbosity.rb +2 -0
  20. data/lib/hecks/adapters/driving/cli_runner/word_help.rb +40 -0
  21. data/lib/hecks/adapters/driving/cli_runner.rb +2 -0
  22. data/lib/hecks/adapters/driving/mcp/progress_sink.rb +4 -2
  23. data/lib/hecks/adapters/driving/mcp.rb +2 -1
  24. data/lib/hecks/adapters/driving/mcp_scope/argument_policy.rb +2 -1
  25. data/lib/hecks/adapters/driving/ruby/aggregate_module/hooks.rb +28 -14
  26. data/lib/hecks/adapters/driving/ruby/aggregate_module.rb +4 -2
  27. data/lib/hecks/assembly.rb +18 -4
  28. data/lib/hecks/behaviors/expectations/adapter_selection.rb +82 -0
  29. data/lib/hecks/behaviors/expectations/boot.rb +12 -5
  30. data/lib/hecks/bluebook/acknowledgements.rb +1 -1
  31. data/lib/hecks/bluebook/command.rb +3 -2
  32. data/lib/hecks/bluebook/declaration.rb +2 -1
  33. data/lib/hecks/bluebook/dsl/adapter_builder.rb +9 -1
  34. data/lib/hecks/bluebook/dsl/bluebook_builder/metadata.rb +6 -4
  35. data/lib/hecks/bluebook/dsl/bluebook_builder/modules.rb +6 -3
  36. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/correlation_keys.rb +2 -1
  37. data/lib/hecks/bluebook/dsl/command_builder/folded_sets.rb +4 -2
  38. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +2 -1
  39. data/lib/hecks/bluebook/hecksagon.rb +6 -3
  40. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +9 -2
  41. data/lib/hecks/bluebook/meta_validator.rb +1 -1
  42. data/lib/hecks/bluebook/model_check/aggregate_checks.rb +2 -1
  43. data/lib/hecks/bluebook/model_check/classification_checks.rb +51 -0
  44. data/lib/hecks/bluebook/model_check/context_checks.rb +2 -0
  45. data/lib/hecks/bluebook/model_check/redundant_relationships.rb +2 -1
  46. data/lib/hecks/ci_speed/adapters/shard_partitioner.adapter +7 -0
  47. data/lib/hecks/ci_speed/adapters/shard_partitioner.rb +66 -0
  48. data/lib/hecks/ci_speed/adapters/timings_source.adapter +7 -0
  49. data/lib/hecks/ci_speed/adapters/timings_source.rb +68 -0
  50. data/lib/hecks/ci_speed/ci_speed.bluebook +111 -0
  51. data/lib/hecks/ci_speed/ci_speed.ports.hecksagon +22 -0
  52. data/lib/hecks/ci_workflows/ci_workflows.bluebook +50 -6
  53. data/lib/hecks/coder/coder.bluebook +3 -1
  54. data/lib/hecks/command_names/index.rb +1 -1
  55. data/lib/hecks/command_names/resolution.rb +15 -5
  56. data/lib/hecks/composer/toolbox.rb +2 -1
  57. data/lib/hecks/corpus.rb +4 -0
  58. data/lib/hecks/doc/reference/readme.rb +1 -1
  59. data/lib/hecks/framework_bluebooks.rb +3 -2
  60. data/lib/hecks/fuzzing/differential.rb +1 -1
  61. data/lib/hecks/fuzzing/era_boundary.rb +1 -1
  62. data/lib/hecks/fuzzing/isolated_boot/postgres_scratch.rb +1 -1
  63. data/lib/hecks/fuzzing/persistence_parity.rb +1 -1
  64. data/lib/hecks/fuzzing/target_capabilities.rb +1 -1
  65. data/lib/hecks/hecks/adapters/ci_runs.adapter +7 -0
  66. data/lib/hecks/hecks/adapters/ci_runs.rb +80 -0
  67. data/lib/hecks/hecks/adapters/claude_agent_list.rb +43 -0
  68. data/lib/hecks/hecks/adapters/claude_agents.rb +50 -19
  69. data/lib/hecks/hecks/adapters/claude_jobs.rb +36 -0
  70. data/lib/hecks/hecks/adapters/codebase/corpus_queries.rb +2 -1
  71. data/lib/hecks/hecks/adapters/codebase/minitest_runs.rb +4 -2
  72. data/lib/hecks/hecks/adapters/codebase/run_options.rb +2 -1
  73. data/lib/hecks/hecks/adapters/codebase/test_suite.rb +3 -19
  74. data/lib/hecks/hecks/adapters/dispatching/brief_text.rb +5 -3
  75. data/lib/hecks/hecks/adapters/dispatching/launcher.rb +2 -1
  76. data/lib/hecks/hecks/adapters/dispatching/plan.rb +8 -4
  77. data/lib/hecks/hecks/adapters/dispatching/settings.rb +2 -1
  78. data/lib/hecks/hecks/adapters/dispatching/settler.rb +4 -2
  79. data/lib/hecks/hecks/adapters/dispatching.rb +6 -3
  80. data/lib/hecks/hecks/adapters/doctor_reading.rb +4 -2
  81. data/lib/hecks/hecks/adapters/git_landing/carried.rb +42 -0
  82. data/lib/hecks/hecks/adapters/git_landing/finisher.rb +2 -1
  83. data/lib/hecks/hecks/adapters/git_landing/flagged.rb +32 -0
  84. data/lib/hecks/hecks/adapters/git_landing/tidy.rb +27 -14
  85. data/lib/hecks/hecks/adapters/git_landing.rb +30 -13
  86. data/lib/hecks/hecks/adapters/git_leftovers.adapter +7 -0
  87. data/lib/hecks/hecks/adapters/git_leftovers.rb +49 -0
  88. data/lib/hecks/hecks/adapters/git_main_pull.rb +2 -2
  89. data/lib/hecks/hecks/adapters/git_train.rb +9 -5
  90. data/lib/hecks/hecks/adapters/git_worktree_add.rb +8 -4
  91. data/lib/hecks/hecks/adapters/github_pull_requests.rb +2 -1
  92. data/lib/hecks/hecks/adapters/in_process_operations.rb +2 -1
  93. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +1 -1
  94. data/lib/hecks/hecks/adapters/journal_store/readings/composition.rb +2 -1
  95. data/lib/hecks/hecks/adapters/journal_store/translation_write/shape_edge.rb +4 -2
  96. data/lib/hecks/hecks/adapters/journal_store/translation_write.rb +4 -2
  97. data/lib/hecks/hecks/adapters/landed_branches.rb +38 -0
  98. data/lib/hecks/hecks/adapters/main_boarding.adapter +7 -0
  99. data/lib/hecks/hecks/adapters/main_boarding.rb +85 -0
  100. data/lib/hecks/hecks/adapters/main_integration/checks.rb +63 -0
  101. data/lib/hecks/hecks/adapters/main_integration/command_runner.rb +32 -0
  102. data/lib/hecks/hecks/adapters/main_integration/range_guard.rb +49 -0
  103. data/lib/hecks/hecks/adapters/main_integration/repository.rb +83 -0
  104. data/lib/hecks/hecks/adapters/main_integration/runs.rb +51 -0
  105. data/lib/hecks/hecks/adapters/main_integration/train.rb +74 -0
  106. data/lib/hecks/hecks/adapters/main_integration.adapter +7 -0
  107. data/lib/hecks/hecks/adapters/main_integration.rb +77 -0
  108. data/lib/hecks/hecks/adapters/main_verification.adapter +7 -0
  109. data/lib/hecks/hecks/adapters/main_verification.rb +89 -0
  110. data/lib/hecks/hecks/adapters/push_recorder.adapter +7 -0
  111. data/lib/hecks/hecks/adapters/push_recorder.rb +78 -0
  112. data/lib/hecks/hecks/adapters/red_flag_guard.rb +62 -0
  113. data/lib/hecks/hecks/adapters/red_flag_marker.rb +101 -0
  114. data/lib/hecks/hecks/adapters/red_flag_report.rb +59 -0
  115. data/lib/hecks/hecks/adapters/red_flag_survey.rb +65 -0
  116. data/lib/hecks/hecks/adapters/red_flagging.adapter +7 -0
  117. data/lib/hecks/hecks/adapters/red_flagging.rb +98 -0
  118. data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +6 -1
  119. data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +6 -3
  120. data/lib/hecks/hecks/adapters/settings_reading/event_tap_row.rb +33 -0
  121. data/lib/hecks/hecks/adapters/settings_reading.rb +3 -1
  122. data/lib/hecks/hecks/codebase.behaviors +0 -6
  123. data/lib/hecks/hecks/custodian.behaviors +22 -1
  124. data/lib/hecks/hecks/delegate/delegate.bluebook +128 -15
  125. data/lib/hecks/hecks/deliver/deliver.bluebook +450 -2
  126. data/lib/hecks/hecks/environments/memory.world +5 -0
  127. data/lib/hecks/hecks/hecks.contextmap +8 -0
  128. data/lib/hecks/hecks/hecks.hecksagon +106 -6
  129. data/lib/hecks/hecks/hecks.world +9 -1
  130. data/lib/hecks/hecks/migrate/migrate.bluebook +6 -1
  131. data/lib/hecks/hecks/redflag/redflag.bluebook +249 -0
  132. data/lib/hecks/hecks/test/test.bluebook +0 -19
  133. data/lib/hecks/language/adapter.bluebook +13 -0
  134. data/lib/hecks/language/bluebook/vocabulary.bluebook +8 -9
  135. data/lib/hecks/language/sentence/sentence.bluebook +2 -0
  136. data/lib/hecks/pipeline/pipeline.bluebook +251 -0
  137. data/lib/hecks/pipeline/pipeline.hecksagon +17 -0
  138. data/lib/hecks/pipeline_board/adapters/cache.rb +43 -0
  139. data/lib/hecks/pipeline_board/adapters/pipeline_fill.rb +56 -0
  140. data/lib/hecks/pipeline_board/adapters/pipeline_git.rb +82 -0
  141. data/lib/hecks/pipeline_board/adapters/pipeline_github/runs.rb +66 -0
  142. data/lib/hecks/pipeline_board/adapters/pipeline_github.adapter +7 -0
  143. data/lib/hecks/pipeline_board/adapters/pipeline_github.rb +70 -0
  144. data/lib/hecks/pipeline_board/adapters/pipeline_jobs.adapter +7 -0
  145. data/lib/hecks/pipeline_board/adapters/pipeline_jobs.rb +87 -0
  146. data/lib/hecks/pipeline_board/adapters/pipeline_journal/chain.rb +40 -0
  147. data/lib/hecks/pipeline_board/adapters/pipeline_journal/tap.rb +75 -0
  148. data/lib/hecks/pipeline_board/adapters/pipeline_journal.adapter +7 -0
  149. data/lib/hecks/pipeline_board/adapters/pipeline_journal.rb +83 -0
  150. data/lib/hecks/pipeline_board/adapters/pipeline_stages/ci_tiles.rb +85 -0
  151. data/lib/hecks/pipeline_board/adapters/pipeline_stages/fanout.rb +73 -0
  152. data/lib/hecks/pipeline_board/adapters/pipeline_stages/gather.rb +57 -0
  153. data/lib/hecks/pipeline_board/adapters/pipeline_stages/metrics.rb +36 -0
  154. data/lib/hecks/pipeline_board/adapters/pipeline_stages/strip.rb +102 -0
  155. data/lib/hecks/pipeline_board/adapters/pipeline_stages/tile_kit.rb +57 -0
  156. data/lib/hecks/pipeline_board/adapters/pipeline_stages/work_tiles.rb +59 -0
  157. data/lib/hecks/pipeline_board/adapters/pipeline_stages.adapter +7 -0
  158. data/lib/hecks/pipeline_board/adapters/pipeline_stages.rb +84 -0
  159. data/lib/hecks/pipeline_board/adapters/pipeline_tickets.adapter +7 -0
  160. data/lib/hecks/pipeline_board/adapters/pipeline_tickets.rb +77 -0
  161. data/lib/hecks/pipeline_board/adapters/pipeline_web/page.html +292 -0
  162. data/lib/hecks/pipeline_board/adapters/pipeline_web/sequence.html +190 -0
  163. data/lib/hecks/pipeline_board/adapters/pipeline_web/server.rb +105 -0
  164. data/lib/hecks/pipeline_board/adapters/pipeline_web/snapshot.rb +57 -0
  165. data/lib/hecks/pipeline_board/adapters/pipeline_web/stream.rb +59 -0
  166. data/lib/hecks/pipeline_board/adapters/pipeline_web/wiring.html +536 -0
  167. data/lib/hecks/pipeline_board/adapters/pipeline_web.adapter +7 -0
  168. data/lib/hecks/pipeline_board/adapters/pipeline_web.rb +80 -0
  169. data/lib/hecks/pipeline_board/adapters/pipeline_wiring/details.rb +85 -0
  170. data/lib/hecks/pipeline_board/adapters/pipeline_wiring/graph.rb +120 -0
  171. data/lib/hecks/pipeline_board/adapters/pipeline_wiring.adapter +7 -0
  172. data/lib/hecks/pipeline_board/adapters/pipeline_wiring.rb +36 -0
  173. data/lib/hecks/pipeline_board/adapters/probe.rb +48 -0
  174. data/lib/hecks/pipeline_board/pipeline_board.bluebook +144 -0
  175. data/lib/hecks/pipeline_board/pipeline_board.hecksagon +12 -0
  176. data/lib/hecks/pipeline_board/pipeline_board.ports.hecksagon +47 -0
  177. data/lib/hecks/ports/persistence/binding_policy.rb +2 -1
  178. data/lib/hecks/ports/persistence/plugins/era/translation/compose.rb +4 -3
  179. data/lib/hecks/ports/persistence/repository_factory.rb +2 -1
  180. data/lib/hecks/projections/ci_pipeline/table.rb +2 -1
  181. data/lib/hecks/projections/deploy/lambda/stack/recipes.rb +2 -2
  182. data/lib/hecks/projections/undo.rb +2 -1
  183. data/lib/hecks/projector/cli_projector/command_help.rb +5 -4
  184. data/lib/hecks/projector/cli_projector/renames.rb +4 -2
  185. data/lib/hecks/projector/cli_projector/usage.rb +4 -3
  186. data/lib/hecks/projector/exporter/adapters.rb +3 -2
  187. data/lib/hecks/projector/narrate_projector/use_cases.rb +74 -0
  188. data/lib/hecks/projector/narrate_projector.rb +10 -3
  189. data/lib/hecks/quality_control/adapters/main_maintenance.rb +9 -5
  190. data/lib/hecks/quality_control/adapters/qa_auto_mint.rb +21 -2
  191. data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +1 -1
  192. data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +2 -1
  193. data/lib/hecks/quality_control/cli/qa_fix_main_bug/publishing.rb +8 -4
  194. data/lib/hecks/quality_control/cli/qa_fix_main_bug.rb +10 -8
  195. data/lib/hecks/quality_control/cli/qa_generated_domains/promotion.rb +2 -2
  196. data/lib/hecks/quality_control/cli/qa_main_gate/gate_run.rb +6 -3
  197. data/lib/hecks/quality_control/cli/qa_main_gate/logging.rb +8 -4
  198. data/lib/hecks/quality_control/cli/qa_main_gate/shell.rb +4 -2
  199. data/lib/hecks/quality_control/cli/qa_main_gate/sweeping.rb +8 -4
  200. data/lib/hecks/quality_control/cli/qa_main_gate/worktree.rb +3 -2
  201. data/lib/hecks/quality_control/cli/qa_main_gate.rb +10 -5
  202. data/lib/hecks/quality_control/cli/qa_sweep/all_mode/children.rb +1 -1
  203. data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +1 -1
  204. data/lib/hecks/quality_control/cli/qa_sweep.rb +1 -1
  205. data/lib/hecks/quality_control/cli/qa_tick.rb +6 -3
  206. data/lib/hecks/quality_control/quality_control.bluebook +11 -11
  207. data/lib/hecks/quality_control/quality_control.ports.hecksagon +6 -3
  208. data/lib/hecks/query_ir/touchpoints.rb +2 -1
  209. data/lib/hecks/refused.rb +2 -1
  210. data/lib/hecks/release/approval.rb +4 -2
  211. data/lib/hecks/runtime/event_log.rb +27 -0
  212. data/lib/hecks/runtime/event_tap.rb +106 -0
  213. data/lib/hecks/runtime/loader/boot_steps.rb +1 -1
  214. data/lib/hecks/runtime/loader.rb +35 -19
  215. data/lib/hecks/runtime/registry/durability_warnings.rb +12 -5
  216. data/lib/hecks/runtime/registry/runtime_state.rb +4 -1
  217. data/lib/hecks/runtime/registry/saga_anchor.rb +54 -0
  218. data/lib/hecks/runtime/registry/saga_durability_rule.rb +66 -0
  219. data/lib/hecks/runtime/registry/saga_persistence.rb +58 -12
  220. data/lib/hecks/runtime/registry/verification.rb +7 -3
  221. data/lib/hecks/runtime/saga_interpreter/lifecycle.rb +2 -1
  222. data/lib/hecks/runtime/saga_interpreter.rb +1 -1
  223. data/lib/hecks/rust_format.rb +2 -1
  224. data/lib/hecks/shape_ledger/edge_hygiene.rb +10 -5
  225. data/lib/hecks/shape_ledger.rb +1 -1
  226. data/lib/hecks/storehouse/audit.rb +2 -1
  227. data/lib/hecks/storehouse/identity.rb +6 -3
  228. data/lib/hecks/storehouse.rb +2 -1
  229. data/lib/hecks/tickets/bluebook/tickets.bluebook +5 -4
  230. data/lib/hecks/tools/ci_workflows.rb +2 -1
  231. data/lib/hecks/tools/document.rb +12 -1
  232. data/lib/hecks/tools/downstream_model_check.rb +4 -2
  233. data/lib/hecks/tools/fuzz_sweep/shards.rb +9 -30
  234. data/lib/hecks/tools/model_check/examination.rb +25 -2
  235. data/lib/hecks/tools/move_disables.rb +4 -2
  236. data/lib/hecks/tools/regeneration_run/scratch.rb +2 -1
  237. data/lib/hecks/tools/rspec_shard_files.rb +12 -15
  238. data/lib/hecks/tools/sequence_script.rb +1 -1
  239. data/lib/hecks/tools/shard_planner.rb +65 -0
  240. data/lib/hecks/tools/stage_progress.rb +2 -1
  241. data/lib/hecks/tools/stress_concurrency_specs.rb +2 -1
  242. data/lib/hecks/version.rb +1 -1
  243. data/lib/hecks/vocabulary.rb +8 -9
  244. data/lib/hecks.rb +5 -2
  245. data/prebuilt/{13c04bdc5970295b310f0a980d397ba722232c8da99cc1a0cdb383249921e871.marshal → 4b81646f769ae5b1e7457f9b11c48d8bc1093e96a1dd6fb61864065121ca6f01.marshal} +0 -0
  246. data/prebuilt/{e3857b77f47d9ecc1787b2e1f5136364f3cb3444ef4aea5479f3b98167affea2.marshal → 681890632e3f4a99646623dcae44af36b1bad66c515f5abf67a2460372b9c6fd.marshal} +0 -0
  247. data/rust/host/HECKS_RELEASE +1 -1
  248. data/rust/parser/src/emit.rs +5 -1
  249. data/rust/parser/src/ir.rs +2 -0
  250. data/rust/parser/src/keywords.rs +12 -0
  251. data/rust/parser/src/main.rs +1 -0
  252. data/rust/parser/src/parse/adapter.rs +1 -0
  253. data/rust/parser/src/phrases.rs +16 -0
  254. data/rust/parser/src/sentence/examples.rs +93 -0
  255. data/rust/parser/src/sentence/mod.rs +1 -0
  256. metadata +89 -5
  257. data/lib/hecks/tools/refresh_rspec_runtime_baseline.rb +0 -166
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5513321d2ace0e5e35b6b806fd04f8421e41d713a49667511c278309892a3ec8
4
- data.tar.gz: b440aca95a39f41a04375a879b917fd153e6277bba6386a1f637e87c2288f225
3
+ metadata.gz: 9d11764e3755dd6389e6266151066f1436a4d1d645b4d4224aa3873b6f98a62f
4
+ data.tar.gz: 87208f597ea96b9cff0d938c8690389b78b91c4d0e00d126febfe75615d54ed1
5
5
  SHA512:
6
- metadata.gz: e318b100521c095c1ee8c0962e5108ffe5595281bc9261de0cf8460306c4144b9c5465ef48c6a455c923175b1bc027bcee34d90ea127f5c201d882b427c95169
7
- data.tar.gz: 1fede9423b4f0dfd0b95a15d7be5ee3b651d0dfdab3b7430f7f4a3f4292e343c8c9c03babbc8c9d52412a76d38914405190fcf37bdd0ab6090f3d27b005daf1c
6
+ metadata.gz: f47097c7ee7c848c84c4a4cbaadf5163a1018cc3af9f0f5ffefc6cf03d600554e7e61c04584e5a381b55ad67a22f1585cd46da7edc85ceb2b8d9f8266e9a14b6
7
+ data.tar.gz: 0ccc3310e227fb052f12b40777fe149e58c097c9c756f856e48db1f08dcc6552dc52014f0d98b26d66f24907f3c16e3f7ea12e19f2259d6ab27271a0fb8b58d1
@@ -82,7 +82,8 @@ module Hecks
82
82
  layered_chain_sql(aggregate, era, edges) || walked_sql(aggregate, era, edges, direct)
83
83
  end
84
84
 
85
- # The whole chain from the journal: one composed step when `direct` and the chain composes,
85
+ # The whole chain from the journal: one composed step when `direct` and the chain
86
+ # composes,
86
87
  # otherwise one link per era.
87
88
  def walked_sql(aggregate, era, edges, direct)
88
89
  (direct && direct_chain_sql(aggregate, era, edges)) || chain_sql(aggregate, era, edges)
@@ -20,7 +20,8 @@ module Hecks
20
20
  # REVOKE are owner-only, so a non-owner app role must skip them.
21
21
  #
22
22
  # @return [void]
23
- # @raise [Runtime::WiringError] if the domain's `formerly_known_as` rename is still pending
23
+ # @raise [Runtime::WiringError] if the domain's `formerly_known_as` rename is still
24
+ # pending
24
25
  # @raise [PG::Error] if Postgres refuses a provisioning statement
25
26
  def ensure_base!
26
27
  refuse_pending_rename!
@@ -120,7 +121,8 @@ module Hecks
120
121
  # Canonical-form version that minted the name (Runtime::StorageShape::FORM_VERSION);
121
122
  # NULL reads as 1.
122
123
  @db.exec("ALTER TABLE hecks_eras ADD COLUMN IF NOT EXISTS canon_form int")
123
- # The edge an era was minted under when no edge file wrote it, as `Translation::ImplicitEdge::RECORD`;
124
+ # The edge an era was minted under when no edge file wrote it, as
125
+ # `Translation::ImplicitEdge::RECORD`;
124
126
  # NULL for every era a written edge reached.
125
127
  @db.exec("ALTER TABLE hecks_eras ADD COLUMN IF NOT EXISTS edge jsonb")
126
128
  @db.exec(ERA_TEXTS_SQL)
@@ -2,11 +2,14 @@ module Hecks
2
2
  module Adapters
3
3
  class PostgresEra
4
4
  class Lineage
5
- # ADR 0166: a `split` writes rows into another aggregate from one aggregate's rows. The target's
6
- # head is not stored: its tail is the source's held-era state, fanned out one row per target key,
5
+ # ADR 0166: a `split` writes rows into another aggregate from one aggregate's rows. The
6
+ # target's
7
+ # head is not stored: its tail is the source's held-era state, fanned out one row per target
8
+ # key,
7
9
  # and read through the same chain every head reads.
8
10
  module SplitSql
9
- # The source's rows as they are in the era the split edge starts from, latest per id, with the
11
+ # The source's rows as they are in the era the split edge starts from, latest per id, with
12
+ # the
10
13
  # era kept so later edges' guards still hold.
11
14
  SPLIT_SOURCE_SQL = <<~SQL.freeze
12
15
  WITH tail AS MATERIALIZED (%<tail>s),
@@ -14,7 +17,8 @@ module Hecks
14
17
  SELECT ordinal, era, aggregate_id, operation, state FROM edge_%<last>s
15
18
  SQL
16
19
 
17
- # The split edge that creates `names[:current][n]`, with the source aggregate and the split, or nil.
20
+ # The split edge that creates `names[:current][n]`, with the source aggregate and the
21
+ # split, or nil.
18
22
  def split_into(names, edges)
19
23
  edges.each_with_index do |edge, index|
20
24
  target = names[:current][index + 1]
@@ -26,7 +30,8 @@ module Hecks
26
30
  nil
27
31
  end
28
32
 
29
- # The target's tail from its source's held-era rows: the source is chained through the edges
33
+ # The target's tail from its source's held-era rows: the source is chained through the
34
+ # edges
30
35
  # before the split edge, so the split reads the shape it declares its fields in.
31
36
  def split_tail_sql(names, edges)
32
37
  found = split_into(names, edges)
@@ -36,7 +41,8 @@ module Hecks
36
41
  split_fanout_sql(source_sql, found[:split], names[:storage][found[:index] + 1])
37
42
  end
38
43
 
39
- # A split target's records as its split fans them out of the source, latest per id, or nil when
44
+ # A split target's records as its split fans them out of the source, latest per id, or nil
45
+ # when
40
46
  # the aggregate is not a split target: the "before" side of the audit of a split edge.
41
47
  def split_latest(aggregate, edges)
42
48
  tail = split_tail_sql(names_by_era(aggregate, edges), edges)
@@ -57,8 +63,10 @@ module Hecks
57
63
  format(SPLIT_SOURCE_SQL, tail: tail, chain: chain.join(",\n"), last: edges.size)
58
64
  end
59
65
 
60
- # One row per source row that carries the key: the key becomes the target's id, and the named
61
- # fields are copied under their own names. Deletes are kept, so a deleted source deletes its
66
+ # One row per source row that carries the key: the key becomes the target's id, and the
67
+ # named
68
+ # fields are copied under their own names. Deletes are kept, so a deleted source deletes
69
+ # its
62
70
  # target row too.
63
71
  def split_fanout_sql(source_sql, split, target_storage)
64
72
  key = text_literal(split.keyed_by.to_s)
@@ -3,6 +3,10 @@ module Hecks
3
3
  class PostgresEra
4
4
  class Lineage
5
5
  # The six shared `hecks_tr_*` jsonb functions that compiled translation SQL calls.
6
+ #
7
+ # A function that calls another `hecks_tr_*` function keeps the search path it was
8
+ # installed under (`SET search_path FROM CURRENT`), so it finds its sibling when the
9
+ # caller's path is empty, as in a `pg_restore` refreshing the views built on them.
6
10
  module TransformSql
7
11
  # Splits a path out of a state, answering what remains, the value and whether it was
8
12
  # there.
@@ -69,7 +73,7 @@ module Hecks
69
73
  # Moves the value at one path to another.
70
74
  TR_MOVE_SQL = <<~SQL.freeze
71
75
  CREATE OR REPLACE FUNCTION hecks_tr_move(state jsonb, from_path text[], to_path text[], rule_label text) RETURNS jsonb
72
- LANGUAGE plpgsql IMMUTABLE AS $fn$
76
+ LANGUAGE plpgsql IMMUTABLE SET search_path FROM CURRENT AS $fn$
73
77
  DECLARE extracted record;
74
78
  BEGIN
75
79
  SELECT * INTO extracted FROM hecks_tr_extract(state, from_path);
@@ -81,7 +85,7 @@ module Hecks
81
85
  # Moves a value to another path, mapping it through a lookup table.
82
86
  TR_CONVERT_SQL = <<~SQL.freeze
83
87
  CREATE OR REPLACE FUNCTION hecks_tr_convert(state jsonb, from_path text[], to_path text[], pairs jsonb, from_label text, rule_label text) RETURNS jsonb
84
- LANGUAGE plpgsql IMMUTABLE AS $fn$
88
+ LANGUAGE plpgsql IMMUTABLE SET search_path FROM CURRENT AS $fn$
85
89
  DECLARE extracted record; pair jsonb;
86
90
  BEGIN
87
91
  SELECT * INTO extracted FROM hecks_tr_extract(state, from_path);
@@ -99,7 +103,7 @@ module Hecks
99
103
  # Removes the value at a path.
100
104
  TR_DROP_SQL = <<~SQL.freeze
101
105
  CREATE OR REPLACE FUNCTION hecks_tr_drop(state jsonb, path text[]) RETURNS jsonb
102
- LANGUAGE plpgsql IMMUTABLE AS $fn$
106
+ LANGUAGE plpgsql IMMUTABLE SET search_path FROM CURRENT AS $fn$
103
107
  DECLARE extracted record;
104
108
  BEGIN
105
109
  SELECT * INTO extracted FROM hecks_tr_extract(state, path);
@@ -46,7 +46,8 @@ module Hecks
46
46
 
47
47
  private
48
48
 
49
- # Opens the lineage: for reading on a boot, and provisioned first on a mint request. Either
49
+ # Opens the lineage: for reading on a boot, and provisioned first on a mint request.
50
+ # Either
50
51
  # refuses, by name, while the domain's history still sits under its former name.
51
52
  def open_lineage(db, bluebook, settings, request)
52
53
  lineage = Lineage.new(db, bluebook.name, formerly_known_as: bluebook.formerly_known_as,
@@ -3,7 +3,8 @@ module Hecks
3
3
  class PostgresEra
4
4
  module LineageManager
5
5
  # The request a mint carries into the era check: whether the mint was confirmed, the verdict
6
- # the rehearsal of that same era reached, and the ledger watermark the rehearsal read. Only the
6
+ # the rehearsal of that same era reached, and the ledger watermark the rehearsal read. Only
7
+ # the
7
8
  # Maintenance mint path builds one; a boot has none, so a boot that would mint refuses.
8
9
  MintRequest = Data.define(:confirm, :verdict, :watermark) do
9
10
  # Reads the request out of a settings hash, spelled with symbol or string keys.
@@ -32,7 +32,8 @@ module Hecks
32
32
  "persisted_by block of its world", minting: false)
33
33
  end
34
34
 
35
- # Refuses a mint that the rehearsal does not back: not confirmed, not a would_mint verdict, or a
35
+ # Refuses a mint that the rehearsal does not back: not confirmed, not a would_mint
36
+ # verdict, or a
36
37
  # ledger watermark that moved since the rehearsal read it.
37
38
  def refuse_unrehearsed_mint!(context)
38
39
  request = context.mint_request
@@ -10,6 +10,9 @@ module Hecks
10
10
  CliRunner::QUERY_WORDS.include?(argv.first) ? argv[1] : argv.first
11
11
  end
12
12
 
13
+ # Whether a query shares its name with a command, the one case `query` is typed.
14
+ def shared?(scope, name, asking) = asking && scope[:cli][:names][:command].key?(name)
15
+
13
16
  # The answer a line gets before any command runs: its help, or its refusal for a
14
17
  # command written without its bang.
15
18
  def early_answer(scope, cli, line)
@@ -5,6 +5,8 @@ module Hecks
5
5
  # The launcher word `completion <shell>` (ADR 0163, plan step 7): the script that completes
6
6
  # the launcher's words in that shell, written from the same listing the help prints.
7
7
  module CompletionWords
8
+ USAGE = "completion <bash|zsh|fish> print the script that completes the launcher in a shell".freeze
9
+
8
10
  # The answer to `completion <shell>`: the script on stdout, or the usage line when the
9
11
  # shell is missing or not one this projection writes.
10
12
  def completion_answer(scope, argv)
@@ -2,9 +2,12 @@ module Hecks
2
2
  module Adapters
3
3
  module Driving
4
4
  module CliRunner
5
- # The session's checkout, for reads only. A read of a checkout's state that names no checkout
6
- # takes the one the session set in `HECKS_CHECKOUT`; a command never does. A command names its
7
- # own target, because a write must land where it was asked to, not where the session last was.
5
+ # The session's checkout, for reads only. A read of a checkout's state that names no
6
+ # checkout
7
+ # takes the one the session set in `HECKS_CHECKOUT`; a command never does. A command names
8
+ # its
9
+ # own target, because a write must land where it was asked to, not where the session last
10
+ # was.
8
11
  module ReadContext
9
12
  # The environment variable a session sets to name its checkout.
10
13
  VARIABLE = "HECKS_CHECKOUT".freeze
@@ -6,7 +6,8 @@ module Hecks
6
6
  # is noted once on standard error, and its argument names translate before the command reads
7
7
  # them. Extended into `CliRunner`.
8
8
  module RenamedNames
9
- # Notes a renamed spelling once, and returns the line's argv with its arguments translated.
9
+ # Notes a renamed spelling once, and returns the line's argv with its arguments
10
+ # translated.
10
11
  #
11
12
  # @param cli [Hash] the projection, holding `:names` with its `:renamed` table
12
13
  # @param typed [String] the word typed, without its `!`
@@ -33,7 +33,7 @@ module Hecks
33
33
  # The answer a line gets without naming a command, or nil when it names one.
34
34
  def answer_for(scope, argv)
35
35
  json_answer(scope, argv) || usage_answer(scope, argv.first) || module_answer(scope, argv.first) ||
36
- search_answer(scope, argv) || completion_answer(scope, argv) || tour_answer(scope, argv) || resume(scope, argv)
36
+ word_answer(scope, argv)
37
37
  end
38
38
 
39
39
  # The answer to a line that is only a request for usage, or nil.
@@ -82,7 +82,7 @@ module Hecks
82
82
 
83
83
  # The usage of one command or question, which its `--help` asks for.
84
84
  def command_help(scope, name, asking)
85
- options = scope[:options].merge(command: name, ask: asking)
85
+ options = scope[:options].merge(command: name, ask: asking, query_word: shared?(scope, name, asking))
86
86
  Projector.call(:cli, bluebook: scope[:bluebook], options: options)[:usage]
87
87
  end
88
88
 
@@ -8,6 +8,7 @@ module Hecks
8
8
  # dispatched with the saved arguments through the ordinary line path.
9
9
  module ResumeWords
10
10
  SAGA = "GateAndBoard".freeze
11
+ USAGE = "resume <run> continue a GateAndBoard saga that faulted, from the stage it faulted in".freeze
11
12
 
12
13
  # The answer to `resume <run>`, or nil when the line is not a resume.
13
14
  def resume(scope, argv)
@@ -5,7 +5,8 @@ module Hecks
5
5
  module Driving
6
6
  module CliRunner
7
7
  # Lets a landing name the linked worktree it lands by its run id, rather than repeating its
8
- # checkout and branch. An explicit checkout or branch always wins over the one the worktree holds.
8
+ # checkout and branch. An explicit checkout or branch always wins over the one the worktree
9
+ # holds.
9
10
  module RunReference
10
11
  # The aggregate whose record a landing's `from` names.
11
12
  SOURCE = "LinkedTree".freeze
@@ -29,7 +30,8 @@ module Hecks
29
30
  # @param runtime [Runtime::Registry] the booted domain the command runs against
30
31
  # @param spec [Hash] the resolved command
31
32
  # @param args [Hash] the parsed arguments, keyed by name
32
- # @return [Hash] the arguments, with checkout and branch filled from the named worktree when the
33
+ # @return [Hash] the arguments, with checkout and branch filled from the named worktree
34
+ # when the
33
35
  # caller gave a `from` and left them out
34
36
  def fill(runtime, spec, args)
35
37
  from = args[:from]&.fetch(:value, nil)
@@ -44,7 +46,8 @@ module Hecks
44
46
  branch: args[:branch] || { value: value_of(record[:branch]) })
45
47
  end
46
48
 
47
- # The ids a result names: the run key, the record written, and the references the command used,
49
+ # The ids a result names: the run key, the record written, and the references the command
50
+ # used,
48
51
  # with the checkout and branch it resolved. Absent ones are left out.
49
52
  #
50
53
  # @param args [Hash] the arguments the command ran with, after any reference was filled
@@ -5,6 +5,8 @@ module Hecks
5
5
  # The launcher word `search`: the commands and queries a word appears in, read from the same
6
6
  # projection the help prints (ADR 0163, step 20). Extended into `CliRunner`.
7
7
  module SearchWords
8
+ USAGE = "search <word> [--all] list the commands and queries a word appears in".freeze
9
+
8
10
  # The answer to `search <word> [--all]`: the commands and queries a word appears in, or
9
11
  # the line saying none does.
10
12
  def search_answer(scope, argv)
@@ -12,6 +12,7 @@ module Hecks
12
12
  TOUR_NAME = "Tour".freeze
13
13
  TOUR_COMMAND = %w[Example.create! name=hello].freeze
14
14
  TOUR_DIRECTORY = "hecks-tour".freeze
15
+ USAGE = "tour [dir] write a sample domain in dir (default hecks-tour) and run one command".freeze
15
16
 
16
17
  # The answer to `tour [dir]`, or nil when the line is not a tour.
17
18
  def tour_answer(scope, argv)
@@ -9,7 +9,8 @@ module Hecks
9
9
  # A realm written before the aggregate: `Hecks::`.
10
10
  REALM = /\A(?:[A-Z]\w*::)+/
11
11
 
12
- # The spelling notices this process has already printed, keyed by the spelling typed, so each
12
+ # The spelling notices this process has already printed, keyed by the spelling typed, so
13
+ # each
13
14
  # prints once.
14
15
  NOTED = Set.new
15
16
 
@@ -65,6 +65,8 @@ module Hecks
65
65
 
66
66
  # @return [String] the context line, as `-v` prints it
67
67
  def checkout_line
68
+ require_relative "../context_line"
69
+ require_relative "../../../hecks/adapters/settings_reading"
68
70
  ContextLine.line(directory: Dir.pwd, stores: SettingsReading.new.stores(Dir.pwd),
69
71
  audience: ContextLine.audience(Dir.pwd))
70
72
  end
@@ -0,0 +1,40 @@
1
+ module Hecks
2
+ module Adapters
3
+ module Driving
4
+ module CliRunner
5
+ # Help for the launcher words that read their own arguments (`tour`, `search`, `completion`,
6
+ # `resume`). A line that asks for help after the word answers the word's one-line usage
7
+ # before the word's handler runs, so `hecks tour --help` never writes a directory named
8
+ # `--help`. Extended into `CliRunner`.
9
+ module WordHelp
10
+ # The usage line of each word, declared by the word's own module.
11
+ #
12
+ # @return [Hash{String => String}] the word and its usage
13
+ def word_usages
14
+ { "tour" => TourWords::USAGE, "search" => SearchWords::USAGE,
15
+ "completion" => CompletionWords::USAGE, "resume" => ResumeWords::USAGE }
16
+ end
17
+
18
+ # The answer to a line that opens with one of these words: its usage when it asks for
19
+ # help,
20
+ # else the word's own handler; nil when the line opens with another word.
21
+ def word_answer(scope, argv)
22
+ word_help(scope, argv) || search_answer(scope, argv) || completion_answer(scope, argv) ||
23
+ tour_answer(scope, argv) || resume(scope, argv)
24
+ end
25
+
26
+ # The answer to `<word> --help`, `<word> -h` or `<word> help`, or nil when the line asks
27
+ # for no help or its first word is not one of these.
28
+ #
29
+ # @return [Hash, nil] `{answer: [text, status]}`
30
+ def word_help(scope, argv)
31
+ usage = word_usages[argv.first]
32
+ return unless usage && argv.drop(1).intersect?(Resolution::HELP_WORDS)
33
+
34
+ { answer: ["usage: #{scope[:program]} #{usage}", ExitStatus::ANSWERED] }
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -16,6 +16,7 @@ require_relative "cli_runner/search_words"
16
16
  require_relative "cli_runner/completion_words"
17
17
  require_relative "cli_runner/tour_words"
18
18
  require_relative "cli_runner/resume_words"
19
+ require_relative "cli_runner/word_help"
19
20
  require_relative "cli_runner/json_words"
20
21
  require_relative "cli_runner/settling"
21
22
  require_relative "cli_runner/streaming"
@@ -45,6 +46,7 @@ module Hecks
45
46
  extend CompletionWords
46
47
  extend TourWords
47
48
  extend ResumeWords
49
+ extend WordHelp
48
50
  extend JsonWords
49
51
  extend Suggestions
50
52
  extend NameIndex
@@ -5,9 +5,11 @@ module Hecks
5
5
  module Adapters
6
6
  module Driving
7
7
  module Mcp
8
- # Where a stage's progress lines go when the client asked for them with a progress token: each
8
+ # Where a stage's progress lines go when the client asked for them with a progress token:
9
+ # each
9
10
  # line becomes one `notifications/progress` message on the server's output, ahead of the
10
- # response to the call. Stands in for the standard error that `Tools::StageProgress` writes to.
11
+ # response to the call. Stands in for the standard error that `Tools::StageProgress` writes
12
+ # to.
11
13
  class ProgressSink
12
14
  # @param token [Object] the client's `progressToken`, echoed back on every notification
13
15
  # @param out [#puts] the server's output, where each notification is written
@@ -156,7 +156,8 @@ module Hecks
156
156
  with_progress(token) { tool_result(answer_tool(params["name"], params["arguments"] || {})) }
157
157
  end
158
158
 
159
- # Runs the block with a progress seam for this call's stages, so their lines reach the client as
159
+ # Runs the block with a progress seam for this call's stages, so their lines reach the
160
+ # client as
160
161
  # notifications. The seam is per thread and removed when the call ends.
161
162
  # @param token [Object] the client's progress token
162
163
  # @return [Object] the block's value
@@ -13,7 +13,8 @@ module Hecks
13
13
  # Checks every argument in `args`, nested or not, and refuses the first one the policy
14
14
  # forbids.
15
15
  #
16
- # Read-only questions whose `path` names one file of the checkout. `path` is denied by name
16
+ # Read-only questions whose `path` names one file of the checkout. `path` is denied by
17
+ # name
17
18
  # for every other command, since it can name a place to write; these reads are allowed it,
18
19
  # and admit_path! still confines it to the checkout.
19
20
  READ_PATH_QUESTIONS = %w[codebase.read_source codebase.outline].freeze
@@ -3,15 +3,19 @@ module Hecks
3
3
  module Driving
4
4
  module Ruby
5
5
  module AggregateModule
6
- # The hooks an aggregate module lands on: a port declared inside a repeat boot, the bare and
7
- # qualified binding calls a `.hecksagon` and a `.world` make, and constant lookup. Each is a
8
- # module function, called as `Hooks.name` from the blocks that define the module's methods, since
6
+ # The hooks an aggregate module lands on: a port declared inside a repeat boot, the bare
7
+ # and
8
+ # qualified binding calls a `.hecksagon` and a `.world` make, and constant lookup. Each is
9
+ # a
10
+ # module function, called as `Hooks.name` from the blocks that define the module's
11
+ # methods, since
9
12
  # a block defined with `define_singleton_method` runs with the module as `self`.
10
13
  module Hooks
11
14
  # What `bound_outcome` answers for a call that is not a binding, so `super` handles it.
12
15
  UNBOUND = Object.new.freeze
13
16
 
14
- # What `bound_outcome` answers for a call that recorded a binding, so the module answers itself.
17
+ # What `bound_outcome` answers for a call that recorded a binding, so the module answers
18
+ # itself.
15
19
  BOUND = Object.new.freeze
16
20
 
17
21
  module_function
@@ -59,7 +63,8 @@ module Hecks
59
63
  end
60
64
  end
61
65
 
62
- # Defines `respond_to_missing?`, answering true while a `.hecksagon` or `.world` is being declared.
66
+ # Defines `respond_to_missing?`, answering true while a `.hecksagon` or `.world` is
67
+ # being declared.
63
68
  #
64
69
  # @param mod [Module] the aggregate module
65
70
  # @return [void]
@@ -70,8 +75,10 @@ module Hecks
70
75
  end
71
76
  end
72
77
 
73
- # Defines `const_missing`. It uses `aggregate.hecks_name`, not the qualified name: qualifying it
74
- # would make `Account::Debit`'s meaning depend on whether a stale module from an earlier boot is
78
+ # Defines `const_missing`. It uses `aggregate.hecks_name`, not the qualified name:
79
+ # qualifying it
80
+ # would make `Account::Debit`'s meaning depend on whether a stale module from an earlier
81
+ # boot is
75
82
  # still on this process.
76
83
  #
77
84
  # @param mod [Module] the aggregate module
@@ -86,8 +93,10 @@ module Hecks
86
93
  end
87
94
  end
88
95
 
89
- # Declares a port on an aggregate during a repeat boot, and registers it with the live registry.
90
- # Re-resolves the aggregate via `Hecks.current_registry` rather than the closed-over `aggregate`,
96
+ # Declares a port on an aggregate during a repeat boot, and registers it with the live
97
+ # registry.
98
+ # Re-resolves the aggregate via `Hecks.current_registry` rather than the closed-over
99
+ # `aggregate`,
91
100
  # which can be stale from an earlier boot.
92
101
  #
93
102
  # @raise [Bluebook::DSL::Malformed] when called outside a boot
@@ -96,8 +105,10 @@ module Hecks
96
105
  built = Bluebook::DSL::ConstShim.with(->(const) { const }) do
97
106
  Bluebook::DSL::DomainPortBuilder.build(name, owner: current.hecks_name, &block)
98
107
  end
99
- # A `verb`-shaped port is a plain `Port`, the same struct `Hecks.port` registers. It belongs to
100
- # no aggregate IR, so it takes the registry's `add_port` directly. Mirrors `DSL::BindingProxy#port`,
108
+ # A `verb`-shaped port is a plain `Port`, the same struct `Hecks.port` registers. It
109
+ # belongs to
110
+ # no aggregate IR, so it takes the registry's `add_port` directly. Mirrors
111
+ # `DSL::BindingProxy#port`,
101
112
  # which handles the identical shape on a domain's first in-process boot.
102
113
  return Hecks.current_registry.add_port(built) if built.is_a?(Bluebook::Port)
103
114
 
@@ -112,14 +123,16 @@ module Hecks
112
123
  raise Bluebook::DSL::Malformed, "#{fqn}.port(#{name.inspect}) called outside a boot"
113
124
  end
114
125
 
115
- # Points each reference attribute of a port's operations at the aggregate that declares it.
126
+ # Points each reference attribute of a port's operations at the aggregate that declares
127
+ # it.
116
128
  def reference_operations(built, current)
117
129
  built.operations.each do |operation|
118
130
  operation.attributes.select(&:reference?).each { |attribute| attribute.type.declared_in = current }
119
131
  end
120
132
  end
121
133
 
122
- # Answers what a method-missing call means: a bare call's attribute path, the world's record of
134
+ # Answers what a method-missing call means: a bare call's attribute path, the world's
135
+ # record of
123
136
  # a setting, a recorded binding (BOUND), or nothing to bind (UNBOUND).
124
137
  #
125
138
  # @return [Object] the answer, or BOUND or UNBOUND
@@ -137,7 +150,8 @@ module Hecks
137
150
  BOUND
138
151
  end
139
152
 
140
- # @return [Boolean] whether the call names no arguments and no block, so it is a bare attribute path
153
+ # @return [Boolean] whether the call names no arguments and no block, so it is a bare
154
+ # attribute path
141
155
  def bare_call?(args, kwargs, block)
142
156
  args.empty? && kwargs.empty? && !block
143
157
  end
@@ -21,7 +21,8 @@ module Hecks
21
21
  # find/all/count/events, project/docs/narrate, and the port/binding hooks.
22
22
  #
23
23
  # Each concern is a helper that defines its methods on the module and closes over the same
24
- # arguments. The hooks live in `AggregateModule::Hooks`, which the module's blocks call by name.
24
+ # arguments. The hooks live in `AggregateModule::Hooks`, which the module's blocks call by
25
+ # name.
25
26
  def aggregate_module(dispatcher, domain, aggregate)
26
27
  fqn = "#{domain}::#{aggregate.hecks_name}"
27
28
  mod = Module.new
@@ -47,7 +48,8 @@ module Hecks
47
48
  end
48
49
  end
49
50
 
50
- # The module's everyday surface: its commands, its identity, its projections, and its reads.
51
+ # The module's everyday surface: its commands, its identity, its projections, and its
52
+ # reads.
51
53
  def define_surface(mod, dispatcher, domain, aggregate, fqn)
52
54
  define_creating_commands(mod, dispatcher, domain, aggregate, fqn)
53
55
  define_reflection(mod, dispatcher, domain, aggregate, fqn)
@@ -13,6 +13,10 @@ module Hecks
13
13
  # means no overlay, whatever the variable holds.
14
14
  FROM_ENV = :from_env
15
15
 
16
+ # The variable that moves the Hecks world's event tap for a process no hecks command runs: a
17
+ # spec run sets it for itself and every child it starts.
18
+ EVENT_TAP_VARIABLE = "HECKS_EVENT_TAP".freeze
19
+
16
20
  module_function
17
21
 
18
22
  # The overlay a boot loads: the caller's own choice (nil meaning none), else the
@@ -28,6 +32,13 @@ module Hecks
28
32
  named.empty? ? nil : named
29
33
  end
30
34
 
35
+ # The event tap override a boot hands the runtime: `HECKS_EVENT_TAP` when it is set (a path
36
+ # moves the Hecks world's tap, an empty value switches it off), else nil, which leaves the
37
+ # world's tap where it is. A world that declares no tap ignores it.
38
+ #
39
+ # @return [String, nil] the override
40
+ def event_tap_override = ENV.fetch(EVENT_TAP_VARIABLE, nil)
41
+
31
42
  # Boots a domain directory. See `Runtime::Loader.boot`.
32
43
  #
33
44
  # @param path [String] path to a domain directory, or a file inside one
@@ -36,7 +47,8 @@ module Hecks
36
47
  # @param environment [String, nil, Symbol] the overlay, or `FROM_ENV` for `HECKS_ENVIRONMENT`
37
48
  # @return [Runtime::Dispatcher, Adapters::Lambda::RemoteDispatcher] the booted dispatcher
38
49
  def boot(path, shared: nil, install_driving: true, environment: FROM_ENV)
39
- drive(Runtime::Loader.boot(path, shared: shared, environment: selected_environment(environment)),
50
+ drive(Runtime::Loader.boot(path, shared: shared, environment: selected_environment(environment),
51
+ event_tap: event_tap_override),
40
52
  install_driving)
41
53
  end
42
54
 
@@ -57,7 +69,7 @@ module Hecks
57
69
  # @param install_driving [Boolean] install the `Widget::Item.Add`-style facade
58
70
  # @return [Runtime::Dispatcher, Adapters::Lambda::RemoteDispatcher] the booted dispatcher
59
71
  def boot_described(described, install_driving: true)
60
- drive(Runtime::Loader.boot_described(described), install_driving)
72
+ drive(Runtime::Loader.boot_described(described, event_tap: event_tap_override), install_driving)
61
73
  end
62
74
 
63
75
  # Boots exactly the named files. See `Runtime::Loader.boot_files`.
@@ -66,9 +78,11 @@ module Hecks
66
78
  # @param shared [String, nil] a shared-root override
67
79
  # @param install_driving [Boolean] install the `Widget::Item.Add`-style facade
68
80
  # @param environment [String, nil, Symbol] the overlay, or `FROM_ENV` for `HECKS_ENVIRONMENT`
81
+ # @param adapters [Array<String>, nil] exactly the `.adapter` files to load; see the loader
69
82
  # @return [Runtime::Dispatcher, Adapters::Lambda::RemoteDispatcher] the booted dispatcher
70
- def boot_files(paths, shared: nil, install_driving: true, environment: FROM_ENV)
71
- drive(Runtime::Loader.boot_files(paths, shared: shared, environment: selected_environment(environment)),
83
+ def boot_files(paths, shared: nil, install_driving: true, environment: FROM_ENV, adapters: nil)
84
+ drive(Runtime::Loader.boot_files(paths, shared: shared, environment: selected_environment(environment),
85
+ adapters: adapters, event_tap: event_tap_override),
72
86
  install_driving)
73
87
  end
74
88