hecks 6.0.0 → 7.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 (754) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +19 -12
  3. data/lib/hecks/adapters/driven/claude_code.rb +2 -2
  4. data/lib/hecks/adapters/driven/folder.rb +10 -1
  5. data/lib/hecks/adapters/driven/folder_overlay.rb +15 -0
  6. data/lib/hecks/adapters/driven/heki.rb +1 -1
  7. data/lib/hecks/adapters/driven/in_process_key_vault.rb +1 -1
  8. data/lib/hecks/adapters/driven/memory/outbox_rows.rb +2 -2
  9. data/lib/hecks/adapters/driven/postgres/name_guard.rb +25 -0
  10. data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -3
  11. data/lib/hecks/adapters/driven/postgres/repository.rb +1 -1
  12. data/lib/hecks/adapters/driven/postgres/shared_connection.rb +1 -1
  13. data/lib/hecks/adapters/driven/postgres.rb +3 -0
  14. data/lib/hecks/adapters/driven/postgres_era/boot.rb +28 -16
  15. data/lib/hecks/adapters/driven/postgres_era/class_methods.rb +27 -7
  16. data/lib/hecks/adapters/driven/postgres_era/dialect.rb +10 -5
  17. data/lib/hecks/adapters/driven/postgres_era/field_cache_provisioner.rb +39 -0
  18. data/lib/hecks/adapters/driven/postgres_era/journal.rb +52 -13
  19. data/lib/hecks/adapters/driven/postgres_era/lineage/chain_sql.rb +29 -49
  20. data/lib/hecks/adapters/driven/postgres_era/lineage/direct_sql.rb +73 -0
  21. data/lib/hecks/adapters/driven/postgres_era/lineage/direct_verified.json +10 -0
  22. data/lib/hecks/adapters/driven/postgres_era/lineage/direct_verified.rb +65 -0
  23. data/lib/hecks/adapters/driven/postgres_era/lineage/domain_rename.rb +77 -25
  24. data/lib/hecks/adapters/driven/postgres_era/lineage/domain_rename_state.rb +108 -0
  25. data/lib/hecks/adapters/driven/postgres_era/lineage/era_integrity.rb +11 -6
  26. data/lib/hecks/adapters/driven/postgres_era/lineage/era_store.rb +63 -5
  27. data/lib/hecks/adapters/driven/postgres_era/lineage/layered_sql.rb +64 -0
  28. data/lib/hecks/adapters/driven/postgres_era/lineage/ledger_reset.rb +150 -0
  29. data/lib/hecks/adapters/driven/postgres_era/lineage/mint_provisioning.rb +85 -0
  30. data/lib/hecks/adapters/driven/postgres_era/lineage/mint_transaction.rb +11 -7
  31. data/lib/hecks/adapters/driven/postgres_era/lineage/provisioning.rb +11 -5
  32. data/lib/hecks/adapters/driven/postgres_era/lineage/split_sql.rb +76 -0
  33. data/lib/hecks/adapters/driven/postgres_era/lineage/sql_templates.rb +9 -0
  34. data/lib/hecks/adapters/driven/postgres_era/lineage.rb +10 -2
  35. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/context.rb +23 -3
  36. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/coverage_check.rb +3 -1
  37. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/disposable_ledger.rb +119 -0
  38. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolution.rb +219 -0
  39. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolver.rb +68 -71
  40. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/held_era.rb +68 -0
  41. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/ledger_change.rb +63 -0
  42. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/merge_coordinator.rb +1 -1
  43. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/mint_decision.rb +163 -0
  44. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/mint_request.rb +24 -0
  45. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/minter.rb +59 -21
  46. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/refusals.rb +24 -11
  47. data/lib/hecks/adapters/driven/postgres_era/lineage_manager.rb +40 -6
  48. data/lib/hecks/adapters/driven/postgres_era/shared_tables.rb +32 -0
  49. data/lib/hecks/adapters/driven/postgres_era.adapter +12 -0
  50. data/lib/hecks/adapters/driven/postgres_era.rb +25 -10
  51. data/lib/hecks/adapters/driven/prism.rb +0 -1
  52. data/lib/hecks/adapters/driven/sql_query_builder.rb +1 -0
  53. data/lib/hecks/adapters/driven/sqlite/dispatch_claims.rb +1 -1
  54. data/lib/hecks/adapters/driven/sqlite/name_guard.rb +25 -0
  55. data/lib/hecks/adapters/driven/sqlite/outbox.rb +2 -2
  56. data/lib/hecks/adapters/driven/sqlite/repository.rb +1 -1
  57. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +20 -0
  58. data/lib/hecks/adapters/driven/sqlite.rb +9 -1
  59. data/lib/hecks/adapters/driven/tenant_provisioner.rb +1 -1
  60. data/lib/hecks/adapters/driven/worktree_overlay.rb +117 -0
  61. data/lib/hecks/adapters/driving/cli/shorthand.rb +5 -1
  62. data/lib/hecks/adapters/driving/cli.rb +1 -1
  63. data/lib/hecks/adapters/driving/cli_runner/answers.rb +77 -22
  64. data/lib/hecks/adapters/driving/cli_runner/bang_rule.rb +35 -0
  65. data/lib/hecks/adapters/driving/cli_runner/completion_words.rb +36 -0
  66. data/lib/hecks/adapters/driving/cli_runner/json_words.rb +55 -0
  67. data/lib/hecks/adapters/driving/cli_runner/name_index.rb +63 -0
  68. data/lib/hecks/adapters/driving/cli_runner/read_context.rb +32 -0
  69. data/lib/hecks/adapters/driving/cli_runner/renamed_names.rb +49 -0
  70. data/lib/hecks/adapters/driving/cli_runner/resolution.rb +43 -17
  71. data/lib/hecks/adapters/driving/cli_runner/resume_words.rb +63 -0
  72. data/lib/hecks/adapters/driving/cli_runner/run_reference.rb +66 -0
  73. data/lib/hecks/adapters/driving/cli_runner/run_replay.rb +118 -0
  74. data/lib/hecks/adapters/driving/cli_runner/search_words.rb +35 -0
  75. data/lib/hecks/adapters/driving/cli_runner/settling.rb +6 -5
  76. data/lib/hecks/adapters/driving/cli_runner/streaming.rb +11 -10
  77. data/lib/hecks/adapters/driving/cli_runner/suggestions.rb +1 -1
  78. data/lib/hecks/adapters/driving/cli_runner/tour_words.rb +77 -0
  79. data/lib/hecks/adapters/driving/cli_runner/verb_names.rb +36 -4
  80. data/lib/hecks/adapters/driving/cli_runner/verbosity.rb +75 -0
  81. data/lib/hecks/adapters/driving/cli_runner.rb +106 -7
  82. data/lib/hecks/adapters/driving/context_line.rb +85 -0
  83. data/lib/hecks/adapters/driving/exit_status.rb +31 -0
  84. data/lib/hecks/adapters/driving/launcher_options.rb +7 -5
  85. data/lib/hecks/adapters/driving/mcp/progress_sink.rb +45 -0
  86. data/lib/hecks/adapters/driving/mcp/tool_calls.rb +7 -5
  87. data/lib/hecks/adapters/driving/mcp.rb +25 -5
  88. data/lib/hecks/adapters/driving/mcp_scope/argument_policy.rb +40 -7
  89. data/lib/hecks/adapters/driving/mcp_scope.rb +8 -7
  90. data/lib/hecks/adapters/driving/ruby/aggregate_module/hooks.rb +154 -0
  91. data/lib/hecks/adapters/driving/ruby/aggregate_module.rb +64 -93
  92. data/lib/hecks/adapters/driving/usage_log.rb +146 -0
  93. data/lib/hecks/adapters/driving/write_guard.rb +55 -0
  94. data/lib/hecks/adapters/driving.rb +0 -1
  95. data/lib/hecks/behaviors/dsl.rb +5 -1
  96. data/lib/hecks/behaviors/expectations/boot.rb +0 -1
  97. data/lib/hecks/bluebook/acknowledgements.rb +1 -1
  98. data/lib/hecks/bluebook/aggregate.rb +21 -18
  99. data/lib/hecks/bluebook/assembly/contracts/sagas.rb +2 -0
  100. data/lib/hecks/bluebook/assembly/contracts/structure.rb +18 -13
  101. data/lib/hecks/bluebook/behaviour/aggregate.rb +27 -3
  102. data/lib/hecks/bluebook/command.rb +16 -5
  103. data/lib/hecks/bluebook/declaration.rb +32 -4
  104. data/lib/hecks/bluebook/domain_port.rb +7 -3
  105. data/lib/hecks/bluebook/dsl/aggregate_builder/relationships.rb +0 -2
  106. data/lib/hecks/bluebook/dsl/aggregate_builder/renaming.rb +25 -0
  107. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +3 -0
  108. data/lib/hecks/bluebook/dsl/attribute_collector.rb +0 -1
  109. data/lib/hecks/bluebook/dsl/audience_word.rb +40 -0
  110. data/lib/hecks/bluebook/dsl/bluebook_builder/metadata.rb +56 -0
  111. data/lib/hecks/bluebook/dsl/bluebook_builder/modules.rb +80 -0
  112. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/correlation_keys.rb +51 -0
  113. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +1 -0
  114. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +17 -34
  115. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +8 -0
  116. data/lib/hecks/bluebook/dsl/command_builder.rb +13 -3
  117. data/lib/hecks/bluebook/dsl/entity_builder.rb +0 -2
  118. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +6 -4
  119. data/lib/hecks/bluebook/dsl/kinds.rb +53 -0
  120. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +9 -2
  121. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +25 -15
  122. data/lib/hecks/bluebook/dsl/translation_builder.rb +16 -1
  123. data/lib/hecks/bluebook/dsl/word_gate.rb +1 -1
  124. data/lib/hecks/bluebook/dsl.rb +1 -0
  125. data/lib/hecks/bluebook/meta_validator/judge/identity.rb +9 -4
  126. data/lib/hecks/bluebook/meta_validator/plan/category.rb +10 -2
  127. data/lib/hecks/bluebook/meta_validator/plan/verbs.rb +9 -0
  128. data/lib/hecks/bluebook/meta_validator/plan.rb +2 -1
  129. data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +3 -1
  130. data/lib/hecks/bluebook/meta_validator/reconstruction/reading.rb +7 -0
  131. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +7 -2
  132. data/lib/hecks/bluebook/meta_validator/shapes.rb +3 -0
  133. data/lib/hecks/bluebook/meta_validator/syntax_boot/disk_cache.rb +1 -1
  134. data/lib/hecks/bluebook/model_check/aggregate_checks.rb +27 -0
  135. data/lib/hecks/bluebook/model_check/ask_checks.rb +25 -0
  136. data/lib/hecks/bluebook/model_check/reaction_chains.rb +114 -0
  137. data/lib/hecks/bluebook/model_check/reaction_cycles.rb +53 -0
  138. data/lib/hecks/bluebook/model_check/reaction_depth_checks.rb +58 -0
  139. data/lib/hecks/bluebook/model_check/reaction_walk.rb +62 -0
  140. data/lib/hecks/bluebook/model_check.rb +5 -27
  141. data/lib/hecks/bluebook/process_manager.rb +20 -3
  142. data/lib/hecks/bluebook/translation.rb +5 -3
  143. data/lib/hecks/bluebook/translation_plan.rb +9 -2
  144. data/lib/hecks/ci_pipeline/adapters/ci_cache.adapter +7 -0
  145. data/lib/hecks/ci_pipeline/adapters/ci_cache.rb +39 -0
  146. data/lib/hecks/ci_pipeline/adapters/ci_runner.adapter +7 -0
  147. data/lib/hecks/ci_pipeline/adapters/ci_runner.rb +55 -0
  148. data/lib/hecks/ci_pipeline/ci_pipeline.behaviors +322 -0
  149. data/lib/hecks/ci_pipeline/ci_pipeline.bluebook +938 -0
  150. data/lib/hecks/ci_pipeline/ci_pipeline.hecksagon +12 -0
  151. data/lib/hecks/ci_pipeline/ci_pipeline.ports.hecksagon +16 -0
  152. data/lib/hecks/ci_speed/adapters/ci_reader.adapter +7 -0
  153. data/lib/hecks/ci_speed/adapters/ci_reader.rb +141 -0
  154. data/lib/hecks/ci_speed/adapters/local_runner/answer.rb +41 -0
  155. data/lib/hecks/ci_speed/adapters/local_runner/catalog.rb +89 -0
  156. data/lib/hecks/ci_speed/adapters/local_runner/checkouts.rb +89 -0
  157. data/lib/hecks/ci_speed/adapters/local_runner/launcher.rb +69 -0
  158. data/lib/hecks/ci_speed/adapters/local_runner/load_average.rb +38 -0
  159. data/lib/hecks/ci_speed/adapters/local_runner/refs.rb +39 -0
  160. data/lib/hecks/ci_speed/adapters/local_runner/refused.rb +11 -0
  161. data/lib/hecks/ci_speed/adapters/local_runner/verdict.rb +71 -0
  162. data/lib/hecks/ci_speed/adapters/local_runner.adapter +7 -0
  163. data/lib/hecks/ci_speed/adapters/local_runner.rb +168 -0
  164. data/lib/hecks/ci_speed/adapters/replayed_runner.rb +39 -0
  165. data/lib/hecks/ci_speed/ci_speed.behaviors +341 -0
  166. data/lib/hecks/ci_speed/ci_speed.bluebook +1073 -0
  167. data/lib/hecks/ci_speed/ci_speed.hecksagon +11 -0
  168. data/lib/hecks/ci_speed/ci_speed.ports.hecksagon +21 -0
  169. data/lib/hecks/ci_workflows/ci_workflows.behaviors +13 -0
  170. data/lib/hecks/ci_workflows/ci_workflows.bluebook +173 -0
  171. data/lib/hecks/ci_workflows/ci_workflows.hecksagon +15 -0
  172. data/lib/hecks/coder/coder.bluebook +385 -0
  173. data/lib/hecks/coder/coder.hecksagon +12 -0
  174. data/lib/hecks/command_names/check.rb +39 -0
  175. data/lib/hecks/command_names/extractor.rb +67 -0
  176. data/lib/hecks/command_names/index.rb +40 -0
  177. data/lib/hecks/command_names/resolution.rb +81 -0
  178. data/lib/hecks/command_names/scan.rb +54 -0
  179. data/lib/hecks/command_names/sources.rb +73 -0
  180. data/lib/hecks/command_names.rb +26 -0
  181. data/lib/hecks/composer/jobs.rb +1 -1
  182. data/lib/hecks/composer/toolbox.rb +8 -1
  183. data/lib/hecks/corpus/generated_key.rb +205 -0
  184. data/lib/hecks/corpus/listing.rb +34 -0
  185. data/lib/hecks/corpus/rust.rb +27 -11
  186. data/lib/hecks/corpus/sources.rb +2 -1
  187. data/lib/hecks/corpus.rb +37 -42
  188. data/lib/hecks/deprecation.rb +23 -0
  189. data/lib/hecks/doc/reference/readme.rb +1 -1
  190. data/lib/hecks/doc/reference/rendering.rb +2 -2
  191. data/lib/hecks/doc/reference.rb +1 -1
  192. data/lib/hecks/embryonaut_bluebook/manifest.rb +1 -1
  193. data/lib/hecks/fixer/fixer.bluebook +240 -0
  194. data/lib/hecks/fixer/fixer.hecksagon +17 -0
  195. data/lib/hecks/framework_bluebooks.rb +32 -7
  196. data/lib/hecks/fuzzing/concurrent_dispatch/world_copy.rb +1 -0
  197. data/lib/hecks/fuzzing/isolated_boot/postgres_scratch.rb +11 -12
  198. data/lib/hecks/fuzzing/isolated_boot/worlds.rb +23 -5
  199. data/lib/hecks/fuzzing/isolated_boot.rb +1 -1
  200. data/lib/hecks/fuzzing/mutation/checks.rb +3 -3
  201. data/lib/hecks/grammar/translation.bluebook +1 -1
  202. data/lib/hecks/grammar/translation_rules.json +64 -0
  203. data/lib/hecks/hecks/adapter_words.json +7 -0
  204. data/lib/hecks/hecks/adapters/area_overlap.rb +156 -0
  205. data/lib/hecks/hecks/adapters/claude_agents.rb +8 -3
  206. data/lib/hecks/hecks/adapters/codebase/batch_runs.rb +60 -0
  207. data/lib/hecks/hecks/adapters/codebase/changed_specs.rb +52 -0
  208. data/lib/hecks/hecks/adapters/codebase/codemods.rb +3 -2
  209. data/lib/hecks/hecks/adapters/codebase/conformance.rb +14 -1
  210. data/lib/hecks/hecks/adapters/codebase/corpus_queries.rb +53 -0
  211. data/lib/hecks/hecks/adapters/codebase/generated_keys.rb +31 -0
  212. data/lib/hecks/hecks/adapters/codebase/impacted_specs.rb +110 -0
  213. data/lib/hecks/hecks/adapters/codebase/language.rb +2 -2
  214. data/lib/hecks/hecks/adapters/codebase/launcher_text.rb +39 -0
  215. data/lib/hecks/hecks/adapters/codebase/minitest_runs.rb +52 -0
  216. data/lib/hecks/hecks/adapters/codebase/regeneration.rb +51 -8
  217. data/lib/hecks/hecks/adapters/codebase/run_options.rb +35 -0
  218. data/lib/hecks/hecks/adapters/codebase/scripting.rb +39 -0
  219. data/lib/hecks/hecks/adapters/codebase/search.rb +1 -1
  220. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +79 -51
  221. data/lib/hecks/hecks/adapters/codebase/spec_files/report.rb +71 -0
  222. data/lib/hecks/hecks/adapters/codebase/spec_files/shared_run.rb +73 -0
  223. data/lib/hecks/hecks/adapters/codebase/spec_files.rb +95 -0
  224. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +53 -4
  225. data/lib/hecks/hecks/adapters/codebase/test_scope.rb +105 -0
  226. data/lib/hecks/hecks/adapters/codebase/test_suite.rb +48 -34
  227. data/lib/hecks/hecks/adapters/console_capture.rb +1 -1
  228. data/lib/hecks/hecks/adapters/cost_explorer.rb +9 -1
  229. data/lib/hecks/hecks/adapters/dispatching/brief_text.rb +51 -0
  230. data/lib/hecks/hecks/adapters/dispatching/launcher.rb +97 -0
  231. data/lib/hecks/hecks/adapters/dispatching/plan.rb +82 -0
  232. data/lib/hecks/hecks/adapters/dispatching/rows.rb +66 -0
  233. data/lib/hecks/hecks/adapters/dispatching/settings.rb +81 -0
  234. data/lib/hecks/hecks/adapters/dispatching/settler.rb +40 -0
  235. data/lib/hecks/hecks/adapters/dispatching.adapter +7 -0
  236. data/lib/hecks/hecks/adapters/dispatching.rb +93 -0
  237. data/lib/hecks/hecks/adapters/doctor_reading/report.rb +27 -0
  238. data/lib/hecks/hecks/adapters/doctor_reading.adapter +7 -0
  239. data/lib/hecks/hecks/adapters/doctor_reading.rb +161 -0
  240. data/lib/hecks/hecks/adapters/git_checkout.rb +1 -1
  241. data/lib/hecks/hecks/adapters/git_commit.adapter +7 -0
  242. data/lib/hecks/hecks/adapters/git_commit.rb +61 -0
  243. data/lib/hecks/hecks/adapters/git_landing/finisher.rb +82 -0
  244. data/lib/hecks/hecks/adapters/git_landing/foreign_hold.rb +111 -0
  245. data/lib/hecks/hecks/adapters/git_landing/line.rb +171 -0
  246. data/lib/hecks/hecks/adapters/git_landing/lineup.rb +98 -0
  247. data/lib/hecks/hecks/adapters/git_landing/merger.rb +1 -1
  248. data/lib/hecks/hecks/adapters/git_landing/numbering.rb +54 -0
  249. data/lib/hecks/hecks/adapters/git_landing/rivals.rb +59 -0
  250. data/lib/hecks/hecks/adapters/git_landing/ticket.rb +156 -0
  251. data/lib/hecks/hecks/adapters/git_landing/tidy.rb +147 -0
  252. data/lib/hecks/hecks/adapters/git_landing/train.rb +104 -0
  253. data/lib/hecks/hecks/adapters/git_landing/verdict.rb +64 -0
  254. data/lib/hecks/hecks/adapters/git_landing/waiting.rb +120 -0
  255. data/lib/hecks/hecks/adapters/git_landing.rb +106 -20
  256. data/lib/hecks/hecks/adapters/git_main_pull.rb +99 -0
  257. data/lib/hecks/hecks/adapters/git_rehearsal/bench.rb +82 -0
  258. data/lib/hecks/hecks/adapters/git_rehearsal/due.rb +84 -0
  259. data/lib/hecks/hecks/adapters/git_rehearsal/impacted/skips.rb +47 -0
  260. data/lib/hecks/hecks/adapters/git_rehearsal/impacted/spec_run.rb +75 -0
  261. data/lib/hecks/hecks/adapters/git_rehearsal/impacted.rb +181 -0
  262. data/lib/hecks/hecks/adapters/git_rehearsal/line.rb +76 -0
  263. data/lib/hecks/hecks/adapters/git_rehearsal/reading.rb +24 -0
  264. data/lib/hecks/hecks/adapters/git_rehearsal/record.rb +146 -0
  265. data/lib/hecks/hecks/adapters/git_rehearsal/spec_map/corpus.rb +25 -0
  266. data/lib/hecks/hecks/adapters/git_rehearsal/spec_map/needles.rb +61 -0
  267. data/lib/hecks/hecks/adapters/git_rehearsal/spec_map.rb +105 -0
  268. data/lib/hecks/hecks/adapters/git_rehearsal/stages.rb +118 -0
  269. data/lib/hecks/hecks/adapters/git_rehearsal.adapter +7 -0
  270. data/lib/hecks/hecks/adapters/git_rehearsal.rb +141 -0
  271. data/lib/hecks/hecks/adapters/git_train/bench.rb +15 -15
  272. data/lib/hecks/hecks/adapters/git_train/branch_guard.rb +62 -0
  273. data/lib/hecks/hecks/adapters/git_train/carriage.rb +27 -28
  274. data/lib/hecks/hecks/adapters/git_train/launcher_shape.rb +75 -0
  275. data/lib/hecks/hecks/adapters/git_train/mint_step.rb +47 -0
  276. data/lib/hecks/hecks/adapters/git_train/settlement.rb +167 -0
  277. data/lib/hecks/hecks/adapters/git_train.rb +73 -15
  278. data/lib/hecks/hecks/adapters/git_worktree_add.adapter +7 -0
  279. data/lib/hecks/hecks/adapters/git_worktree_add.rb +68 -0
  280. data/lib/hecks/hecks/adapters/github_pull_requests.adapter +7 -0
  281. data/lib/hecks/hecks/adapters/github_pull_requests.rb +109 -0
  282. data/lib/hecks/hecks/adapters/host_http.rb +6 -6
  283. data/lib/hecks/hecks/adapters/in_process_boot.rb +10 -8
  284. data/lib/hecks/hecks/adapters/in_process_operations.rb +11 -17
  285. data/lib/hecks/hecks/adapters/in_process_undo.rb +17 -0
  286. data/lib/hecks/hecks/adapters/journal_store/changes.rb +13 -4
  287. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +28 -15
  288. data/lib/hecks/hecks/adapters/journal_store/examination.rb +17 -1
  289. data/lib/hecks/hecks/adapters/journal_store/held_domain/renaming.rb +45 -0
  290. data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +31 -5
  291. data/lib/hecks/hecks/adapters/journal_store/held_mint.rb +128 -0
  292. data/lib/hecks/hecks/adapters/journal_store/readings/attestation.rb +1 -1
  293. data/lib/hecks/hecks/adapters/journal_store/readings/boot_status.rb +58 -0
  294. data/lib/hecks/hecks/adapters/journal_store/readings/composition.rb +39 -0
  295. data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/outcomes.rb +76 -0
  296. data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/postgres_reader.rb +44 -0
  297. data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/reader.rb +64 -0
  298. data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/report.rb +102 -0
  299. data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/sqlite_reader.rb +43 -0
  300. data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/stores.rb +80 -0
  301. data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/subscribers.rb +72 -0
  302. data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/summary.rb +39 -0
  303. data/lib/hecks/hecks/adapters/journal_store/readings/event_trace.rb +39 -0
  304. data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/command_line.rb +57 -0
  305. data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/edge_guards.rb +107 -0
  306. data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/inspection.rb +94 -0
  307. data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/plan.rb +66 -0
  308. data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/report.rb +72 -0
  309. data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/store.rb +34 -0
  310. data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/watermark_guards.rb +86 -0
  311. data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/world.rb +66 -0
  312. data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan.rb +36 -0
  313. data/lib/hecks/hecks/adapters/journal_store/readings/projection_audit.rb +64 -0
  314. data/lib/hecks/hecks/adapters/journal_store/readings/scaffolding.rb +3 -3
  315. data/lib/hecks/hecks/adapters/journal_store/readings/sqlite_status/database_reading.rb +113 -0
  316. data/lib/hecks/hecks/adapters/journal_store/readings/sqlite_status/read_only.rb +33 -0
  317. data/lib/hecks/hecks/adapters/journal_store/readings/sqlite_status.rb +32 -0
  318. data/lib/hecks/hecks/adapters/journal_store/readings.rb +13 -1
  319. data/lib/hecks/hecks/adapters/journal_store/reconcile_report.rb +60 -0
  320. data/lib/hecks/hecks/adapters/journal_store/reconciliation.rb +121 -0
  321. data/lib/hecks/hecks/adapters/journal_store/translation_write/shape_edge.rb +59 -0
  322. data/lib/hecks/hecks/adapters/journal_store/translation_write.rb +123 -0
  323. data/lib/hecks/hecks/adapters/journal_store.rb +16 -0
  324. data/lib/hecks/hecks/adapters/landed_work.adapter +7 -0
  325. data/lib/hecks/hecks/adapters/landed_work.rb +52 -0
  326. data/lib/hecks/hecks/adapters/local_files.rb +6 -6
  327. data/lib/hecks/hecks/adapters/process_pool.rb +3 -2
  328. data/lib/hecks/hecks/adapters/push_size.rb +57 -0
  329. data/lib/hecks/hecks/adapters/qa_quiescing.adapter +7 -0
  330. data/lib/hecks/hecks/adapters/qa_quiescing.rb +57 -0
  331. data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +30 -3
  332. data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +63 -3
  333. data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +29 -6
  334. data/lib/hecks/hecks/adapters/rehearsal/subject.rb +11 -5
  335. data/lib/hecks/hecks/adapters/rust_toolchain.rb +10 -1
  336. data/lib/hecks/hecks/adapters/rust_workspace.rb +1 -1
  337. data/lib/hecks/hecks/adapters/settings_reading/disposable_ledger.rb +32 -0
  338. data/lib/hecks/hecks/adapters/settings_reading/push_nudge.rb +26 -0
  339. data/lib/hecks/hecks/adapters/settings_reading/stores.rb +76 -0
  340. data/lib/hecks/hecks/adapters/settings_reading/test_scope.rb +28 -0
  341. data/lib/hecks/hecks/adapters/settings_reading.rb +28 -2
  342. data/lib/hecks/hecks/adapters/started_work.rb +42 -0
  343. data/lib/hecks/hecks/adapters/terminal.rb +12 -10
  344. data/lib/hecks/hecks/adapters/where_reading.adapter +7 -0
  345. data/lib/hecks/hecks/adapters/where_reading.rb +64 -0
  346. data/lib/hecks/hecks/adapters/work_areas.rb +57 -0
  347. data/lib/hecks/hecks/adapters/work_limits.rb +57 -0
  348. data/lib/hecks/hecks/build/build.bluebook +576 -0
  349. data/lib/hecks/hecks/check/check.bluebook +966 -0
  350. data/lib/hecks/hecks/codebase.behaviors +61 -5
  351. data/lib/hecks/hecks/composer.behaviors +1 -1
  352. data/lib/hecks/hecks/context_map.hecksagon +1 -1
  353. data/lib/hecks/hecks/custodian.behaviors +33 -7
  354. data/lib/hecks/hecks/delegate/delegate.bluebook +355 -0
  355. data/lib/hecks/hecks/deliver/deliver.bluebook +945 -0
  356. data/lib/hecks/hecks/deploy.behaviors +1 -1
  357. data/lib/hecks/hecks/evolve/evolve.bluebook +788 -0
  358. data/lib/hecks/hecks/find/find.bluebook +81 -0
  359. data/lib/hecks/hecks/hecks.behaviors +1 -1
  360. data/lib/hecks/hecks/hecks.bluebook +0 -133
  361. data/lib/hecks/hecks/hecks.contextmap +2 -0
  362. data/lib/hecks/hecks/hecks.hecksagon +185 -29
  363. data/lib/hecks/hecks/hecks.world +35 -9
  364. data/lib/hecks/hecks/implicit_moves.json +24 -0
  365. data/lib/hecks/hecks/migrate/migrate.bluebook +1066 -0
  366. data/lib/hecks/hecks/operate/operate.bluebook +695 -0
  367. data/lib/hecks/hecks/quiesce/quiesce.bluebook +117 -0
  368. data/lib/hecks/hecks/rehearse/rehearse.bluebook +133 -0
  369. data/lib/hecks/hecks/release/release.bluebook +916 -0
  370. data/lib/hecks/hecks/serve/serve.bluebook +134 -0
  371. data/lib/hecks/hecks/shapes.json +1 -15
  372. data/lib/hecks/hecks/site.behaviors +1 -1
  373. data/lib/hecks/hecks/start/start.bluebook +194 -0
  374. data/lib/hecks/hecks/test/test.bluebook +638 -0
  375. data/lib/hecks/hecks/tickets.world +14 -0
  376. data/lib/hecks/language/bluebook/aggregate.bluebook +22 -0
  377. data/lib/hecks/language/bluebook/bluebook.bluebook +34 -0
  378. data/lib/hecks/language/bluebook/command.bluebook +35 -0
  379. data/lib/hecks/language/bluebook/process_manager.bluebook +14 -1
  380. data/lib/hecks/language/bluebook/vocabulary.bluebook +174 -54
  381. data/lib/hecks/language/hecksagon/domain_port.bluebook +1 -0
  382. data/lib/hecks/language/hecksagon/port_operation.bluebook +14 -0
  383. data/lib/hecks/language/kinds/run.kind +120 -0
  384. data/lib/hecks/language/oidc.json +10 -0
  385. data/lib/hecks/language/translation/translation_aggregate.bluebook +24 -0
  386. data/lib/hecks/module_folders.rb +31 -0
  387. data/lib/hecks/ports/key_vault.rb +1 -1
  388. data/lib/hecks/ports/persistence/append_only.rb +26 -8
  389. data/lib/hecks/ports/persistence/binding_policy.rb +3 -1
  390. data/lib/hecks/ports/persistence/codec_boundary.rb +1 -1
  391. data/lib/hecks/ports/persistence/mint_door.rb +74 -0
  392. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +6 -5
  393. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +5 -1
  394. data/lib/hecks/ports/persistence/plugins/era/era_status.rb +48 -0
  395. data/lib/hecks/ports/persistence/plugins/era/projected_bluebook.rb +127 -0
  396. data/lib/hecks/ports/persistence/plugins/era/translation/additive_shape.rb +107 -0
  397. data/lib/hecks/ports/persistence/plugins/era/translation/compose.rb +155 -0
  398. data/lib/hecks/ports/persistence/plugins/era/translation/compose_render.rb +79 -0
  399. data/lib/hecks/ports/persistence/plugins/era/translation/edge_files.rb +49 -0
  400. data/lib/hecks/ports/persistence/plugins/era/translation/edge_route.rb +61 -0
  401. data/lib/hecks/ports/persistence/plugins/era/translation/implicit_edge.rb +67 -0
  402. data/lib/hecks/ports/persistence/plugins/era/translation/reconcile.rb +130 -0
  403. data/lib/hecks/ports/persistence/plugins/era/translation/reconcile_files.rb +35 -0
  404. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +13 -5
  405. data/lib/hecks/ports/persistence/plugins/era/translation.rb +5 -0
  406. data/lib/hecks/ports/persistence/plugins/era.rb +1 -0
  407. data/lib/hecks/ports/persistence/repository_factory.rb +11 -3
  408. data/lib/hecks/ports/persistence/stored_name_guard.rb +36 -0
  409. data/lib/hecks/ports/persistence.rb +2 -0
  410. data/lib/hecks/projections/ci_pipeline/table/checks.rb +137 -0
  411. data/lib/hecks/projections/ci_pipeline/table/lookup.rb +59 -0
  412. data/lib/hecks/projections/ci_pipeline/table/refusals.rb +58 -0
  413. data/lib/hecks/projections/ci_pipeline/table/rows.rb +119 -0
  414. data/lib/hecks/projections/ci_pipeline/table/tree.rb +30 -0
  415. data/lib/hecks/projections/ci_pipeline/table/typing.rb +92 -0
  416. data/lib/hecks/projections/ci_pipeline/table.rb +112 -0
  417. data/lib/hecks/projections/ci_pipeline/workflows.rb +162 -0
  418. data/lib/hecks/projections/ci_pipeline/yaml_text.rb +104 -0
  419. data/lib/hecks/projections/deploy/box/hosting.rb +1 -1
  420. data/lib/hecks/projections/deploy/box/roll_recipe.rb +1 -1
  421. data/lib/hecks/projections/deploy/box/roll_scripts.rb +1 -1
  422. data/lib/hecks/projections/deploy/box.rb +1 -1
  423. data/lib/hecks/projections/deploy/templates/fargate/Makefile.tmpl +1 -1
  424. data/lib/hecks/projections/deploy/templates/lambda/Makefile.tmpl +3 -3
  425. data/lib/hecks/projections/undo.rb +46 -0
  426. data/lib/hecks/projections.rb +2 -0
  427. data/lib/hecks/projector/cli_projector/claims.rb +11 -0
  428. data/lib/hecks/projector/cli_projector/command_help.rb +6 -1
  429. data/lib/hecks/projector/cli_projector/command_specs.rb +11 -1
  430. data/lib/hecks/projector/cli_projector/completion.rb +87 -0
  431. data/lib/hecks/projector/cli_projector/everyday.rb +40 -0
  432. data/lib/hecks/projector/cli_projector/json_listing.rb +77 -0
  433. data/lib/hecks/projector/cli_projector/listing.rb +1 -1
  434. data/lib/hecks/projector/cli_projector/modules.rb +39 -0
  435. data/lib/hecks/projector/cli_projector/query_specs.rb +1 -0
  436. data/lib/hecks/projector/cli_projector/renames.rb +58 -0
  437. data/lib/hecks/projector/cli_projector/search.rb +74 -0
  438. data/lib/hecks/projector/cli_projector/usage.rb +23 -6
  439. data/lib/hecks/projector/cli_projector.rb +24 -1
  440. data/lib/hecks/quality_control/adapters/ci_head.adapter +8 -0
  441. data/lib/hecks/quality_control/adapters/image_roll.adapter +9 -0
  442. data/lib/hecks/quality_control/adapters/image_roll.rb +158 -0
  443. data/lib/hecks/quality_control/adapters/main_maintenance.adapter +8 -0
  444. data/lib/hecks/quality_control/adapters/main_maintenance.rb +275 -0
  445. data/lib/hecks/quality_control/adapters/pump_tools.adapter +7 -0
  446. data/lib/hecks/quality_control/adapters/pump_tools.rb +18 -0
  447. data/lib/hecks/quality_control/adapters/push_due_reader.adapter +8 -0
  448. data/lib/hecks/quality_control/adapters/push_due_reader.rb +99 -0
  449. data/lib/hecks/quality_control/adapters/qa_auto_mint.rb +183 -0
  450. data/lib/hecks/quality_control/adapters/qa_era_mint.rb +94 -0
  451. data/lib/hecks/quality_control/adapters/qa_quiesce_marker.rb +126 -0
  452. data/lib/hecks/quality_control/adapters/run_keys.rb +36 -0
  453. data/lib/hecks/quality_control/adapters/run_reader.adapter +7 -0
  454. data/lib/hecks/quality_control/adapters/run_reader.rb +188 -0
  455. data/lib/hecks/quality_control/cli/child.rb +1 -0
  456. data/lib/hecks/quality_control/cli/qa_discover_external_domains/scanning.rb +1 -1
  457. data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +3 -3
  458. data/lib/hecks/quality_control/cli/qa_event_pump/attached.rb +67 -0
  459. data/lib/hecks/quality_control/cli/qa_event_pump/consumer.rb +103 -0
  460. data/lib/hecks/quality_control/cli/qa_event_pump/cursors.rb +60 -0
  461. data/lib/hecks/quality_control/cli/qa_event_pump/reactions.rb +46 -0
  462. data/lib/hecks/quality_control/cli/qa_event_pump/reader.rb +30 -0
  463. data/lib/hecks/quality_control/cli/qa_event_pump.rb +76 -0
  464. data/lib/hecks/quality_control/cli/qa_fix_main_bug/publishing.rb +79 -0
  465. data/lib/hecks/quality_control/cli/qa_fix_main_bug.rb +167 -0
  466. data/lib/hecks/quality_control/cli/qa_generated_domains/evaluation.rb +1 -1
  467. data/lib/hecks/quality_control/cli/qa_generated_domains/promotion.rb +3 -3
  468. data/lib/hecks/quality_control/cli/qa_main_gate/gate_run.rb +52 -0
  469. data/lib/hecks/quality_control/cli/qa_main_gate/logging.rb +70 -0
  470. data/lib/hecks/quality_control/cli/qa_main_gate/shell.rb +47 -0
  471. data/lib/hecks/quality_control/cli/qa_main_gate/sweeping.rb +59 -0
  472. data/lib/hecks/quality_control/cli/qa_main_gate/worktree.rb +62 -0
  473. data/lib/hecks/quality_control/cli/qa_main_gate.rb +135 -0
  474. data/lib/hecks/quality_control/cli/qa_postgres_role.rb +1 -1
  475. data/lib/hecks/quality_control/cli/qa_pr_check/checking.rb +2 -3
  476. data/lib/hecks/quality_control/cli/qa_push_nudge.rb +48 -0
  477. data/lib/hecks/quality_control/cli/qa_seed_angles/seed.rb +1 -1
  478. data/lib/hecks/quality_control/cli/qa_sweep/seat.rb +1 -1
  479. data/lib/hecks/quality_control/cli/qa_tick/event_pump_step.rb +34 -0
  480. data/lib/hecks/quality_control/cli/qa_tick/output.rb +16 -1
  481. data/lib/hecks/quality_control/cli/qa_tick/push_nudge_step.rb +28 -0
  482. data/lib/hecks/quality_control/cli/qa_tick/quiesce_guard.rb +51 -0
  483. data/lib/hecks/quality_control/cli/qa_tick.rb +36 -8
  484. data/lib/hecks/quality_control/quality_control.behaviors +65 -0
  485. data/lib/hecks/quality_control/quality_control.bluebook +1131 -11
  486. data/lib/hecks/quality_control/quality_control.hecksagon +11 -0
  487. data/lib/hecks/quality_control/quality_control.ports.hecksagon +138 -0
  488. data/lib/hecks/query_ir/touchpoints.rb +5 -7
  489. data/lib/hecks/refused.rb +21 -0
  490. data/lib/hecks/release/approval.rb +6 -3
  491. data/lib/hecks/release/conditions.rb +46 -0
  492. data/lib/hecks/release/runner/gem_publisher.rb +4 -4
  493. data/lib/hecks/release/version_commit.rb +48 -0
  494. data/lib/hecks/runtime/command_interpreter/hydration.rb +5 -4
  495. data/lib/hecks/runtime/command_interpreter/persisting.rb +11 -3
  496. data/lib/hecks/runtime/command_interpreter.rb +2 -2
  497. data/lib/hecks/runtime/command_rules/admissibility.rb +0 -2
  498. data/lib/hecks/runtime/command_rules/emission.rb +0 -1
  499. data/lib/hecks/runtime/dependency_planning/expression_reads.rb +0 -1
  500. data/lib/hecks/runtime/dispatcher/planning.rb +24 -0
  501. data/lib/hecks/runtime/dispatcher/routing.rb +6 -0
  502. data/lib/hecks/runtime/dispatcher/value_routing.rb +54 -0
  503. data/lib/hecks/runtime/dispatcher.rb +7 -1
  504. data/lib/hecks/runtime/dry_run_plan.rb +60 -0
  505. data/lib/hecks/runtime/entity_element/location.rb +0 -1
  506. data/lib/hecks/runtime/entity_element/mutations.rb +0 -1
  507. data/lib/hecks/runtime/entity_interpreter/locating.rb +5 -0
  508. data/lib/hecks/runtime/entity_interpreter.rb +0 -1
  509. data/lib/hecks/runtime/errors.rb +26 -0
  510. data/lib/hecks/runtime/instance.rb +0 -1
  511. data/lib/hecks/runtime/invocation_builder.rb +0 -1
  512. data/lib/hecks/runtime/outbox/consumer_runner.rb +9 -1
  513. data/lib/hecks/runtime/outbox/relay.rb +25 -4
  514. data/lib/hecks/runtime/outbox/runnable.rb +3 -1
  515. data/lib/hecks/runtime/outbox.rb +6 -2
  516. data/lib/hecks/runtime/policy_interpreter/fan_out.rb +18 -2
  517. data/lib/hecks/runtime/policy_interpreter.rb +17 -9
  518. data/lib/hecks/runtime/port_operation_interpreter.rb +21 -7
  519. data/lib/hecks/runtime/query_interpreter/arguments.rb +6 -5
  520. data/lib/hecks/runtime/reaction_invocation.rb +0 -1
  521. data/lib/hecks/runtime/refusal_wording.rb +12 -1
  522. data/lib/hecks/runtime/registry/context_maps.rb +1 -5
  523. data/lib/hecks/runtime/registry/declarations.rb +34 -4
  524. data/lib/hecks/runtime/registry/hecksagon_rules.rb +15 -1
  525. data/lib/hecks/runtime/registry/runtime_state.rb +10 -0
  526. data/lib/hecks/runtime/registry/world_defaults.rb +24 -2
  527. data/lib/hecks/runtime/registry/world_names.rb +99 -0
  528. data/lib/hecks/runtime/registry.rb +33 -27
  529. data/lib/hecks/runtime/saga_interpreter/compensation.rb +10 -0
  530. data/lib/hecks/runtime/saga_interpreter/correlation.rb +29 -3
  531. data/lib/hecks/runtime/saga_interpreter/delivery.rb +0 -1
  532. data/lib/hecks/runtime/saga_interpreter/lifecycle.rb +1 -1
  533. data/lib/hecks/runtime/saga_interpreter.rb +46 -2
  534. data/lib/hecks/runtime/value/coercion.rb +36 -8
  535. data/lib/hecks/rust_build/conformance.rb +16 -5
  536. data/lib/hecks/rust_build/parser.rb +25 -0
  537. data/lib/hecks/rust_build/project_rust/codegen_run.rb +45 -12
  538. data/lib/hecks/rust_build/project_rust/declared.rb +80 -0
  539. data/lib/hecks/rust_build/project_rust/features_header.rb +22 -0
  540. data/lib/hecks/rust_build/project_rust/manifest.rb +96 -0
  541. data/lib/hecks/rust_build/project_rust/meta.rb +36 -0
  542. data/lib/hecks/rust_build/project_rust.rb +28 -90
  543. data/lib/hecks/rust_build/write_if_changed.rb +19 -4
  544. data/lib/hecks/rust_build.rb +2 -1
  545. data/lib/hecks/rust_format.rb +32 -2
  546. data/lib/hecks/secrets.rb +111 -0
  547. data/lib/hecks/shape_ledger/edge_hygiene.rb +170 -0
  548. data/lib/hecks/shape_ledger/scope.rb +51 -0
  549. data/lib/hecks/shape_ledger/status.rb +89 -0
  550. data/lib/hecks/shape_ledger.rb +78 -33
  551. data/lib/hecks/site/bluebook/site.bluebook +1 -0
  552. data/lib/hecks/storehouse/audit.rb +34 -4
  553. data/lib/hecks/storehouse/callers.rb +8 -0
  554. data/lib/hecks/storehouse/dispatching.rb +14 -3
  555. data/lib/hecks/storehouse/identity.rb +41 -0
  556. data/lib/hecks/storehouse/querying.rb +7 -7
  557. data/lib/hecks/storehouse.rb +28 -10
  558. data/lib/hecks/tickets/bluebook/adapters/work_areas.adapter +7 -0
  559. data/lib/hecks/tickets/bluebook/adapters/work_limits.adapter +7 -0
  560. data/lib/hecks/tickets/bluebook/tickets.behaviors +70 -0
  561. data/lib/hecks/tickets/bluebook/tickets.bluebook +323 -28
  562. data/lib/hecks/tickets/bluebook/tickets.hecksagon +7 -0
  563. data/lib/hecks/tickets/bluebook/tickets.ports.hecksagon +17 -0
  564. data/lib/hecks/{cli → tools}/behaviors.rb +1 -1
  565. data/lib/hecks/{cli → tools}/canonicalise.rb +1 -1
  566. data/lib/hecks/{cli → tools}/check_engine_agreement.rb +1 -1
  567. data/lib/hecks/{cli → tools}/check_era.rb +6 -6
  568. data/lib/hecks/tools/ci_gates.rb +8 -2
  569. data/lib/hecks/tools/ci_workflows.rb +98 -0
  570. data/lib/hecks/{cli → tools}/console.rb +1 -1
  571. data/lib/hecks/{cli → tools}/deploy_template_diff.rb +1 -1
  572. data/lib/hecks/{cli → tools}/doc_coverage.rb +2 -2
  573. data/lib/hecks/{cli → tools}/document.rb +1 -1
  574. data/lib/hecks/{cli → tools}/domain_stub.rb +1 -1
  575. data/lib/hecks/{cli → tools}/domain_writer.rb +1 -1
  576. data/lib/hecks/tools/downstream_model_check.rb +122 -0
  577. data/lib/hecks/tools/evolve_run.rb +2 -2
  578. data/lib/hecks/{cli → tools}/expected_era.rb +1 -1
  579. data/lib/hecks/{cli → tools}/expression_projection.rb +1 -1
  580. data/lib/hecks/{cli → tools}/follow.rb +1 -1
  581. data/lib/hecks/tools/fuzz_sweep/options.rb +40 -5
  582. data/lib/hecks/tools/fuzz_sweep/pool.rb +12 -1
  583. data/lib/hecks/tools/fuzz_sweep/shards.rb +155 -0
  584. data/lib/hecks/tools/fuzz_sweep.rb +11 -5
  585. data/lib/hecks/tools/gate.rb +38 -29
  586. data/lib/hecks/tools/gate_memo/local_files.rb +33 -0
  587. data/lib/hecks/tools/gate_memo/rehearsal.rb +54 -0
  588. data/lib/hecks/tools/gate_memo/ruby_files.rb +152 -0
  589. data/lib/hecks/tools/gate_memo/session.rb +114 -0
  590. data/lib/hecks/tools/gate_memo/standalone.rb +67 -0
  591. data/lib/hecks/tools/gate_memo.rb +196 -0
  592. data/lib/hecks/tools/gate_report.rb +56 -0
  593. data/lib/hecks/{cli → tools}/history.rb +1 -1
  594. data/lib/hecks/{cli → tools}/interview_agent.rb +1 -1
  595. data/lib/hecks/{cli → tools}/interview_aggregate.rb +1 -1
  596. data/lib/hecks/{cli → tools}/interview_draft.rb +1 -1
  597. data/lib/hecks/{cli → tools}/interview_record.rb +1 -1
  598. data/lib/hecks/{cli → tools}/interview_run.rb +2 -2
  599. data/lib/hecks/{cli → tools}/interview_session/agent_state.rb +1 -1
  600. data/lib/hecks/{cli → tools}/interview_session/catalog.rb +1 -1
  601. data/lib/hecks/{cli → tools}/interview_session/manual_findings.rb +1 -1
  602. data/lib/hecks/{cli → tools}/interview_session/proposals.rb +1 -1
  603. data/lib/hecks/{cli → tools}/interview_session.rb +2 -2
  604. data/lib/hecks/{cli → tools}/interview_shape/lifecycle.rb +1 -1
  605. data/lib/hecks/{cli → tools}/interview_shape.rb +1 -1
  606. data/lib/hecks/{cli → tools}/ir.rb +1 -1
  607. data/lib/hecks/tools/lanes/files.rb +1 -1
  608. data/lib/hecks/tools/lanes/watch_workflow.rb +6 -8
  609. data/lib/hecks/tools/lanes/workflow.rb +1 -1
  610. data/lib/hecks/tools/lanes.rb +1 -1
  611. data/lib/hecks/{cli → tools}/mcp.rb +1 -1
  612. data/lib/hecks/{cli → tools}/model_check/examination.rb +1 -1
  613. data/lib/hecks/{cli → tools}/model_check/sources.rb +1 -1
  614. data/lib/hecks/{cli → tools}/model_check.rb +1 -1
  615. data/lib/hecks/tools/move_disables/reasons.rb +35 -0
  616. data/lib/hecks/tools/move_disables.rb +211 -0
  617. data/lib/hecks/tools/move_former_name.rb +105 -0
  618. data/lib/hecks/{cli → tools}/pattern_cases.rb +1 -1
  619. data/lib/hecks/{cli → tools}/persistence_notice.rb +1 -1
  620. data/lib/hecks/{cli → tools}/present.rb +1 -1
  621. data/lib/hecks/{cli → tools}/project_cli/launcher_source.rb +32 -22
  622. data/lib/hecks/{cli → tools}/project_cli/templates.rb +22 -15
  623. data/lib/hecks/{cli → tools}/project_cli.rb +11 -7
  624. data/lib/hecks/{cli → tools}/project_diagrams.rb +3 -3
  625. data/lib/hecks/{cli → tools}/project_glossary.rb +2 -2
  626. data/lib/hecks/{cli → tools}/reference.rb +2 -2
  627. data/lib/hecks/{cli → tools}/refresh_projections.rb +1 -1
  628. data/lib/hecks/{cli → tools}/refresh_rspec_runtime_baseline.rb +1 -1
  629. data/lib/hecks/tools/regeneration_run/pool.rb +148 -0
  630. data/lib/hecks/tools/regeneration_run/scratch.rb +76 -0
  631. data/lib/hecks/tools/regeneration_run.rb +125 -103
  632. data/lib/hecks/{cli → tools}/release.rb +1 -1
  633. data/lib/hecks/{cli → tools}/release_gem.rb +1 -1
  634. data/lib/hecks/{cli → tools}/rspec_io_parallel_files.rb +1 -1
  635. data/lib/hecks/{cli → tools}/rspec_shard_files.rb +1 -1
  636. data/lib/hecks/{cli → tools}/run.rb +9 -2
  637. data/lib/hecks/{cli → tools}/run_expectations.rb +1 -1
  638. data/lib/hecks/{cli → tools}/seed_semantics_corpus.rb +4 -4
  639. data/lib/hecks/{cli → tools}/serve_query_ir_mcp.rb +1 -1
  640. data/lib/hecks/{cli → tools}/shape.rb +3 -2
  641. data/lib/hecks/{cli → tools}/smoke_http/checks.rb +1 -1
  642. data/lib/hecks/{cli → tools}/smoke_http/settings.rb +1 -1
  643. data/lib/hecks/{cli → tools}/smoke_http/transport.rb +1 -1
  644. data/lib/hecks/{cli → tools}/smoke_http.rb +1 -1
  645. data/lib/hecks/{cli → tools}/smoke_test.rb +1 -1
  646. data/lib/hecks/{cli → tools}/spec_example.rb +1 -1
  647. data/lib/hecks/tools/stage_progress.rb +54 -0
  648. data/lib/hecks/{cli → tools}/statements.rb +1 -1
  649. data/lib/hecks/{cli → tools}/stores.rb +1 -1
  650. data/lib/hecks/{cli → tools}/stress_concurrency_specs/reporting.rb +1 -1
  651. data/lib/hecks/{cli → tools}/stress_concurrency_specs/usage.rb +4 -4
  652. data/lib/hecks/{cli → tools}/stress_concurrency_specs.rb +3 -3
  653. data/lib/hecks/tools/tenant_provisioning.rb +23 -0
  654. data/lib/hecks/tools/tools_doc.rb +10 -8
  655. data/lib/hecks/tools/translation_audit/edges.rb +21 -16
  656. data/lib/hecks/tools/translation_audit/verdicts.rb +1 -1
  657. data/lib/hecks/tools/translation_audit.rb +1 -1
  658. data/lib/hecks/tools/translation_scaffold.rb +1 -1
  659. data/lib/hecks/tools.rb +4 -1
  660. data/lib/hecks/version.rb +1 -1
  661. data/lib/hecks/vocabulary.rb +61 -31
  662. data/lib/hecks/workflow_pagination/judge.rb +48 -0
  663. data/lib/hecks/workflow_pagination/statement.rb +50 -0
  664. data/lib/hecks/workflow_pagination.rb +58 -0
  665. data/lib/hecks.rb +2 -0
  666. data/lib/rubocop/cop/hecks/bare_event_and_query_names.rb +58 -0
  667. data/lib/rubocop/cop/hecks/correlates_by_aggregate.rb +39 -0
  668. data/lib/rubocop/cop/hecks/creating_command_sets.rb +75 -0
  669. data/lib/rubocop/cop/hecks/invariant_expression_language.rb +47 -0
  670. data/lib/rubocop/cop/hecks/lifecycle_needs_attribute.rb +58 -0
  671. data/lib/rubocop/cop/hecks/no_id_string_attribute.rb +49 -0
  672. data/lib/rubocop/cop/hecks/one_terminal_mark_per_lifecycle.rb +47 -0
  673. data/lib/rubocop/cop/hecks/value_object_shorthand.rb +56 -0
  674. data/prebuilt/13c04bdc5970295b310f0a980d397ba722232c8da99cc1a0cdb383249921e871.marshal +0 -0
  675. data/prebuilt/e3857b77f47d9ecc1787b2e1f5136364f3cb3444ef4aea5479f3b98167affea2.marshal +0 -0
  676. data/qa/settings.yml +23 -0
  677. data/rust/.gitignore +0 -6
  678. data/rust/Cargo.toml +2 -1
  679. data/rust/build/Cargo.toml +1 -1
  680. data/rust/build/src/binding_pass.rs +57 -4
  681. data/rust/build/src/pipeline.rs +6 -4
  682. data/rust/build/src/resolve.rs +1 -0
  683. data/rust/codegen/Cargo.toml +1 -1
  684. data/rust/codegen/src/domain_generator.rs +3 -0
  685. data/rust/codegen/src/json_codec.rs +182 -23
  686. data/rust/codegen/src/one_of_references.rs +1 -0
  687. data/rust/codegen/src/queries.rs +20 -2
  688. data/rust/codegen/src/registry.rs +21 -5
  689. data/rust/expr/Cargo.toml +1 -1
  690. data/rust/host/Cargo.toml +1 -1
  691. data/rust/host/HECKS_RELEASE +1 -1
  692. data/rust/host/core/Cargo.toml +1 -1
  693. data/rust/host/src/bin/mint_harness.rs +1 -0
  694. data/rust/host/src/boot.rs +1 -0
  695. data/rust/host/src/store/mint.rs +40 -6
  696. data/rust/lsp/Cargo.toml +1 -1
  697. data/rust/parser/Cargo.toml +1 -1
  698. data/rust/parser/src/build/correlation_keys.rs +125 -0
  699. data/rust/parser/src/build/mod.rs +1 -0
  700. data/rust/parser/src/emit.rs +55 -3
  701. data/rust/parser/src/ir.rs +33 -1
  702. data/rust/parser/src/keywords.rs +289 -1
  703. data/rust/parser/src/main.rs +2 -0
  704. data/rust/parser/src/parse/aggregate.rs +10 -1
  705. data/rust/parser/src/parse/audience.rs +65 -0
  706. data/rust/parser/src/parse/command.rs +14 -0
  707. data/rust/parser/src/parse/declaration.rs +97 -0
  708. data/rust/parser/src/parse/domain_port.rs +6 -0
  709. data/rust/parser/src/parse/mod.rs +1 -0
  710. data/rust/parser/src/parse/process_manager.rs +17 -10
  711. data/rust/parser/src/parse/world.rs +12 -8
  712. data/rust/parser/src/render_ruby.rs +9 -0
  713. data/rust/parser/src/sentence/format.rs +3 -0
  714. data/rust/parser/src/sentence/process.rs +6 -2
  715. data/rust/src/exemplar/json.rs +17 -0
  716. data/rust/src/kernel/cli.rs +27 -3
  717. data/rust/src/kernel/dispatch.rs +4 -2
  718. data/rust/src/kernel/json.rs +62 -0
  719. data/rust/src/kernel/orchestrate.rs +28 -3
  720. data/rust/src/kernel/orchestrate_guard_tests.rs +12 -12
  721. data/rust/web/Cargo.toml +1 -1
  722. metadata +389 -96
  723. data/lib/hecks/cli/command_table.rb +0 -72
  724. data/lib/hecks/cli/launcher_words.rb +0 -168
  725. data/lib/hecks/cli.rb +0 -133
  726. data/lib/hecks/hecks/agents.bluebook +0 -246
  727. data/lib/hecks/hecks/codebase.bluebook +0 -3209
  728. data/lib/hecks/hecks/custodian.bluebook +0 -1300
  729. data/lib/hecks/hecks/ledger.bluebook +0 -190
  730. data/lib/hecks/hecks/rehearsal.bluebook +0 -437
  731. data/lib/hecks/hecks/tooling.bluebook +0 -1234
  732. data/lib/hecks/hecks/translations/2-148748.bluebook +0 -2
  733. data/lib/hecks/hecks/translations/2-15a2e4.bluebook +0 -2
  734. data/lib/hecks/hecks/translations/2-1b447c.bluebook +0 -5
  735. data/lib/hecks/hecks/translations/2-240474.bluebook +0 -2
  736. data/lib/hecks/hecks/translations/2-44446d.bluebook +0 -2
  737. data/lib/hecks/hecks/translations/2-46ca26.bluebook +0 -2
  738. data/lib/hecks/hecks/translations/2-473eab.bluebook +0 -2
  739. data/lib/hecks/hecks/translations/2-75cc28.bluebook +0 -2
  740. data/lib/hecks/hecks/translations/2-781c07.bluebook +0 -2
  741. data/lib/hecks/hecks/translations/2-84c18b.bluebook +0 -2
  742. data/lib/hecks/hecks/translations/2-aa5fff.bluebook +0 -2
  743. data/lib/hecks/hecks/translations/2-bfdb48.bluebook +0 -2
  744. data/lib/hecks/hecks/translations/2-cd96d8.bluebook +0 -10
  745. data/lib/hecks/hecks/translations/2-d43f71.bluebook +0 -2
  746. data/lib/hecks/hecks/translations/2-eea577.bluebook +0 -2
  747. data/lib/hecks/hecks/translations/2-f53248.bluebook +0 -2
  748. data/lib/hecks/hecks/translations/2-fbb677.bluebook +0 -2
  749. data/lib/hecks/hecks/translations/2-ffdf12.bluebook +0 -6
  750. data/lib/hecks/quality_control/adapters/clearance_recorder.rb +0 -36
  751. data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +0 -56
  752. data/prebuilt/31cf81e12f16236ad26249be590cfea3799c9db67432e6a4ef54b801c355b6ae.marshal +0 -0
  753. data/prebuilt/68ecb2bd3abb1a221007db4f2b0375834c13aaccac8f2b99778e8517f11aa113.marshal +0 -0
  754. data/prebuilt/verdicts-0328c2403383837d780ad5ed81d1da351c56436b894cf9015b5d56b8f1f1bf10.json +0 -1
@@ -0,0 +1,99 @@
1
+ require_relative "../errors"
2
+ require_relative "../../deprecation"
3
+
4
+ module Hecks
5
+ module Runtime
6
+ class Registry
7
+ # The names a world gives to what is stored: `stored_as Revision: "commit"` (the table or key
8
+ # an aggregate's rows sit under) at the world's top level, and `formerly "Old"` in a
9
+ # persistence block (the name a domain's history is held under until `era.rename_domain`).
10
+ # These are storage facts, so the world says them and the bluebook does not. The bluebook's
11
+ # `formerly_known_as` still works as a fallback; it warns once, naming the replacement,
12
+ # and must agree with the world when both are given.
13
+ module WorldNames
14
+ PERSISTENCE_VERB = "persisted_by".freeze
15
+
16
+ # Applies each domain's world names to its loaded bluebook, then records the names each
17
+ # renamed aggregate's rows may sit under. Safe to call again: the result is the same and
18
+ # the warning is not repeated.
19
+ #
20
+ # @return [Registry] self
21
+ # @raise [WiringError] naming the aggregate or domain when the world and the bluebook
22
+ # disagree, or `stored_as` names an aggregate the domain does not declare
23
+ def apply_world_names!
24
+ bluebooks.each_value do |bluebook|
25
+ world = world(bluebook.name)
26
+ apply_stored_as!(bluebook, world)
27
+ apply_formerly!(bluebook, world)
28
+ bluebook.aggregates.each { |aggregate| record_prior_names(bluebook, aggregate) }
29
+ end
30
+ self
31
+ end
32
+
33
+ private
34
+
35
+ def apply_stored_as!(bluebook, world)
36
+ given = world ? world.for_verb("stored_as").except(:adapter) : {}
37
+ given.each { |name, table| adopt_stored_as!(bluebook, name.to_s, table.to_s) }
38
+ end
39
+
40
+ def adopt_stored_as!(bluebook, name, table)
41
+ aggregate = bluebook.aggregate(name) ||
42
+ raise(WiringError, "stored_as names #{name}, but #{bluebook.name} declares no such aggregate")
43
+ former = aggregate.former_name
44
+ if former && Naming.snake(former) != Naming.snake(table)
45
+ raise WiringError, "#{bluebook.name} #{name} is stored_as #{table.inspect} in the world but " \
46
+ "formerly_known_as #{former.inspect} in the bluebook: they name different tables. " \
47
+ "Keep the world's line and remove the bluebook's."
48
+ end
49
+ aggregate.stored_as = table
50
+ end
51
+
52
+ def apply_formerly!(bluebook, world)
53
+ named = formerly_in(world)
54
+ return unless named
55
+
56
+ declared = bluebook.formerly_known_as
57
+ if declared && declared != named
58
+ raise WiringError, "#{bluebook.name} is formerly #{named.inspect} in the world but " \
59
+ "formerly_known_as #{declared.inspect} in the bluebook: they name different domains. " \
60
+ "Keep the world's line and remove the bluebook's."
61
+ end
62
+ bluebook.formerly_known_as = named
63
+ end
64
+
65
+ def formerly_in(world)
66
+ return nil unless world
67
+
68
+ persistence_settings(world).filter_map { |settings| settings[:formerly]&.to_s }.first
69
+ end
70
+
71
+ def persistence_settings(world)
72
+ world.settings.select { |key, _| key == PERSISTENCE_VERB || key.start_with?("#{PERSISTENCE_VERB}:") }.values
73
+ end
74
+
75
+ def record_prior_names(bluebook, aggregate)
76
+ aggregate.prior_storage_names = [aggregate.former_name, *renamed_from(bluebook, aggregate)].compact.uniq
77
+ warn_formerly_known_as(bluebook, aggregate)
78
+ end
79
+
80
+ def renamed_from(bluebook, aggregate)
81
+ edges = translations.select { |edge| edge.domain == bluebook.name }
82
+ edges.filter_map { |edge| edge.for_aggregate(aggregate.name)&.was }
83
+ end
84
+
85
+ def warn_formerly_known_as(bluebook, aggregate)
86
+ former = aggregate.former_name
87
+ return unless former
88
+
89
+ Deprecation.once([bluebook.name, aggregate.name], deprecation_text(bluebook, aggregate, former))
90
+ end
91
+
92
+ def deprecation_text(bluebook, aggregate, former)
93
+ "[hecks] #{bluebook.name} #{aggregate.name}: `formerly_known_as #{former.inspect}` is deprecated. " \
94
+ "Say it in the world: `stored_as #{aggregate.name}: #{Naming.snake(former).inspect}`."
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -7,6 +7,7 @@ require_relative "registry/read_repository"
7
7
  require_relative "registry/verification"
8
8
  require_relative "registry/saga_persistence"
9
9
  require_relative "registry/world_defaults"
10
+ require_relative "registry/world_names"
10
11
  require_relative "registry/context_maps"
11
12
  require_relative "registry/adapter_capabilities"
12
13
  require_relative "outbox"
@@ -26,6 +27,7 @@ module Hecks
26
27
  include Verification
27
28
  include SagaPersistence
28
29
  include WorldDefaults
30
+ include WorldNames
29
31
  include AdapterCapabilities
30
32
  include Providers
31
33
  include Merging
@@ -35,6 +37,11 @@ module Hecks
35
37
  # The thread-local key under which open reaction collections are kept.
36
38
  REACTION_SINKS = :hecks_reaction_sinks
37
39
 
40
+ # Guards every registry's reaction log and its outcome index, which dispatching threads all
41
+ # append to. One lock serves every registry: each hold is a single append, so the contention
42
+ # is negligible.
43
+ REACTION_LOCK = Mutex.new
44
+
38
45
  attr_reader :root, :saga_mutex
39
46
 
40
47
  # What a boot gathers, and what a dispatch produces; each is held by `Declarations` or
@@ -51,7 +58,8 @@ module Hecks
51
58
  @root = root
52
59
  # Recorded at hecksagon-build time (AggregateModule#mark_sensitive), Loader.boot's
53
60
  # post-dispatch step turns each pending privacy marking into a real Privacy::Marking.Mark,
54
- # idempotently. `resolved_eras` and `superseded_eras` are eager, not lazy, so no two
61
+ # idempotently. `resolved_eras`, `superseded_eras` and `unminted_eras` are eager, not lazy,
62
+ # so no two
55
63
  # dispatching threads race to create them; all writes still happen at boot,
56
64
  # single-threaded (EraResolver.check!).
57
65
  @declared = Declarations.empty
@@ -62,6 +70,7 @@ module Hecks
62
70
  @saga_mutex = Mutex.new
63
71
  @repositories = {}
64
72
  @projection_repositories = {}
73
+ @saga_persistence = {}
65
74
  # Eager: CapabilityGraph.new only stores the registry reference, and eager
66
75
  # construction avoids the same first-access race as `resolved_eras` while
67
76
  # keeping one instance per registry.
@@ -69,7 +78,6 @@ module Hecks
69
78
  # Guards only the lazy per-domain resolution inside @saga_persistence. Must not reuse
70
79
  # @saga_mutex: checkpoint calls saga_persistence(domain) from inside
71
80
  # @saga_mutex.synchronize, and Mutex is not reentrant.
72
- @saga_persistence = {}
73
81
  @saga_persistence_mutex = Mutex.new
74
82
  @outbox = Outbox::Relay.new(self)
75
83
  end
@@ -95,12 +103,11 @@ module Hecks
95
103
  # Boot-time-only, single-threaded: every add_* below runs from Hecks.collect while a
96
104
  # .bluebook/.hecksagon/.world file is being Kernel.loaded, strictly during Loader.boot,
97
105
  # before dispatcher_for hands this registry to a live, multi-threaded caller.
98
- # rubocop:disable Hecks/ThreadSharedIvarMutation
99
106
  # Registers a loaded bluebook, keyed by its own declared name.
100
107
  #
101
108
  # @param item [Bluebook::Declaration] the loaded, judged bluebook
102
109
  # @return [Bluebook::Declaration] `item`, unchanged
103
- def add_bluebook(item) = @declared.bluebooks[item.name] = item
110
+ def add_bluebook(item) = @declared.store(:bluebooks, item.name, item)
104
111
 
105
112
  # Drops a bluebook and the open builder and source record that accumulated it, so the
106
113
  # bluebook can be loaded again from nothing.
@@ -108,9 +115,9 @@ module Hecks
108
115
  # @param name [String, Symbol] the bluebook name to forget
109
116
  # @return [void]
110
117
  def forget_bluebook(name)
111
- @declared.bluebooks.delete(name.to_s)
112
- @declared.bluebook_builders.delete(name.to_s)
113
- @declared.bluebook_sources.delete(name.to_s)
118
+ @declared.remove(:bluebooks, name.to_s)
119
+ @declared.remove(:bluebook_builders, name.to_s)
120
+ @declared.remove(:bluebook_sources, name.to_s)
114
121
  end
115
122
 
116
123
  # Tracks which .bluebook file(s) contributed to a bluebook name (a boot-time loading
@@ -121,7 +128,7 @@ module Hecks
121
128
  # @param path [String] the `.bluebook` file that declared it
122
129
  # @return [Array<String>] every path recorded for that bluebook, `path` last
123
130
  def record_bluebook_source(name, path)
124
- (@declared.bluebook_sources[name.to_s] ||= []) << path
131
+ @declared.record_source(name.to_s, path)
125
132
  end
126
133
 
127
134
  # Merges into any wiring already registered for the domain rather than replacing it,
@@ -131,7 +138,7 @@ module Hecks
131
138
  # @return [void]
132
139
  def add_hecksagon(item)
133
140
  existing = @declared.hecksagons[item.domain]
134
- @declared.hecksagons[item.domain] = existing ? merge_hecksagons(existing, item) : item
141
+ @declared.store(:hecksagons, item.domain, existing ? merge_hecksagons(existing, item) : item)
135
142
  mark_bounded(item.domain) if item.bounded?
136
143
  end
137
144
 
@@ -143,7 +150,7 @@ module Hecks
143
150
  # @param name [String, Symbol] the bluebook name to mark bounded
144
151
  # @return [void]
145
152
  def mark_bounded(name)
146
- @declared.bounded_bluebooks[name.to_s] = true
153
+ @declared.store(:bounded_bluebooks, name.to_s, true)
147
154
  end
148
155
 
149
156
  # Says whether `name` is a bounded context — attached via `attaches`, or a consumer
@@ -157,13 +164,13 @@ module Hecks
157
164
  #
158
165
  # @param item [Bluebook::Port, Bluebook::DomainPort] the loaded port
159
166
  # @return [Bluebook::Port, Bluebook::DomainPort] `item`, unchanged
160
- def add_port(item) = @declared.ports[item.name] = item
167
+ def add_port(item) = @declared.store(:ports, item.name, item)
161
168
 
162
169
  # Registers a loaded adapter, keyed by its own declared name.
163
170
  #
164
171
  # @param item [Bluebook::Adapter] the loaded, judged adapter
165
172
  # @return [Bluebook::Adapter] `item`, unchanged
166
- def add_adapter(item) = @declared.adapters[item.name] = item
173
+ def add_adapter(item) = @declared.store(:adapters, item.name, item)
167
174
 
168
175
  # Finds the plugin adapters that say they answer a query.
169
176
  #
@@ -182,7 +189,7 @@ module Hecks
182
189
  # @return [void]
183
190
  def add_world(item)
184
191
  existing = @declared.worlds[item.domain]
185
- @declared.worlds[item.domain] = existing ? merge_worlds(existing, item) : item
192
+ @declared.store(:worlds, item.domain, existing ? merge_worlds(existing, item) : item)
186
193
  end
187
194
 
188
195
  # Registers a loaded translation.
@@ -190,7 +197,7 @@ module Hecks
190
197
  # @param item [Bluebook::Translation] the loaded, judged translation
191
198
  # @return [Array<Bluebook::Translation>] every translation registered so far,
192
199
  # `item` last
193
- def add_translation(item) = @declared.translations << item
200
+ def add_translation(item) = @declared.append(:translations, item)
194
201
 
195
202
  # Declares one attribute of a domain's aggregate sensitive, called from a terminal
196
203
  # has_<category>(readable_by:). Recorded, not dispatched: Loader.boot's
@@ -205,15 +212,17 @@ module Hecks
205
212
  # @param readable_by [String] the Governance role a read must hold, unredacted
206
213
  # @return [void]
207
214
  def add_pending_privacy_marking(domain:, attribute_path:, category:, readable_by:)
208
- @declared.pending_privacy_markings << { domain: domain, attribute_path: attribute_path,
209
- category: category, readable_by: readable_by }
215
+ @declared.append(:pending_privacy_markings, { domain: domain, attribute_path: attribute_path,
216
+ category: category, readable_by: readable_by })
210
217
  end
211
- # rubocop:enable Hecks/ThreadSharedIvarMutation
212
218
 
213
219
  # `resolved_eras` is {domain name => era ordinal} resolved by the boot-time era gate;
214
220
  # `superseded_eras` is the domain name -> the ordinal that superseded this boot's own era,
215
- # for an old checkout only. Stood up eagerly; plain readers, not memoizers.
216
- def_delegators :@declared, :resolved_eras, :superseded_eras
221
+ # for an old checkout only. `unminted_eras` is the domain name -> the latest held ordinal, set
222
+ # when this boot's shape matches no held era and no mint was requested: the copy reads and
223
+ # refuses writes. `behind_eras` is the same, for a shape a recorded move or edge leads to from
224
+ # the latest held era. Stood up eagerly; plain readers, not memoizers.
225
+ def_delegators :@declared, :resolved_eras, :superseded_eras, :unminted_eras, :behind_eras
217
226
 
218
227
  # Finds a loaded bluebook by name.
219
228
  #
@@ -278,10 +287,8 @@ module Hecks
278
287
  # @param record [Hash{Symbol => Object}] the reaction's outcome
279
288
  # @param event [String, Integer, nil] identity of the event instance the reaction answered
280
289
  # @return [void]
281
- # rubocop:disable-next Hecks/ThreadSharedIvarMutation
282
290
  def log_reaction(record, event: nil)
283
- @state.reaction_log << record
284
- @state.reaction_events[record] = event if event
291
+ REACTION_LOCK.synchronize { @state.log_reaction(record, event) }
285
292
  Array(Thread.current[REACTION_SINKS]).each { |sink| sink << record }
286
293
  end
287
294
 
@@ -310,16 +317,15 @@ module Hecks
310
317
  # what booting the files produced (bluebooks, hecksagons, ports, adapters, worlds,
311
318
  # resolved eras) untouched.
312
319
  #
313
- # Repositories are dropped, not emptied, so a fresh Memory adapter starts empty while
314
- # a durable one still sees what it persisted. Single-threaded caller only
320
+ # Repositories are dropped from the registry's maps, so a fresh Memory adapter starts empty
321
+ # while a durable one still sees what it persisted. Single-threaded caller only
315
322
  # (Behaviors::Expectations.run_one runs one test at a time).
316
323
  #
317
324
  # @return [Runtime::Registry] self
318
- # rubocop:disable-next Hecks/ThreadSharedIvarMutation
319
325
  def reset_runtime_state!
320
326
  @state.clear
321
- @repositories = {}
322
- @projection_repositories = {}
327
+ @repositories.clear
328
+ @projection_repositories.clear
323
329
  @outbox.clear_log
324
330
  rehydrate_sagas!
325
331
  self
@@ -62,6 +62,8 @@ module Hecks
62
62
  # One try. Answers nil once the compensation has settled (delivered or refused), or the
63
63
  # crash that stopped it.
64
64
  def compensate_once(leg, entry, record)
65
+ return refuse_compensation_at_depth_ceiling(record) if @dispatcher.reaction_depth_reached?
66
+
65
67
  reenter_command(leg, entry[:command_name], entry[:args], explicit: true, source_receiver: nil)
66
68
  @registry.saga_log << record.merge(delivered: true, compensation: true)
67
69
  nil
@@ -73,6 +75,14 @@ module Hecks
73
75
  e
74
76
  end
75
77
 
78
+ # A compensation is a reaction like any other: past the cascade limit it is recorded
79
+ # undelivered, never run.
80
+ def refuse_compensation_at_depth_ceiling(record)
81
+ @registry.saga_log << record.merge(delivered: false, compensation: true, compensation_failed: true,
82
+ reason: "reaction depth #{@dispatcher.max_reaction_depth} reached")
83
+ nil
84
+ end
85
+
76
86
  def log_compensation_retry(record, error, attempt)
77
87
  @registry.saga_log << record.merge(delivered: false, reason: error.message, compensation: true,
78
88
  defect: true, error_class: error.class.name,
@@ -29,10 +29,19 @@ module Hecks
29
29
  # Strings respond to `[]`, so test for Hash/Value explicitly rather than
30
30
  # `respond_to?(:[])`.
31
31
  def payload_correlation(process_manager, event)
32
- path = process_manager.correlates_by.to_s.split(".")
33
- path.reduce(event.payload) do |held, segment|
34
- held.is_a?(Hash) || held.is_a?(Value) ? held[segment.to_sym] : held
32
+ path = own_correlation_path(process_manager, event)
33
+ held = path.reduce(event.payload) do |current, segment|
34
+ current.is_a?(Hash) || current.is_a?(Value) ? current[segment.to_sym] : current
35
35
  end
36
+ sole_field_scalar(held)
37
+ end
38
+
39
+ # A path ending at a single-field value object reads that object's one field, so a bare
40
+ # `Thing.id` keys by the same scalar `Thing.id.value` does.
41
+ def sole_field_scalar(held)
42
+ return held unless held.is_a?(Value)
43
+
44
+ Value.materialize_unwrapped(held)
36
45
  end
37
46
 
38
47
  # The stamp `deliver_saga_dispatch` puts on its own event, for legs whose command
@@ -42,6 +51,19 @@ module Hecks
42
51
  event.correlation && event.correlation[process_manager.correlation_head.to_s]
43
52
  end
44
53
 
54
+ # `Message.id` (what a bare `correlates_by Message` resolves to) names the emitting
55
+ # aggregate's own id: the path is walked without its leading aggregate name.
56
+ def own_correlation_path(process_manager, event)
57
+ path = process_manager.correlates_by.to_s.split(".")
58
+ path.size > 1 && path.first == emitting_aggregate_name(event) ? path.drop(1) : path
59
+ end
60
+
61
+ # The emitting aggregate's bare name, without its domain module.
62
+ def emitting_aggregate_name(event)
63
+ _domain, bare_name = event.aggregate.to_s.split("::", 2)
64
+ bare_name
65
+ end
66
+
45
67
  def self_identified?(process_manager, event)
46
68
  domain, bare_name = event.aggregate.to_s.split("::", 2)
47
69
  return false unless bare_name
@@ -49,6 +71,10 @@ module Hecks
49
71
  construct = @registry.bluebook(domain)&.aggregate(bare_name)
50
72
  return false unless construct
51
73
 
74
+ head, *rest = process_manager.correlates_by.to_s.split(".")
75
+ # The emitting aggregate's own id, spelled with its name: `Message.id`.
76
+ return rest == ["id"] if head == bare_name
77
+
52
78
  construct.identity_heads.map(&:to_s).include?(process_manager.correlation_head.to_s)
53
79
  end
54
80
  end
@@ -17,7 +17,6 @@ module Hecks
17
17
  # Delivers one command a saga leg dispatches: resolves its arguments, logs the inputs they
18
18
  # were bound from, then runs the checkpoint/dispatch/compensation ledger protocol with the
19
19
  # retries a crash gets.
20
- # rubocop:disable-next Metrics/ParameterLists -- spec/runtime/reaction_invocation_spec.rb calls it by name
21
20
  def deliver_saga_dispatch(process_manager, spec, event, instance, correlation, domain, dispatch_key: nil)
22
21
  leg = Leg.new(process_manager, event, domain, correlation, nil, instance)
23
22
  leg.dispatch_key = dispatch_key
@@ -38,7 +38,7 @@ module Hecks
38
38
  end
39
39
 
40
40
  def end_saga(process_manager, event, domain)
41
- return unless event.name == process_manager.ends_on
41
+ return unless process_manager.ending_events.include?(event.name)
42
42
 
43
43
  correlation = saga_correlation(process_manager, event)
44
44
  return if correlation.to_s.empty?
@@ -27,6 +27,11 @@ module Hecks
27
27
  # The trigger lives on the declaration it triggers — see ProcessManager::REFUSED.
28
28
  REFUSED = Bluebook::ProcessManager::REFUSED
29
29
 
30
+ # The state a saga parks in when a stage faults, and the memory key that records the state it
31
+ # faulted from.
32
+ NEEDS_HUMAN = "needs_human".freeze
33
+ FAULTED_FROM_KEY = :__hecks_saga_faulted_from__
34
+
30
35
  # A crash gets this many retries before it's treated as something to
31
36
  # compensate for, instead of unwinding on the first failure.
32
37
  MAX_DEFECT_RETRIES = 3
@@ -54,14 +59,25 @@ module Hecks
54
59
  # @return [Array] the dispatches the taken handler declares
55
60
  def dispatches = handler.dispatches
56
61
 
57
- # Moves the instance into the handler's state, remembering the state it left.
62
+ # Moves the instance into the handler's state, remembering the state it left. A move into
63
+ # `needs_human` also records that state in the instance's memory, so a resume knows the
64
+ # stage that faulted.
58
65
  #
59
66
  # @param leg_handler [Bluebook::ProcessManager::Handler] the leg being taken
60
67
  # @return [void]
61
68
  def take(leg_handler)
62
69
  self.handler = leg_handler
63
70
  self.pre_state = instance[:state]
64
- instance[:state] = leg_handler.to_state
71
+ to_state = leg_handler.to_state
72
+ instance[:state] = to_state
73
+ remember_fault_origin if to_state == NEEDS_HUMAN
74
+ end
75
+
76
+ # Records the state the instance faulted from, under the saga's memory.
77
+ #
78
+ # @return [void]
79
+ def remember_fault_origin
80
+ (instance[:memory] ||= {})[FAULTED_FROM_KEY] = pre_state
65
81
  end
66
82
 
67
83
  # The identity the leg stamps on the dispatch it is delivering.
@@ -114,8 +130,36 @@ module Hecks
114
130
  end
115
131
  end
116
132
 
133
+ # Puts a faulted saga instance back in the stage it faulted from, so the caller can dispatch
134
+ # that stage again with the arguments the saga started with. Dispatches nothing itself.
135
+ #
136
+ # @param domain [String, Symbol] the domain whose saga is resumed
137
+ # @param process_manager [String] the declared saga's name
138
+ # @param correlation [String] the instance's correlation key
139
+ # @return [Hash{Symbol => Object}] `:resumed` true with the `:stage` to dispatch and the
140
+ # saved `:arguments`, or `:resumed` false with a `:reason`
141
+ def resume(domain, process_manager, correlation)
142
+ instance = @registry.saga_instances.dig(process_manager, correlation)
143
+ return { resumed: false, reason: "no saga #{process_manager} with #{correlation}" } unless instance
144
+ unless instance[:state] == NEEDS_HUMAN
145
+ return { resumed: false, reason: "saga is #{instance[:state]}, not #{NEEDS_HUMAN}" }
146
+ end
147
+
148
+ restore_faulted_stage(domain, process_manager, correlation, instance)
149
+ end
150
+
117
151
  private
118
152
 
153
+ # Moves a needs_human instance back to the stage it faulted from, forgets that record, and
154
+ # checkpoints the move.
155
+ def restore_faulted_stage(domain, process_manager, correlation, instance)
156
+ stage = instance[:memory].delete(FAULTED_FROM_KEY)
157
+ instance[:state] = stage
158
+ definition = @registry.bluebook(domain).process_managers.find { |pm| pm.name == process_manager }
159
+ checkpoint(definition, correlation, instance, domain)
160
+ { resumed: true, stage: stage, arguments: instance[:memory].dup }
161
+ end
162
+
119
163
  # Holds `saga_mutex` across both the in-memory mutation and the
120
164
  # persistence write, never just the mutation — otherwise two threads
121
165
  # racing the same (process_manager, correlation) key could interleave
@@ -37,21 +37,49 @@ module Hecks
37
37
  # Coerces `value` for a single, already-resolved `attribute`, branching on
38
38
  # its declared shape (list, reference, composite, or bare scalar).
39
39
  #
40
- # `boundary: false` is the query entry point, where a declared type documents the
41
- # argument for callers/generators rather than naming a shape to enforce.
42
40
  # `argument: true` is the command/entity/port dispatch entry point, where a nil for
43
41
  # a required attribute is a left-empty argument (C3.7), not ordinary state nil.
42
+ # A query's arguments are coerced here too, so a bare scalar of the wrong type refuses
43
+ # for a query exactly as it does for a command.
44
44
  #
45
45
  # @raise [Runtime::TypeMismatch] if `value` cannot be coerced, or a required
46
46
  # reference/attribute is a wrong-shaped value
47
47
  # @raise [Runtime::UnknownArgument] if `value` is a Hash naming an undeclared field
48
48
  # @raise [Runtime::InvariantViolation] if a coerced value object breaks an invariant
49
- def for_attribute(aggregate, attribute, value, boundary: true, argument: false)
49
+ def for_attribute(aggregate, attribute, value, argument: false)
50
50
  return nil_or_missing(aggregate, attribute, value, argument) if attribute.nil? || value.nil?
51
51
  return reference_or_list(aggregate, attribute, value) if attribute.list? || attribute.reference?
52
52
  return value unless aggregate.respond_to?(:value_object)
53
53
 
54
- coerce_scalar(aggregate, attribute, value, boundary)
54
+ coerce_scalar(aggregate, attribute, value)
55
+ end
56
+
57
+ # Refuses a query argument whose bare value does not match its declared scalar type, with
58
+ # the refusal a command argument of that type gets. A nil, a list, a reference and a value
59
+ # object are left to `for_attribute`, which owns their shape.
60
+ #
61
+ # @param aggregate [Bluebook::Aggregate, Bluebook::Entity] the queried construct
62
+ # @param attribute [Bluebook::Attribute] the query's declared argument
63
+ # @param value [Object] the offered value
64
+ # @raise [Runtime::TypeMismatch] if `value` is not of the attribute's declared scalar type
65
+ def check_query_argument!(aggregate, attribute, value)
66
+ return if value.nil? || attribute.list? || attribute.reference?
67
+ return unless aggregate.respond_to?(:value_object) && value_object_for(aggregate, attribute.type).nil?
68
+
69
+ check_bare_primitive(aggregate, attribute, value)
70
+ end
71
+
72
+ # Shape-checks every declared argument of `declared` that `args` offers, before any store
73
+ # is read. The Postgres query builder calls it so its own path refuses what the query
74
+ # interpreter refuses.
75
+ #
76
+ # @param aggregate [Bluebook::Aggregate, Bluebook::Entity] the queried construct
77
+ # @param declared [Bluebook::Query] the declared query whose `attributes` are its arguments
78
+ # @param args [Hash{Symbol => Object}] the offered argument values
79
+ # @raise [Runtime::TypeMismatch] if an offered bare scalar does not match its declared type
80
+ def check_query_arguments!(aggregate, declared, args)
81
+ attributes = declared.respond_to?(:attributes) ? declared.attributes : []
82
+ attributes.each { |attribute| check_query_argument!(aggregate, attribute, args[attribute.name.to_sym]) }
55
83
  end
56
84
 
57
85
  # Resolves the value-object class `type` names: `aggregate`'s own
@@ -150,9 +178,9 @@ module Hecks
150
178
  # A bare scalar or a value object. `admits:` is checked here, where the attribute is
151
179
  # known — `build` only sees the value object. Checked after coercion: a scalar arrives
152
180
  # wrapped in its type's own holder, and checking the raw payload would be wrong.
153
- def coerce_scalar(aggregate, attribute, value, boundary)
181
+ def coerce_scalar(aggregate, attribute, value)
154
182
  value_object = value_object_for(aggregate, attribute.type)
155
- return bare_primitive(aggregate, attribute, value, boundary) if value_object.nil?
183
+ return bare_primitive(aggregate, attribute, value) if value_object.nil?
156
184
 
157
185
  coerced = if value.is_a?(self) && value.type_name == value_object.hecks_name
158
186
  value
@@ -195,8 +223,8 @@ module Hecks
195
223
  # A bare primitive is boundary-checked too (C3.8) — wrong-typed input
196
224
  # refuses here as a TypeMismatch, never later as a broken predicate.
197
225
  # Its `admits:` set is still checked, exactly as a value object's is.
198
- def bare_primitive(aggregate, attribute, value, boundary)
199
- check_bare_primitive(aggregate, attribute, value) if boundary
226
+ def bare_primitive(aggregate, attribute, value)
227
+ check_bare_primitive(aggregate, attribute, value)
200
228
  admit_declared_set(aggregate, attribute, value)
201
229
  value
202
230
  end
@@ -5,6 +5,7 @@ require "open3"
5
5
  require_relative "../rust_build"
6
6
  require_relative "native_build"
7
7
  require_relative "conformance/surface"
8
+ require_relative "kernel_input"
8
9
 
9
10
  module Hecks
10
11
  module RustBuild
@@ -49,18 +50,28 @@ module Hecks
49
50
  # The artifact's JSON for the script: live from a binary, or read from a file.
50
51
  def artifact_output(domain, script, other)
51
52
  case other
52
- when "native" then run_binary(native_binary || missing_native!, script)
53
- when "build" then run_binary(built_binary(domain), script)
53
+ when "native" then run_binary(native_binary || missing_native!, kernel_input(domain, script))
54
+ when "build" then run_binary(built_binary(domain), kernel_input(domain, script))
54
55
  when WASM_MODULE then run_wasm(domain, script, other)
55
- when method(:pinned_binary?) then run_binary(other, script)
56
+ when method(:pinned_binary?) then run_binary(other, kernel_input(domain, script))
56
57
  else File.read(other)
57
58
  end
58
59
  end
59
60
 
61
+ # The stdin a compiled artifact reads: the script's steps with the domain's `defaults`,
62
+ # `needs` and `query_needs` tables beside them, as every other conformance caller sends
63
+ # them (`KernelInput`). Without the tables the kernel never answers a fact the declaration
64
+ # `needs`, and a Ruby-filled argument refuses on the Rust side.
65
+ def kernel_input(domain, script)
66
+ input = JSON.parse(File.read(script))
67
+ KernelInput.tables_for(domain).each { |name, table| input[name] = table unless table.empty? }
68
+ JSON.generate(input)
69
+ end
70
+
60
71
  def run_wasm(domain, script, wasm)
61
72
  raise Failure, "#{wasm}: no such file — run hecks build_wasm #{domain} first" unless File.exist?(wasm)
62
73
 
63
- run_process(["wasmtime", "run", wasm], File.read(script))
74
+ run_process(["wasmtime", "run", wasm], kernel_input(domain, script))
64
75
  end
65
76
 
66
77
  # A pinned per-domain binary, as named by a sweep's `replay:` line.
@@ -68,7 +79,7 @@ module Hecks
68
79
  !path.end_with?(".json") && File.file?(path) && File.executable?(path)
69
80
  end
70
81
 
71
- def run_binary(binary, script) = run_process([binary], File.read(script))
82
+ def run_binary(binary, stdin) = run_process([binary], stdin)
72
83
 
73
84
  def run_process(command, stdin_data)
74
85
  stdout, status = Open3.capture2(*command, stdin_data: stdin_data)
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../rust_build"
4
+
5
+ module Hecks
6
+ module RustBuild
7
+ # Builds the `hecks-parse` binary from `rust/parser`, the one the bluebook parser specs run, so
8
+ # they need no hand build to reach it.
9
+ #
10
+ # Parser.call([])
11
+ #
12
+ # Writes `rust/parser/target/debug/hecks-parse`, the path those specs look for.
13
+ module Parser
14
+ module_function
15
+
16
+ # @param _argv [Array<String>] unused: the crate has one build
17
+ # @return [Integer] 0 once the binary is built
18
+ # @raise [Failure] when cargo cannot build it
19
+ def call(_argv)
20
+ RustBuild.command!("cargo", "build", chdir: File.join(RustBuild.rust_dir, "parser"))
21
+ 0
22
+ end
23
+ end
24
+ end
25
+ end