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
@@ -99,14 +99,14 @@ module Hecks
99
99
  [argv.first(split), argv.drop(split + 1).reject { |arg| arg == "--against" }]
100
100
  end
101
101
 
102
- # `hecks project_rust` reads exactly `<name>/bluebook/<name>.bluebook`, so refuse anything
102
+ # `hecks build.project_rust!` reads exactly `<name>/bluebook/<name>.bluebook`, so refuse anything
103
103
  # else early.
104
104
  def refuse_unless_stress_domain_shaped!(path)
105
105
  expected = File.join(path, "bluebook", "#{File.basename(path)}.bluebook")
106
106
  return if File.file?(expected)
107
107
 
108
108
  raise UsageError, "#{path} is not shaped like a stress domain: expected #{expected} to exist " \
109
- "(`<name>/bluebook/<name>.bluebook` — a flat file breaks `hecks project_rust`; " \
109
+ "(`<name>/bluebook/<name>.bluebook` — a flat file breaks `hecks build.project_rust!`; " \
110
110
  "see qa/stress_domains/ledger_ordering/NOTES.md)"
111
111
  end
112
112
 
@@ -121,7 +121,7 @@ module Hecks
121
121
  raise Stopped
122
122
  end
123
123
 
124
- JSON.parse(out).map { |row| row.dig("path", "value") }.compact
124
+ JSON.parse(out).filter_map { |row| row["path"] }
125
125
  end
126
126
 
127
127
  def normalize(path) = File.expand_path(path, @root)
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hecks
4
+ module QualityControlCli
5
+ class QaEventPump
6
+ # The domains the pump reads and reacts for: each name with the directory that boots it. The
7
+ # ledger, `QualityControl`, is the one whose `EventCursor` rows hold the positions.
8
+ class Attached
9
+ # @param root [String] the repository root the default directories are found under
10
+ # @param env [Hash{String => String}] `QA_SWEEP_DOMAIN_DIR` overrides the ledger's directory
11
+ # @param dirs [Hash{String => String}, nil] the directories by domain name, in place of the
12
+ # defaults
13
+ def initialize(root:, env: ENV, dirs: nil)
14
+ @dirs = dirs || default_dirs(root, env)
15
+ @runtimes = {}
16
+ end
17
+
18
+ # @return [Array<String>] the attached domain names, in the order the pump visits them
19
+ def names = @dirs.keys
20
+
21
+ # @param name [String] a domain name
22
+ # @return [Boolean] whether the pump attaches this domain
23
+ def known?(name) = @dirs.key?(name)
24
+
25
+ # @return [Array<Hecks::Registry>] the registries of every domain booted so far this run
26
+ def registries = @runtimes.values.map(&:registry)
27
+
28
+ # @param name [String] an attached domain name
29
+ # @return [String] the directory that boots it
30
+ def dir(name) = @dirs.fetch(name)
31
+
32
+ # @param name [String] an attached domain name
33
+ # @return [Hecks::Runtime::Dispatcher] the domain booted once, and kept for the run
34
+ def runtime(name)
35
+ @runtimes[name] ||= Hecks.boot(dir(name))
36
+ end
37
+
38
+ # Whether a domain booted in this process has already delivered `policy` for `event`. The
39
+ # reaction log keeps the event id each reaction answered, so a second run of the same event
40
+ # in this process is skipped whatever the cursor says.
41
+ #
42
+ # @param event [Hecks::Runtime::Event] the event, with its id
43
+ # @param policy [Hecks::Bluebook::Policy] the policy about to run
44
+ # @return [Boolean] true when a delivered reaction for this event and policy is logged
45
+ def reacted?(event, policy)
46
+ registries.any? do |registry|
47
+ registry.reaction_log.any? do |record|
48
+ record[:delivered] && record[:policy] == policy.name && record[:on] == event.name &&
49
+ registry.reaction_event(record) == event.id
50
+ end
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def default_dirs(root, env)
57
+ {
58
+ "QualityControl" => env.fetch("QA_SWEEP_DOMAIN_DIR", File.join(root, "qa/bluebook")),
59
+ "Fixer" => File.join(root, "lib/hecks/fixer"),
60
+ "Coder" => File.join(root, "lib/hecks/coder"),
61
+ "CiPipeline" => File.join(root, "lib/hecks/ci_pipeline")
62
+ }
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hecks/naming"
4
+
5
+ module Hecks
6
+ module QualityControlCli
7
+ class QaEventPump
8
+ # One attached domain as a consumer: the logs of the domains its hecksagon subscribes to, read
9
+ # past each cursor, with the policies that react to each event run through the domain's own
10
+ # runtime. A subscription to a domain the pump does not attach is named, not read.
11
+ class Consumer
12
+ # @param name [String] the consumer's domain name
13
+ # @param attached [Attached] the attached domains
14
+ # @param cursors [Cursors] where the positions are kept
15
+ # @param reactions [Reactions] where the reactions already made are kept
16
+ def initialize(name, attached:, cursors:, reactions:)
17
+ @name = name
18
+ @attached = attached
19
+ @cursors = cursors
20
+ @reactions = reactions
21
+ @failed = false
22
+ end
23
+
24
+ # @return [Boolean] whether reading or reacting stopped this consumer
25
+ def failed? = @failed
26
+
27
+ # Reads every attached log this consumer subscribes to, and names each subscription it
28
+ # cannot read.
29
+ #
30
+ # @return [Array<String>] one line per reaction and per problem
31
+ def lines
32
+ producers.flat_map { |producer| read(producer) } + unattached
33
+ end
34
+
35
+ private
36
+
37
+ def runtime = @attached.runtime(@name)
38
+
39
+ def subscribed
40
+ (runtime.registry.hecksagon(@name)&.subscriptions || []).filter_map { |event| Naming.qualifier(event) }.uniq
41
+ end
42
+
43
+ def producers = subscribed.select { |domain| @attached.known?(domain) }
44
+
45
+ def unattached
46
+ (subscribed - producers).map { |domain| "#{@name} subscribes to #{domain}, which the pump does not attach" }
47
+ end
48
+
49
+ # Reads one producer's log past this consumer's cursor, reacting to each entry in turn. A
50
+ # stop leaves the cursor on the last entry that was reacted to.
51
+ def read(producer)
52
+ start = @cursors.position(producer, @name)
53
+ entries = Reader.after(@attached.dir(producer), start)[:events]
54
+ entries.each_with_index.flat_map { |entry, index| react(producer, entry, start + index + 1) }
55
+ rescue StandardError => e
56
+ @failed = true
57
+ ["#{@name} <- #{producer}: stopped, #{e.class}: #{e.message}"]
58
+ end
59
+
60
+ # Runs each policy that reacts to the entry and that neither the ledger nor this process
61
+ # holds a reaction for, then moves the cursor past it. A reaction is recorded as soon as
62
+ # its policy answers, before the cursor moves. The reactions and the cursor share one
63
+ # transaction where the ledger's store has one, so a stop between them rolls both back
64
+ # and the rerun repeats both.
65
+ def react(producer, entry, position)
66
+ event = Reader.event(entry)
67
+ @cursors.transaction do
68
+ lines = runtime.outbox.policies_for(event, producer).flat_map do |policy, home|
69
+ next [] if reacted?(event, policy)
70
+
71
+ fire(event, policy, home, producer, position)
72
+ end
73
+ @cursors.advance(producer, @name, position)
74
+ lines
75
+ end
76
+ end
77
+
78
+ # Whether the policy has already reacted to this event: recorded in the ledger by an
79
+ # earlier pass, or delivered in this process by a domain attached here, by either path.
80
+ def reacted?(event, policy)
81
+ @reactions.recorded?(@name, event.id, policy.name) || @attached.reacted?(event, policy)
82
+ end
83
+
84
+ def fire(event, policy, home, producer, position)
85
+ log = runtime.reactions
86
+ before = log.size
87
+ runtime.outbox.react_policy(event, policy: policy, home: home, domain: producer,
88
+ event_uid: "#{producer}##{position}")
89
+ records = log.drop(before)
90
+ @reactions.record(@name, event.id, policy.name) if records.any?
91
+ records.map { |record| describe(record, policy, event, producer) }
92
+ end
93
+
94
+ def describe(record, policy, event, producer)
95
+ label = "#{@name} <- #{producer} #{event.name}: #{policy.name}"
96
+ return "reacted: #{label}" if record[:delivered]
97
+
98
+ "refused: #{label}: #{record[:reason]}"
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hecks
4
+ module QualityControlCli
5
+ class QaEventPump
6
+ # The positions the pump has read to, kept as the ledger's `EventCursor` rows: one per (log,
7
+ # consumer). A row is opened at the start of the log the first time a consumer reads it.
8
+ class Cursors
9
+ # @param runtime [Hecks::Runtime::Dispatcher] the booted ledger the rows live in
10
+ def initialize(runtime)
11
+ @runtime = runtime
12
+ end
13
+
14
+ # @param log [String] the domain whose event log is read
15
+ # @param consumer [String] the domain whose policies react
16
+ # @return [Integer] the count of log entries the consumer has reacted to
17
+ def position(log, consumer)
18
+ row = row_for(key(log, consumer)) || open_row(log, consumer)
19
+ row[:position][:value]
20
+ end
21
+
22
+ # Moves one consumer's cursor past the entries it has reacted to.
23
+ #
24
+ # @param log [String] the domain whose event log was read
25
+ # @param consumer [String] the domain whose policies reacted
26
+ # @param position [Integer] the count of entries now reacted to
27
+ # @return [void]
28
+ def advance(log, consumer, position)
29
+ @runtime.dispatch_flat("QualityControl::EventCursor.Advance", to: key(log, consumer), position: position)
30
+ end
31
+
32
+ # Runs the block in one transaction on the ledger's store where that store has one, so a
33
+ # reaction and the cursor past it commit together or not at all. A store without
34
+ # transactions (Memory) yields, and the reaction log is then the only guard against a rerun.
35
+ #
36
+ # @yield the reaction and the cursor move, as one unit
37
+ # @return [Object] the block's own value
38
+ def transaction(&)
39
+ repository = @runtime.registry.repository("QualityControl", cursor_aggregate)
40
+ repository.respond_to?(:transaction) ? repository.transaction(&) : yield
41
+ end
42
+
43
+ private
44
+
45
+ def cursor_aggregate = ledger_bluebook.aggregates.find { |aggregate| aggregate.hecks_name == "EventCursor" }
46
+
47
+ def ledger_bluebook = @runtime.registry.bluebook("QualityControl")
48
+
49
+ def key(log, consumer) = "#{log}/#{consumer}"
50
+
51
+ def row_for(key) = @runtime.query("QualityControl::EventCursor.All").find { |row| row[:key][:value] == key }
52
+
53
+ def open_row(log, consumer)
54
+ @runtime.dispatch_flat("QualityControl::EventCursor.Start", key: key(log, consumer), log: log, consumer: consumer)
55
+ row_for(key(log, consumer))
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hecks
4
+ module QualityControlCli
5
+ class QaEventPump
6
+ # The reactions the pump has made, kept as the ledger's `EventReaction` rows: one per
7
+ # (consumer, event, policy). The pump asks before it runs a policy, and records the reaction
8
+ # once the policy's command has answered, delivered or refused. The keys are read once, on
9
+ # first use, and kept for the run, so a pass costs one query however many events it reads.
10
+ class Reactions
11
+ # @param runtime [Hecks::Runtime::Dispatcher] the booted ledger the rows live in
12
+ def initialize(runtime)
13
+ @runtime = runtime
14
+ @known = nil
15
+ end
16
+
17
+ # @param consumer [String] the domain whose policy would run
18
+ # @param event_id [String] the id of the event the policy would react to
19
+ # @param policy [String] the policy's name
20
+ # @return [Boolean] whether the ledger already holds this reaction
21
+ def recorded?(consumer, event_id, policy)
22
+ known.include?(key(consumer, event_id, policy))
23
+ end
24
+
25
+ # @param consumer [String] the domain whose policy answered
26
+ # @param event_id [String] the id of the event it answered
27
+ # @param policy [String] the policy's name
28
+ # @return [void]
29
+ def record(consumer, event_id, policy)
30
+ row = key(consumer, event_id, policy)
31
+ @runtime.dispatch_flat("QualityControl::EventReaction.Record", key: row, consumer: consumer,
32
+ event_id: event_id, policy: policy)
33
+ known << row
34
+ end
35
+
36
+ private
37
+
38
+ def known
39
+ @known ||= @runtime.query("QualityControl::EventReaction.All").to_set { |row| row[:key][:value] }
40
+ end
41
+
42
+ def key(consumer, event_id, policy) = "#{consumer}/#{event_id}/#{policy}"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "hecks/hecks/adapters/in_process_boot"
5
+
6
+ module Hecks
7
+ module QualityControlCli
8
+ class QaEventPump
9
+ # Reads a domain's event log past a cursor through the `Operation.Follow` query, and turns
10
+ # each entry back into an event a policy can react to.
11
+ module Reader
12
+ module_function
13
+
14
+ # @param dir [String] the directory of the domain whose log is read
15
+ # @param position [Integer] the count of entries already read
16
+ # @return [Hash] `cursor:` the count now read to, and `events:` the entries past `position`
17
+ # (each with its payload as JSON text, as the query answers it)
18
+ def after(dir, position)
19
+ Hecks::Adapters::InProcessBoot.new.follow(domain: dir, since: position, wait: 0)
20
+ end
21
+
22
+ # @param entry [Hash] one entry the query answered
23
+ # @return [Hecks::Runtime::Event] the event, with its payload parsed back to a hash
24
+ def event(entry)
25
+ Hecks::Runtime::Outbox.event_from(entry.merge("payload" => JSON.parse(entry["payload"])))
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../hecks"
4
+ # The era subsystem does not load with core (ADR 0033); the QualityControl ledger binds it.
5
+ require_relative "../../ports/persistence/plugins/era"
6
+ require_relative "qa_event_pump/attached"
7
+ require_relative "qa_event_pump/cursors"
8
+ require_relative "qa_event_pump/reactions"
9
+ require_relative "qa_event_pump/reader"
10
+ require_relative "qa_event_pump/consumer"
11
+
12
+ module Hecks
13
+ module QualityControlCli
14
+ # The command behind `hecks quality_control event_pump.pump!`: reads each attached domain's
15
+ # event log past its cursor and runs the policies that react to what it reads. A consumer reads
16
+ # the logs its hecksagon subscribes to, and each cursor is one (log, consumer) row of the
17
+ # ledger's `EventCursor`. The pump writes no domain's event log.
18
+ #
19
+ # A policy that has an `EventReaction` row for its event is not run again. A refused reaction is
20
+ # recorded and named, and the cursor moves past it. A cursor does not move for an event whose
21
+ # reaction could not run at all: that consumer stops, and the pump exits 1.
22
+ class QaEventPump
23
+ EXIT_OK = 0
24
+ EXIT_ERROR = 1
25
+
26
+ USAGE = "usage: hecks quality_control event_pump.pump!"
27
+
28
+ # Runs the pump, or prints its usage for `--help`.
29
+ #
30
+ # @param argv [Array<String>] no arguments
31
+ # @param root [String] the repository root the attached domains are found under
32
+ # @param env [Hash{String => String}] `QA_SWEEP_DOMAIN_DIR` picks the ledger's bluebook
33
+ # directory
34
+ # @return [Integer] 0 when every consumer read its logs, 1 when one could not
35
+ # @raise [SystemExit] when given arguments
36
+ def self.call(argv, root:, env: ENV)
37
+ return reject(argv) unless argv.empty?
38
+
39
+ new(root: root, env: env).run
40
+ end
41
+
42
+ # @param argv [Array<String>] the arguments given
43
+ # @return [Integer] 0 for `--help`
44
+ # @raise [SystemExit] for any other argument
45
+ def self.reject(argv)
46
+ return puts(USAGE) && EXIT_OK if %w[-h --help].include?(argv.first)
47
+
48
+ abort "#{USAGE}\nthis command takes no arguments — one pump is always the same pump"
49
+ end
50
+
51
+ # @param root [String] the repository root
52
+ # @param env [Hash{String => String}] the environment the ledger's directory is read from
53
+ # @param attached [Attached, nil] the attached domains; built from `root` and `env` when
54
+ # absent
55
+ def initialize(root:, env: ENV, attached: nil)
56
+ @attached = attached || Attached.new(root: root, env: env)
57
+ end
58
+
59
+ # Runs every consumer once and prints what each reaction did.
60
+ #
61
+ # @return [Integer] 0 or 1, as `call` answers
62
+ def run
63
+ ledger = @attached.runtime("QualityControl")
64
+ cursors = Cursors.new(ledger)
65
+ reactions = Reactions.new(ledger)
66
+ consumers = @attached.names.map do |name|
67
+ Consumer.new(name, attached: @attached, cursors: cursors, reactions: reactions)
68
+ end
69
+ lines = consumers.flat_map(&:lines)
70
+ lines.each { |line| puts line }
71
+ puts "event pump: #{lines.size} line(s) reported"
72
+ consumers.any?(&:failed?) ? EXIT_ERROR : EXIT_OK
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hecks
4
+ module QualityControlCli
5
+ class QaFixMainBug
6
+ # What happens after a fix is committed: the ledger records the investigation and the fix, the branch
7
+ # lands on local main, the ledger records the verification, and main is pushed through the push train.
8
+ # The push runs only after the quick gate is green on main's head, and origin's main is fetched right
9
+ # before it.
10
+ module Publishing
11
+ private
12
+
13
+ # Records where the bug lives and why, before any fix is attempted. Only a logged bug is
14
+ # investigated; a bug already investigated keeps its first note.
15
+ def investigate(row)
16
+ return unless row[:status] == "logged"
17
+
18
+ files = files_of(row)
19
+ ::QualityControl::Bug.find(row[:reference][:value]).investigate!(
20
+ site: { value: files.empty? ? "the quick gate's output" : files.join(", ") },
21
+ cause: { value: "the quick gate's #{check_id(row)} check is red on main" }
22
+ )
23
+ end
24
+
25
+ def stuck(row, reason)
26
+ Outcome.new(EXIT_STUCK,
27
+ "stays a bug: #{reason} (#{row[:reference][:value]}); left investigating for the owner")
28
+ end
29
+
30
+ def land_and_push(row, branch, sha)
31
+ reference = row[:reference][:value]
32
+ bug = ::QualityControl::Bug.find(reference)
33
+ bug.fix!(reference: { value: reference }, commit: { value: sha })
34
+ output, landed = @shell.land(@root, branch)
35
+ return Outcome.new(EXIT_STUCK, "stopped: landing #{branch} was refused: #{output.strip}") unless landed
36
+
37
+ delete_branch(branch)
38
+ bug.verify!(evidence: { value: "quick gate green on #{sha[0, 7]} and landed on local main from #{branch}" })
39
+ push_main(reference)
40
+ end
41
+
42
+ def delete_branch(branch)
43
+ QaMainGate::Worktree.try(@root, "branch", "-d", branch)
44
+ end
45
+
46
+ # @return [Array<QaMainGate::GateRun::Result>] the checks that are red on a commit of main
47
+ def red_at(head)
48
+ QaMainGate::Worktree.with(root: @root, ref: head) { |dir| @gate.run(dir) }.reject(&:passed)
49
+ end
50
+
51
+ def push_main(reference)
52
+ head = QaMainGate::Worktree.git!(@root, "rev-parse", "main")
53
+ reds = red_at(head)
54
+ return unpushed("main at #{head[0, 7]} is red: #{reds.map(&:id).join(", ")}") if reds.any?
55
+
56
+ behind = behind_origin
57
+ return unpushed(behind) if behind
58
+
59
+ output, pushed = @shell.push(@root)
60
+ return Outcome.new(EXIT_OK, "landed and pushed #{reference} (main at #{head[0, 7]})") if pushed
61
+
62
+ unpushed("the push train refused main: #{output.strip}")
63
+ end
64
+
65
+ # Fetches origin's main right before the push. @return [String, nil] why main cannot be pushed as it is
66
+ def behind_origin
67
+ QaMainGate::Worktree.git!(@root, "fetch", "origin", "main")
68
+ return nil if QaMainGate::Worktree.git?(@root, "merge-base", "--is-ancestor", "origin/main", "main")
69
+
70
+ "origin/main has commits local main does not have; pull main first (nothing was pushed)"
71
+ end
72
+
73
+ def unpushed(reason)
74
+ Outcome.new(EXIT_STUCK, "landed, not pushed: #{reason}")
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../hecks"
4
+ # The era subsystem does not load with core (ADR 0033); the QualityControl ledger binds it.
5
+ require_relative "../../ports/persistence/plugins/era"
6
+ require_relative "qa_main_gate/gate_run"
7
+ require_relative "qa_main_gate/worktree"
8
+ require_relative "qa_main_gate/shell"
9
+ require_relative "qa_main_gate/logging"
10
+ require_relative "qa_fix_main_bug/publishing"
11
+
12
+ module Hecks
13
+ module QualityControlCli
14
+ # The command behind `hecks quality_control bug.fix_and_land --bug BUG#n`: takes one self-contained red-main
15
+ # bug through a fix on a fresh branch off main, the quick gate on that exact commit, a landing on local main,
16
+ # and a push through the push train. A bug triaged bigger, or one whose fixer changes nothing or leaves a
17
+ # check red, stops before anything lands and stays open for the owner. Nothing is landed unless the gate is
18
+ # green on the commit, and nothing is pushed unless the gate is green on main's head.
19
+ #
20
+ # Exit 0 when the fix is landed (pushed, or the push's refusal is printed), 1 when refused before any fix,
21
+ # 2 when the fix stays red.
22
+ class QaFixMainBug
23
+ include Publishing
24
+
25
+ EXIT_OK = 0
26
+ EXIT_REFUSED = 1
27
+ EXIT_STUCK = 2
28
+
29
+ # The file a `rubocop` offense line starts with, as `file.rb:12:3: C: ...` prints it.
30
+ RUBOCOP_OFFENSE = /^(\S+\.rb):\d+:\d+:/
31
+
32
+ # The trailer every commit the practice writes carries.
33
+ TRAILER = "Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>"
34
+
35
+ USAGE = "usage: hecks quality_control bug.fix_and_land --bug BUG#n"
36
+
37
+ # The outcome of one bug's attempt.
38
+ #
39
+ # @!attribute [r] code
40
+ # @return [Integer] the exit status this attempt earns
41
+ # @!attribute [r] message
42
+ # @return [String] one line for the report
43
+ Outcome = Struct.new(:code, :message)
44
+
45
+ # A fix attempt that did not produce a green commit.
46
+ Stuck = Struct.new(:reason)
47
+
48
+ # Runs the command.
49
+ #
50
+ # @param argv [Array<String>] `--bug BUG#n`
51
+ # @param root [String] the repository root
52
+ # @param env [Hash{String => String}] `QA_SWEEP_DOMAIN_DIR` picks another ledger
53
+ # @param gate [#run] the quick gate's runner; a spec injects one
54
+ # @param shell [Module] the fixer, landing and push commands; a spec injects one
55
+ # @return [Integer] the exit status
56
+ def self.call(argv, root:, env: ENV, gate: QaMainGate::GateRun, shell: QaMainGate::Shell)
57
+ reference = parse(argv)
58
+ return EXIT_REFUSED unless reference
59
+
60
+ runtime = Hecks.boot(env.fetch("QA_SWEEP_DOMAIN_DIR", File.join(root, "qa/bluebook")))
61
+ outcome = new(runtime: runtime, root: root, gate: gate, shell: shell).fix(reference)
62
+ puts outcome.message
63
+ outcome.code
64
+ end
65
+
66
+ # @return [String, nil] the reference, or nil after printing the usage for bad arguments
67
+ def self.parse(argv)
68
+ index = argv.index("--bug")
69
+ return argv[index + 1] if index && argv[index + 1]
70
+
71
+ warn USAGE
72
+ nil
73
+ end
74
+
75
+ # @param runtime [Object] the booted QualityControl ledger
76
+ # @param root [String] the repository root
77
+ # @param gate [#run] the quick gate's runner
78
+ # @param shell [Module] the fixer, landing and push commands
79
+ def initialize(runtime:, root:, gate:, shell:)
80
+ @runtime = runtime
81
+ @root = root
82
+ @gate = gate
83
+ @shell = shell
84
+ end
85
+
86
+ # @param reference [String] the bug's reference, such as `BUG#12`
87
+ # @return [Outcome] what happened, once, in one line
88
+ def fix(reference)
89
+ row = bug_row(reference)
90
+ refusal = refusal_for(reference, row)
91
+ return Outcome.new(EXIT_REFUSED, "refused: #{refusal}") if refusal
92
+
93
+ attempt(row)
94
+ rescue QaMainGate::Worktree::Failed => e
95
+ Outcome.new(EXIT_STUCK, "stopped: #{e.message}")
96
+ end
97
+
98
+ private
99
+
100
+ def attempt(row)
101
+ branch = branch_for(row[:reference][:value])
102
+ return Outcome.new(EXIT_REFUSED, "refused: branch #{branch} already exists") if branch_exists?(branch)
103
+
104
+ investigate(row)
105
+ outcome = QaMainGate::Worktree.with(root: @root, ref: "main", branch: branch) { |dir| fix_in(dir, row) }
106
+ return stuck(row, outcome.reason) if outcome.is_a?(Stuck)
107
+
108
+ land_and_push(row, branch, outcome)
109
+ end
110
+
111
+ def bug_row(reference)
112
+ @runtime.query("QualityControl::Bug.All").find { |row| row[:reference][:value] == reference }
113
+ end
114
+
115
+ # @return [String, nil] why the bug is not fixed by this command, nil when it may be
116
+ def refusal_for(reference, row)
117
+ return "no such bug #{reference}" unless row
118
+ return "#{reference} is triaged #{row[:disposition][:value]}; a bigger bug is left for the owner" unless
119
+ row[:disposition][:value] == "self_contained"
120
+ return "#{reference} is #{row[:status]}; nothing to fix" unless %w[logged investigating].include?(row[:status])
121
+
122
+ "no mechanical fixer for #{check_id(row)}" unless QaMainGate::Logging::SELF_CONTAINED.include?(check_id(row))
123
+ end
124
+
125
+ # @return [String] the gate check the bug is about, such as `rubocop`
126
+ def check_id(row)
127
+ (row[:name] && row[:name][:value]).to_s.delete_prefix("main-red-").tr("-", "_")
128
+ end
129
+
130
+ # @return [Array<String>] the files the failing check named, from its own output
131
+ def files_of(row)
132
+ row[:demonstration][:value].scan(RUBOCOP_OFFENSE).flatten.uniq
133
+ end
134
+
135
+ def branch_for(reference)
136
+ "qa/red-main-#{reference.downcase.tr("#", "-")}"
137
+ end
138
+
139
+ def branch_exists?(branch)
140
+ QaMainGate::Worktree.git?(@root, "rev-parse", "--verify", "--quiet", "refs/heads/#{branch}")
141
+ end
142
+
143
+ # The fixer runs, then the gate on the exact commit it makes. Returns the commit, or what kept it red.
144
+ def fix_in(dir, row)
145
+ @shell.rubocop(dir, files_of(row))
146
+ return Stuck.new("the fixer changed nothing") unless changed?(dir)
147
+
148
+ sha = commit(dir, row)
149
+ reds = @gate.run(dir).reject(&:passed)
150
+ return sha if reds.empty?
151
+
152
+ Stuck.new("the quick gate is still red on the fix: #{reds.map(&:id).join(", ")}")
153
+ end
154
+
155
+ def changed?(dir)
156
+ !QaMainGate::Worktree.git!(dir, "status", "--porcelain").empty?
157
+ end
158
+
159
+ def commit(dir, row)
160
+ QaMainGate::Worktree.git!(dir, "add", "-A")
161
+ title = "Fix the quick gate on main: #{check_id(row)} (#{row[:reference][:value]})"
162
+ QaMainGate::Worktree.git!(dir, "commit", "-m", title, "-m", TRAILER)
163
+ QaMainGate::Worktree.git!(dir, "rev-parse", "HEAD")
164
+ end
165
+ end
166
+ end
167
+ end
@@ -86,7 +86,7 @@ module Hecks
86
86
 
87
87
  def sync_scratch!
88
88
  FileUtils.mkdir_p(@scratch)
89
- sources = %w[Cargo.toml Cargo.lock src].map { |entry| File.join(@root, "rust", entry) }
89
+ sources = %w[Cargo.toml Cargo.lock src expr].map { |entry| File.join(@root, "rust", entry) }
90
90
  system("rsync", "-a", "--delete", "--exclude", "target", *sources, "#{@scratch}/") or
91
91
  abort "rsync into #{@scratch} failed"
92
92
  end